├── appicon.ico
├── flexiplot.rc
├── images
├── graph.png
├── icon.png
├── 04_maps.png
├── Connect.png
├── list-add.png
├── piechart.ico
├── scatter.png
├── settings.png
├── Disconnect.png
├── edit-clear.png
├── help-about.png
├── kcoloredit.png
├── linechart.ico
├── document-new.png
├── document-save.png
├── transform-move.png
├── view-statistics.png
├── application-exit.png
├── document-save-as.png
├── format-text-bold.png
├── format-text-italic.png
├── system-lock-screen.png
├── utilities-terminal.png
├── window-duplicate.png
├── document-open-folder.png
├── document-open-recent.png
├── media-playback-start.png
├── media-playback-stop.png
├── format-text-underline.png
└── view-split-left-right.png
├── data.qrc
├── widgets
├── abstractwidget.cpp
├── helper.h
├── plotitem.cpp
├── flexipieslice.h
├── plotitem.h
├── abstractwidget.h
├── mapper.h
├── TemplateWidget.cpp
├── flexipieslice.cpp
├── gmapwidget.h
├── helper.cpp
├── mapper.cpp
├── TemplateWidget.h
├── xychartplotitem.h
├── scatterchart.h
├── piechart.h
├── bargraph.h
├── linechart.h
├── mapper.ui
├── gmapwidget.cpp
├── xychartplotitem.cpp
├── linegraph.h
├── piechart.cpp
├── bargraph.cpp
├── plotter.ui
└── linegraph.ui
├── .gitignore
├── aboutdialog.h
├── main.cpp
├── aboutdialog.cpp
├── todo.md
├── index.html
├── settings.h
├── config.h
├── debugtools.h
├── terminal.h
├── icons.qrc
├── main.js
├── config.cpp
├── FlexiPlot.pro
├── README.md
├── mainwindow.h
├── aboutdialog.ui
├── settings.cpp
├── debugtools.cpp
├── terminal.cpp
├── terminal.ui
├── debugtools.ui
├── settings.ui
└── mainwindow.ui
/appicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/appicon.ico
--------------------------------------------------------------------------------
/flexiplot.rc:
--------------------------------------------------------------------------------
1 | IDI_ICON1 ICON DISCARDABLE "appicon.ico"
--------------------------------------------------------------------------------
/images/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/graph.png
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/icon.png
--------------------------------------------------------------------------------
/images/04_maps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/04_maps.png
--------------------------------------------------------------------------------
/images/Connect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/Connect.png
--------------------------------------------------------------------------------
/images/list-add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/list-add.png
--------------------------------------------------------------------------------
/images/piechart.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/piechart.ico
--------------------------------------------------------------------------------
/images/scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/scatter.png
--------------------------------------------------------------------------------
/images/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/settings.png
--------------------------------------------------------------------------------
/images/Disconnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/Disconnect.png
--------------------------------------------------------------------------------
/images/edit-clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/edit-clear.png
--------------------------------------------------------------------------------
/images/help-about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/help-about.png
--------------------------------------------------------------------------------
/images/kcoloredit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/kcoloredit.png
--------------------------------------------------------------------------------
/images/linechart.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/linechart.ico
--------------------------------------------------------------------------------
/images/document-new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/document-new.png
--------------------------------------------------------------------------------
/images/document-save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/document-save.png
--------------------------------------------------------------------------------
/images/transform-move.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/transform-move.png
--------------------------------------------------------------------------------
/images/view-statistics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/view-statistics.png
--------------------------------------------------------------------------------
/images/application-exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/application-exit.png
--------------------------------------------------------------------------------
/images/document-save-as.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/document-save-as.png
--------------------------------------------------------------------------------
/images/format-text-bold.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/format-text-bold.png
--------------------------------------------------------------------------------
/images/format-text-italic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/format-text-italic.png
--------------------------------------------------------------------------------
/images/system-lock-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/system-lock-screen.png
--------------------------------------------------------------------------------
/images/utilities-terminal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/utilities-terminal.png
--------------------------------------------------------------------------------
/images/window-duplicate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/window-duplicate.png
--------------------------------------------------------------------------------
/images/document-open-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/document-open-folder.png
--------------------------------------------------------------------------------
/images/document-open-recent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/document-open-recent.png
--------------------------------------------------------------------------------
/images/media-playback-start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/media-playback-start.png
--------------------------------------------------------------------------------
/images/media-playback-stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/media-playback-stop.png
--------------------------------------------------------------------------------
/images/format-text-underline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/format-text-underline.png
--------------------------------------------------------------------------------
/images/view-split-left-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xcoder123/FlexiPlot/HEAD/images/view-split-left-right.png
--------------------------------------------------------------------------------
/data.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | index.html
4 | main.js
5 |
6 |
7 |
--------------------------------------------------------------------------------
/widgets/abstractwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "abstractwidget.h"
2 |
3 | AbstractWidget::AbstractWidget(QWidget *parent)
4 | :QWidget(parent)
5 | {
6 | }
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user
2 | *.user
3 | SerialPlot.pro.user.15
4 | SerialPlot.pro.user
5 | *.0-pre1
6 | SerialPlot.pro.user.3.2-pre1
7 | *.15
8 | FlexiPlot.pro.user.3.2-pre1
--------------------------------------------------------------------------------
/widgets/helper.h:
--------------------------------------------------------------------------------
1 | #ifndef HELPER_H
2 | #define HELPER_H
3 |
4 | //#include "linegraph.h"
5 | #include "linechart.h"
6 | #include "bargraph.h"
7 | #include "piechart.h"
8 | #include "scatterchart.h"
9 |
10 | class Helper
11 | {
12 | public:
13 | Helper();
14 |
15 | static bool validPacket(QString packet, int type=0);
16 | };
17 |
18 | #endif // HELPER_H
19 |
--------------------------------------------------------------------------------
/aboutdialog.h:
--------------------------------------------------------------------------------
1 | #ifndef ABOUTDIALOG_H
2 | #define ABOUTDIALOG_H
3 |
4 | #include
5 |
6 | namespace Ui {
7 | class AboutDialog;
8 | }
9 |
10 | class AboutDialog : public QDialog
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit AboutDialog(QWidget *parent = 0);
16 | ~AboutDialog();
17 |
18 | private:
19 | Ui::AboutDialog *ui;
20 | };
21 |
22 | #endif // ABOUTDIALOG_H
23 |
--------------------------------------------------------------------------------
/widgets/plotitem.cpp:
--------------------------------------------------------------------------------
1 | #include "plotitem.h"
2 |
3 | PlotItem::PlotItem(QwtPlot *plot, QString name)
4 | {
5 | curve = new QwtPlotCurve(name);
6 |
7 | curve->attach(plot);
8 | this->name = name;
9 | }
10 |
11 | void PlotItem::addData(QPointF p, QColor color)
12 | {
13 | points.push_back(p);
14 | this->color = color;
15 | }
16 |
17 | void PlotItem::deleteFirst()
18 | {
19 | points.takeFirst();
20 | }
21 |
22 | void PlotItem::clear()
23 | {
24 | points.clear();
25 | }
26 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 |
8 | QCoreApplication::setOrganizationName("Morf");
9 | QCoreApplication::setOrganizationDomain("morf.lv");
10 | QCoreApplication::setApplicationName("FlexiPlot");
11 |
12 | MainWindow w;
13 | w.show();
14 |
15 | if(argc > 1)
16 | w.openDash(QString::fromLatin1(argv[1]));
17 |
18 | return a.exec();
19 | }
20 |
--------------------------------------------------------------------------------
/widgets/flexipieslice.h:
--------------------------------------------------------------------------------
1 | #ifndef FLEXIPIESLICE_H
2 | #define FLEXIPIESLICE_H
3 |
4 | #include
5 | #include
6 |
7 | QT_CHARTS_USE_NAMESPACE
8 |
9 | class FlexiPieSlice : public QPieSlice
10 | {
11 | Q_OBJECT
12 |
13 | public:
14 | FlexiPieSlice(QString label, qreal value);
15 | void setExplodeOnHover(bool b) { explodeOnHover = b; }
16 |
17 | public:
18 | QBrush originalBrush();
19 |
20 | public Q_SLOTS:
21 | void showHighlight(bool show);
22 |
23 | private:
24 | QBrush m_originalBrush;
25 | bool explodeOnHover;
26 |
27 | };
28 |
29 | #endif // FLEXIPIESLICE_H
30 |
--------------------------------------------------------------------------------
/widgets/plotitem.h:
--------------------------------------------------------------------------------
1 | #ifndef PLOTITEM_H
2 | #define PLOTITEM_H
3 |
4 | #include
5 | #include
6 |
7 | class PlotItem
8 | {
9 | public:
10 | PlotItem(QwtPlot * plot, QString name);
11 | QwtPlotCurve* getCurve() { return curve; }
12 | void addData(QPointF p, QColor color);
13 | QVector getData() { return points; }
14 | QColor getColor() { return color; }
15 | void deleteFirst();
16 | void clear();
17 |
18 | private:
19 | QwtPlotCurve* curve;
20 | QString name;
21 | QVector points;
22 | QColor color;
23 | };
24 |
25 | #endif // PLOTITEM_H
26 |
--------------------------------------------------------------------------------
/aboutdialog.cpp:
--------------------------------------------------------------------------------
1 | #include "aboutdialog.h"
2 | #include "ui_aboutdialog.h"
3 |
4 | AboutDialog::AboutDialog(QWidget *parent) :
5 | QDialog(parent),
6 | ui(new Ui::AboutDialog)
7 | {
8 | ui->setupUi(this);
9 |
10 |
11 | connect(ui->closeBtn, SIGNAL(clicked(bool)), this, SLOT(close()));
12 |
13 |
14 | ui->basedLbl->setText(QString("Based on Qt %1 ( Build Arch: %2)").arg(QT_VERSION_STR).arg(QSysInfo::buildCpuArchitecture()) );
15 | ui->builtLbl->setText("Built on " + QString::fromLocal8Bit( __DATE__ ) + " " + QString::fromLocal8Bit(__TIME__));
16 | }
17 |
18 | AboutDialog::~AboutDialog()
19 | {
20 | delete ui;
21 | }
22 |
--------------------------------------------------------------------------------
/todo.md:
--------------------------------------------------------------------------------
1 | # TO-DO list
2 |
3 | - Scatter Plot (done)
4 | - Scatter Plot show/hide series
5 | - Line Chart logarithmic axis
6 | - Instructions with Qt Help Assistent
7 | - Languages
8 | - Arduino Library
9 | - Map Widget
10 | - Temperature widget
11 | - Speed-o-meter type widget
12 | - Data Table
13 | - Save dashboard picture
14 | - Save widget picture
15 | - "Are you sure dialog" when closing widget
16 | - Multiple serial ports??? (maybe)
17 | - Line Chart add a margin to calculated range
18 | - Forbid entering whitespace for widget IDs **(Important)**
19 |
20 | ## Future improvements
21 | - Timestamp in Line Charts with QtCharts module (currently impossible, due to Qt limitations)
22 |
23 |
--------------------------------------------------------------------------------
/widgets/abstractwidget.h:
--------------------------------------------------------------------------------
1 | #ifndef ABSTRACTWIDGET_H
2 | #define ABSTRACTWIDGET_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | class AbstractWidget : public QWidget
9 | {
10 | public:
11 | AbstractWidget(QWidget *parent);
12 | virtual void reset() = 0;
13 | virtual void serialPacket(QStringList packet) = 0;
14 | virtual QString getId() = 0;
15 |
16 | virtual int type() const = 0;
17 |
18 | virtual void xmlStream(QXmlStreamWriter *writer) = 0;
19 | virtual void xmlParse(QXmlStreamReader* xml) = 0;
20 |
21 |
22 | public slots:
23 | virtual void setId(QString str) = 0;
24 |
25 | };
26 |
27 | #endif // ABSTRACTWIDGET_H
28 |
--------------------------------------------------------------------------------
/widgets/mapper.h:
--------------------------------------------------------------------------------
1 | #ifndef MAPPER_H
2 | #define MAPPER_H
3 |
4 | #include
5 | #include "abstractwidget.h"
6 | #include "config.h"
7 |
8 |
9 | namespace Ui {
10 | class Mapper;
11 | }
12 |
13 | class Mapper : public AbstractWidget
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit Mapper(QWidget *parent = 0);
19 | ~Mapper();
20 |
21 | void reset();
22 | void serialPacket(QStringList packet);
23 | QString getId();
24 |
25 | void xmlStream(QXmlStreamWriter *writer);
26 | void xmlParse(QXmlStreamReader* xml);
27 |
28 | public slots:
29 | void setId(QString str);
30 |
31 | private:
32 | Ui::Mapper *ui;
33 |
34 | QString id;
35 | };
36 |
37 | #endif // MAPPER_H
38 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
17 |
18 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/widgets/TemplateWidget.cpp:
--------------------------------------------------------------------------------
1 | #include "templatewidget.h"
2 |
3 | TemplateWidget::TemplateWidget(QWidget *parent) :
4 | AbstractWidget(parent)
5 | {
6 | }
7 |
8 | bool TemplateWidget::validPacket(QString packet)
9 | {
10 | return true;
11 | }
12 |
13 | void TemplateWidget::reset()
14 | {
15 |
16 | }
17 |
18 | void TemplateWidget::serialPacket(QStringList packet)
19 | {
20 |
21 | }
22 |
23 | void TemplateWidget::xmlStream(QXmlStreamWriter *writer)
24 | {
25 |
26 | }
27 |
28 | void TemplateWidget::xmlParse(QXmlStreamReader *xml)
29 | {
30 |
31 | }
32 |
33 | void TemplateWidget::setId(QString str)
34 | {
35 | id = str;
36 | }
37 |
38 | void TemplateWidget::setTitle(QString str)
39 | {
40 |
41 | }
42 |
43 |
44 | TemplateWidget::~TemplateWidget()
45 | {
46 | delete ui;
47 | }
48 |
--------------------------------------------------------------------------------
/settings.h:
--------------------------------------------------------------------------------
1 | #ifndef SETTINGS_H
2 | #define SETTINGS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | namespace Ui {
13 | class Settings;
14 | }
15 |
16 | class Settings : public QDialog
17 | {
18 | Q_OBJECT
19 |
20 | public:
21 | explicit Settings(QWidget *parent = 0);
22 | ~Settings();
23 |
24 |
25 | signals:
26 | void settingsChanged();
27 |
28 | private slots:
29 | void loadSettings();
30 | void saveSettings();
31 | void backgroundColor();
32 |
33 |
34 | private:
35 | Ui::Settings *ui;
36 |
37 | QColor currentBackgroundColor;
38 | };
39 |
40 | #endif // SETTINGS_H
41 |
--------------------------------------------------------------------------------
/widgets/flexipieslice.cpp:
--------------------------------------------------------------------------------
1 | #include "flexipieslice.h"
2 |
3 |
4 | QT_CHARTS_USE_NAMESPACE
5 |
6 | FlexiPieSlice::FlexiPieSlice(QString label, qreal value)
7 | : QPieSlice(label, value)
8 | {
9 | connect(this, SIGNAL(hovered(bool)), this, SLOT(showHighlight(bool)));
10 | }
11 |
12 | QBrush FlexiPieSlice::originalBrush()
13 | {
14 | return m_originalBrush;
15 | }
16 |
17 | void FlexiPieSlice::showHighlight(bool show)
18 | {
19 | if (show) {
20 | QBrush brush = this->brush();
21 | m_originalBrush = brush;
22 | brush.setColor(brush.color().lighter());
23 | setBrush(brush);
24 | if(explodeOnHover)
25 | setExploded(true);
26 | } else {
27 | setBrush(m_originalBrush);
28 | if(explodeOnHover)
29 | setExploded(false);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/config.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_H
2 | #define CONFIG_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 |
12 |
13 | class Config : public QObject
14 | {
15 | Q_OBJECT
16 | public:
17 | static Config* getInstance();
18 | void destroyInstance();
19 |
20 | bool getUnsavedChanges();
21 | void setUnsavedChanges(bool bb);
22 |
23 | void setCurrentOpenedFile(QString file) { currentOpenedFile = file; }
24 | QString getCurrentOpenedFile() { return currentOpenedFile; }
25 |
26 | signals:
27 | void savedStatusChanged(bool);
28 |
29 | private:
30 | Config();
31 | static Config* m_pInstance;
32 | bool unsavedChanges;
33 | QReadWriteLock saveChangesMutex;
34 | QString currentOpenedFile;
35 | };
36 |
37 | #endif // CONFIG_H
38 |
--------------------------------------------------------------------------------
/debugtools.h:
--------------------------------------------------------------------------------
1 | #ifndef DEBUGTOOLS_H
2 | #define DEBUGTOOLS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | namespace Ui {
11 | class DebugTools;
12 | }
13 |
14 | class DebugTools : public QDialog
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | explicit DebugTools(QWidget *parent = 0);
20 | ~DebugTools();
21 |
22 | private:
23 | void saveHistory();
24 | void loadHistory();
25 |
26 | private slots:
27 | void sendPacket();
28 | void sentHistoryListItemDoubleClicked();
29 | void sentHistoryListItemClicked();
30 | void clear();
31 |
32 | void exampleItemSelected();
33 |
34 | protected:
35 | bool eventFilter(QObject *obj, QEvent *e);
36 |
37 | signals:
38 | void packetSent(QByteArray packet);
39 |
40 | private:
41 | Ui::DebugTools *ui;
42 | };
43 |
44 | #endif // DEBUGTOOLS_H
45 |
--------------------------------------------------------------------------------
/widgets/gmapwidget.h:
--------------------------------------------------------------------------------
1 | #ifndef GMAPWIDGET_H
2 | #define GMAPWIDGET_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | class GMapWidget : public QWebView
12 | {
13 | Q_OBJECT
14 | public:
15 | explicit GMapWidget(QWidget *parent = 0);
16 |
17 | public slots:
18 | void addMarker(float lat, float lng, QString name);
19 |
20 | void setGMapCenter(const QString &location);
21 | void setGMapCenter(const QPointF &pos);
22 | void setGMapCenter(qreal lat, qreal lng);
23 |
24 | void setGMapZoom(int zoomLevel);
25 |
26 | void loadMap();
27 |
28 | private slots:
29 | void slotNetworkReply(QNetworkReply *reply);
30 | void slotLoadFinished(bool ok);
31 |
32 | private:
33 | void runScript(const QString &script);
34 |
35 | private:
36 | QNetworkAccessManager *m_accessManager;
37 | bool m_initMap;
38 | };
39 |
40 | #endif // GMAPWIDGET_H
41 |
--------------------------------------------------------------------------------
/widgets/helper.cpp:
--------------------------------------------------------------------------------
1 | #include "helper.h"
2 |
3 | Helper::Helper()
4 | {
5 |
6 | }
7 |
8 | bool Helper::validPacket(QString packet, int type)
9 | {
10 | if(packet.isEmpty())
11 | return false;
12 |
13 | if(type == 0) //check for any object
14 | {
15 | return LineChart::validPacket(packet) || BarGraph::validPacket(packet) || PieChart::validPacket(packet)
16 | || ScatterChart::validPacket(packet);
17 | }
18 | else
19 | {
20 | bool packetValid = false;
21 | switch(type) {
22 | case LineChart::Type: packetValid = LineChart::validPacket(packet); break;
23 | case BarGraph::Type: packetValid = BarGraph::validPacket(packet); break;
24 | case PieChart::Type: packetValid = PieChart::validPacket(packet); break;
25 | case ScatterChart::Type: packetValid = ScatterChart::validPacket(packet); break;
26 | default: packetValid = false;
27 | }
28 |
29 | return packetValid;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/terminal.h:
--------------------------------------------------------------------------------
1 | #ifndef TERMINAL_H
2 | #define TERMINAL_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 | #include
11 |
12 | #include
13 |
14 | #include
15 |
16 | #include "widgets/helper.h"
17 |
18 | namespace Ui {
19 | class Terminal;
20 | }
21 |
22 | class Terminal : public QDialog
23 | {
24 | Q_OBJECT
25 |
26 | public:
27 | explicit Terminal(QWidget *parent = 0);
28 | ~Terminal();
29 |
30 | enum DataFinalizeType { NO_LINE_END, NL_END, CR_END, BOTH_NL_CR_END };
31 |
32 | void appendOutput(QByteArray data);
33 | void appendOutput(QString data);
34 |
35 | private:
36 | void saveHistory();
37 | void loadHistory();
38 |
39 | private slots:
40 | void sendInput();
41 | void sentCmdListItemClicked();
42 | void sentCmdListItemDoubleClicked();
43 | void clear();
44 |
45 | protected:
46 | bool eventFilter(QObject *obj, QEvent *e);
47 |
48 | signals:
49 | void writeToSerial(QByteArray data);
50 |
51 | private:
52 | Ui::Terminal *ui;
53 | };
54 |
55 | #endif // TERMINAL_H
56 |
--------------------------------------------------------------------------------
/widgets/mapper.cpp:
--------------------------------------------------------------------------------
1 | #include "mapper.h"
2 | #include "ui_mapper.h"
3 |
4 | Mapper::Mapper(QWidget *parent) :
5 | AbstractWidget(parent),
6 | ui(new Ui::Mapper)
7 | {
8 | ui->setupUi(this);
9 |
10 | connect(ui->locEdit, SIGNAL(textEdited(QString)), ui->mapWidget, SLOT(setGMapCenter(QString)));
11 | }
12 |
13 | void Mapper::reset()
14 | {
15 |
16 | }
17 |
18 | void Mapper::serialPacket(QStringList packet)
19 | {
20 |
21 | }
22 |
23 | QString Mapper::getId()
24 | {
25 | return id;
26 | }
27 |
28 | void Mapper::xmlParse(QXmlStreamReader *xml)
29 | {
30 |
31 | }
32 |
33 | void Mapper::xmlStream(QXmlStreamWriter *writer)
34 | {
35 |
36 | }
37 |
38 | void Mapper::setId(QString str)
39 | {
40 | id = str;
41 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg("Sample map plot").arg(str));
42 | // this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(ui->titleEdit->text()).arg(str));
43 |
44 | // ui->idEdit->blockSignals(true);
45 | // ui->idEdit->setText( str );
46 | // ui->idEdit->blockSignals(false);
47 |
48 | Config::getInstance()->setUnsavedChanges(true);
49 | }
50 |
51 | Mapper::~Mapper()
52 | {
53 | delete ui;
54 | }
55 |
--------------------------------------------------------------------------------
/widgets/TemplateWidget.h:
--------------------------------------------------------------------------------
1 | #ifndef TEMPLATEWIDGET_H
2 | #define TEMPLATEWIDGET_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 |
23 | #include "plotitem.h"
24 | #include "config.h"
25 | #include "abstractwidget.h"
26 |
27 | namespace Ui {
28 | class TemplateWidget;
29 | }
30 |
31 | class TemplateWidget : public AbstractWidget
32 | {
33 | Q_OBJECT
34 |
35 | public:
36 | enum {Type = 3 /* must be unique */ };
37 |
38 | int type() const
39 | {
40 | return Type;
41 | }
42 |
43 | explicit TemplateWidget(QWidget *parent = 0);
44 | ~TemplateWidget();
45 |
46 | void serialPacket(QStringList packet);
47 | QString getId() { return id; }
48 |
49 | void reset();
50 | void xmlStream(QXmlStreamWriter *writer);
51 | void xmlParse(QXmlStreamReader* xml);
52 |
53 | static bool validPacket(QString packet);
54 |
55 | public slots:
56 | void setId(QString str);
57 | void setTitle(QString str);
58 |
59 | private:
60 | QString id;
61 | };
62 |
63 | #endif // TEMPLATEWIDGET_H
64 |
--------------------------------------------------------------------------------
/widgets/xychartplotitem.h:
--------------------------------------------------------------------------------
1 | #ifndef XYCHARTPLOTITEM_H
2 | #define XYCHARTPLOTITEM_H
3 |
4 | #include
5 | #include
6 |
7 | struct xy_items_max_min_values_t {
8 | QPointF maxValues;
9 | QPointF minValues;
10 | };
11 |
12 | class XYChartPlotItem
13 | {
14 | public:
15 | enum UpdateType {
16 | UPDATE_MANUAL, //Points are passed to series only when update() method is invoked
17 | UPDATE_INSTANTLY //Points are instantly passed to the series
18 | };
19 |
20 | public:
21 | XYChartPlotItem(QXYSeries *m_series, QString name, UpdateType updateType = UPDATE_MANUAL);
22 |
23 | void addData(QPointF p);
24 | QVector getData() { return points; }
25 |
26 | void setColor(QColor color);
27 | QColor getColor() { return color; }
28 | bool isColorSet() { return colorIsSet; }
29 |
30 | void deleteFirst();
31 | void clear();
32 |
33 | QXYSeries *series() { return m_series; }
34 |
35 | QPointF maxValues();
36 | QPointF minValues();
37 |
38 | void setSamplingSize(int size) { m_samplingSize = size; }
39 | int samplingSize() { return m_samplingSize; }
40 |
41 | void update();
42 |
43 | static xy_items_max_min_values_t getMaxMinValues(QHash items);
44 |
45 | private:
46 | QString name;
47 | QVector points;
48 | QColor color;
49 | QXYSeries *m_series;
50 |
51 | bool colorIsSet;
52 |
53 | int m_samplingSize;
54 |
55 | UpdateType updateType;
56 |
57 |
58 | };
59 |
60 | #endif // XYCHARTPLOTITEM_H
61 |
--------------------------------------------------------------------------------
/icons.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/icon.png
4 | images/media-playback-start.png
5 | images/media-playback-stop.png
6 | images/Connect.png
7 | images/Disconnect.png
8 | images/settings.png
9 | images/application-exit.png
10 | images/help-about.png
11 | images/list-add.png
12 | images/document-open-folder.png
13 | images/document-save.png
14 | images/document-save-as.png
15 | images/document-new.png
16 | images/kcoloredit.png
17 | images/view-split-left-right.png
18 | images/window-duplicate.png
19 | images/04_maps.png
20 | images/graph.png
21 | images/utilities-terminal.png
22 | images/view-statistics.png
23 | images/transform-move.png
24 | images/system-lock-screen.png
25 | images/format-text-bold.png
26 | images/format-text-italic.png
27 | images/format-text-underline.png
28 | images/piechart.ico
29 | images/linechart.ico
30 | appicon.ico
31 | images/edit-clear.png
32 | images/document-open-recent.png
33 | images/scatter.png
34 |
35 |
36 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | // main var
2 | var map;
3 | var markers = [];
4 | var infowindow = new google.maps.InfoWindow({});
5 |
6 | // main init function
7 | function initialize() {
8 | var myOptions = {
9 | center:new google.maps.LatLng(51.508742,-0.120850),
10 | zoom: 12,
11 | mapTypeId: google.maps.MapTypeId.ROADMAP
12 | };
13 |
14 | map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
15 |
16 | newMarker(37.09024, -95.712891, 'trialhead0');
17 | }
18 |
19 | // custom functions
20 | function setGMapCenter(lat, lng)
21 | {
22 | map.setCenter(new google.maps.LatLng(lat, lng));
23 | }
24 |
25 | function setGMapZoom(zoom)
26 | {
27 | map.setZoom(zoom);
28 | }
29 |
30 |
31 | function newMarker(_lat, _lng, _name)
32 | {
33 | var lat = parseFloat(_lat );
34 | var lng = parseFloat( _lng );
35 | var name = _name;
36 |
37 | var myLatlng = new google.maps.LatLng(lat, lng);
38 |
39 | var contentString = "";
40 |
41 | var marker = new google.maps.Marker({
42 | position: myLatlng,
43 | map: map,
44 | title: "Coordinates: " + lat + " , " + lng + " | Name: " + name
45 | });
46 |
47 | marker['infowindow'] = contentString;
48 |
49 | markers.push( marker );
50 | //marker.setMap(map);
51 |
52 |
53 | google.maps.event.addListener(marker, 'click', function() {
54 | infowindow.setContent(this['infowindow']);
55 | infowindow.open(map, this);
56 | });
57 | }
58 |
--------------------------------------------------------------------------------
/config.cpp:
--------------------------------------------------------------------------------
1 | #include "config.h"
2 |
3 | Config* Config::m_pInstance = NULL;
4 |
5 | /********************************************************************************/
6 | /* Config::Config() */
7 | /********************************************************************************/
8 | Config::Config()
9 | {
10 | unsavedChanges = false;
11 | currentOpenedFile.clear();
12 | }
13 |
14 |
15 | void Config::setUnsavedChanges(bool bb)
16 | {
17 | saveChangesMutex.lockForWrite();
18 | unsavedChanges = bb;
19 | emit savedStatusChanged(bb);
20 | saveChangesMutex.unlock();
21 | }
22 |
23 | bool Config::getUnsavedChanges()
24 | {
25 | saveChangesMutex.lockForRead();
26 | bool res = unsavedChanges;
27 | saveChangesMutex.unlock();
28 | return res;
29 | }
30 |
31 |
32 | /********************************************************************************/
33 | /* Config* Config::getInstance() */
34 | /********************************************************************************/
35 | Config* Config::getInstance()
36 | {
37 | if(NULL== m_pInstance )
38 | {
39 | m_pInstance = new Config();
40 | }
41 | return m_pInstance;
42 | }
43 |
44 | /********************************************************************************/
45 | /* void Config::destroyInstance() */
46 | /********************************************************************************/
47 | void Config::destroyInstance()
48 | {
49 | delete m_pInstance;
50 | m_pInstance = NULL;
51 | }
52 |
53 |
54 |
--------------------------------------------------------------------------------
/FlexiPlot.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2013-10-14T22:48:52
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui serialport printsupport charts opengl
8 | #CONFIG += qwt
9 |
10 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
11 |
12 | TARGET = FlexiPlot
13 | TEMPLATE = app
14 |
15 | RC_FILE = flexiplot.rc
16 |
17 |
18 | SOURCES += main.cpp\
19 | mainwindow.cpp \
20 | # widgets/plotitem.cpp \
21 | settings.cpp \
22 | config.cpp \
23 | #gmapwidget.cpp \
24 | #mapper.cpp \
25 | widgets/abstractwidget.cpp \
26 | terminal.cpp \
27 | widgets/bargraph.cpp \
28 | # widgets/linegraph.cpp \
29 | debugtools.cpp \
30 | widgets/helper.cpp \
31 | widgets/piechart.cpp \
32 | widgets/flexipieslice.cpp \
33 | aboutdialog.cpp \
34 | widgets/linechart.cpp \
35 | widgets/scatterchart.cpp \
36 | widgets/xychartplotitem.cpp
37 |
38 | HEADERS += mainwindow.h \
39 | # widgets/plotitem.h \
40 | settings.h \
41 | config.h \
42 | #gmapwidget.h \
43 | #mapper.h \
44 | widgets/abstractwidget.h \
45 | terminal.h \
46 | widgets/bargraph.h \
47 | # widgets/linegraph.h \
48 | debugtools.h \
49 | widgets/helper.h \
50 | widgets/piechart.h \
51 | widgets/flexipieslice.h \
52 | aboutdialog.h \
53 | widgets/linechart.h \
54 | widgets/scatterchart.h \
55 | widgets/xychartplotitem.h
56 |
57 | FORMS += mainwindow.ui \
58 | settings.ui \
59 | widgets/mapper.ui \
60 | terminal.ui \
61 | widgets/bargraph.ui \
62 | # widgets/linegraph.ui \
63 | debugtools.ui \
64 | widgets/piechart.ui \
65 | aboutdialog.ui \
66 | widgets/linechart.ui \
67 | widgets/scatterchart.ui
68 |
69 | RESOURCES += \
70 | icons.qrc \
71 | data.qrc
72 |
--------------------------------------------------------------------------------
/widgets/scatterchart.h:
--------------------------------------------------------------------------------
1 | #ifndef SCATTERCHART_H
2 | #define SCATTERCHART_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "config.h"
23 | #include "abstractwidget.h"
24 | #include "xychartplotitem.h"
25 |
26 | namespace Ui {
27 | class ScatterChart;
28 | }
29 |
30 | class ScatterChart : public AbstractWidget
31 | {
32 | Q_OBJECT
33 |
34 | public:
35 | enum LegendPosition {POS_TOP, POS_RIGHT, POS_BOTTOM, POS_LEFT, POS_DETACHED };
36 |
37 | enum {Type = 4 /* must be unique */ };
38 |
39 | int type() const
40 | {
41 | return Type;
42 | }
43 |
44 | explicit ScatterChart(QWidget *parent = 0);
45 | ~ScatterChart();
46 |
47 | void serialPacket(QStringList packet);
48 | QString getId() { return id; }
49 |
50 | void reset();
51 | void xmlStream(QXmlStreamWriter *writer);
52 | void xmlParse(QXmlStreamReader* xml);
53 |
54 | static bool validPacket(QString packet);
55 |
56 | public slots:
57 | void setId(QString str);
58 | void setTitle(QString str);
59 | void settingsChanged();
60 | void markerPropertiesChanged();
61 | void samplingSizeChanged(int value);
62 | void openGlStateChanged();
63 |
64 | void plot();
65 | void clear();
66 |
67 | void savePlot();
68 | void startStopPlotting();
69 |
70 | private:
71 | void checkIfAnimationsAllowed();
72 | void updateDetachedLegendLayout();
73 | void blockAllSignals(bool b);
74 |
75 |
76 | private:
77 | Ui::ScatterChart *ui;
78 | QString id;
79 |
80 | QChart *chart;
81 | QHash items;
82 | bool doPlotting;
83 | };
84 |
85 | #endif // SCATTERCHART_H
86 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FlexiPlot
2 |
3 | Simple Qt based plotting tool for micro-controllers
4 |
5 | ## Sending Data to FlexiPlot
6 |
7 | ### Line chart
8 |
9 | Sample data sent from uC to FlexiPlot
10 | Basically, it will send a real time update of two separate data points to flexi for plotting on the same plane with ID "P0"
11 |
12 | ```
13 | {P0|Roll|255,0,0|25|Pitch|0,255,0|56}
14 | ```
15 |
16 | Note a packet consists of
17 | -ID of plot
18 | -Name of real time value (Roll)
19 | -Color in RGB format (Red)
20 | -Value (25)
21 |
22 | -Name of real time value
23 | -Color in RGB format
24 | -Value
25 |
26 | And you can repeat this pattern as much as you like.
27 |
28 | It also supports XY plane plotting. A sample packet for plotting quadratic:
29 |
30 | ```
31 | {P3|Quadratic|255,0,0|-5 25 -4 16 -3 9 -2 4 -1 1 0 0 1 1 2 4 3 9 4 16 5 25}
32 | ```
33 |
34 | ### Bar Graphs
35 |
36 | An example packet for plotting to a bar graph:
37 | Plotting with automatic color assignment
38 | ```
39 | {P0|Jan;Feb;Mar|Jane|25 15 17|John|8 9 23}
40 | ```
41 |
42 | P0 = ID of plot
43 | Jan;Feb:Mar = Are the columns for bar graph
44 | Jane = Is the set name for bar graph, every set expects as many values as columns
45 | 25 15 17 = Values for Jane for columsn Jan, Feb and Mar.
46 | John= Is the set name for bar graph, every set expects as many values as columns
47 | 8 9 23 = Values for John for columsn Jan, Feb and Mar.
48 |
49 | If you want to use custom set of colors, you can just specify them in the packet:
50 | ```
51 | {P0|Jan;Feb;Mar|Jane|255,0,0|25 15 17|John|0,255,0|8 9 23}
52 | ```
53 |
54 |
55 | # Screenshots
56 | 
57 | 
58 | 
59 | 
60 |
--------------------------------------------------------------------------------
/widgets/piechart.h:
--------------------------------------------------------------------------------
1 | #ifndef PIECHART_H
2 | #define PIECHART_H
3 |
4 | /*!
5 | * Packets:
6 | * {P0|Slice 1|255,0,0|value1|Slice 2|0,255,0|value2|Slice 3|0,0,255|value3}
7 | * Example: {P0|Slice 1|255,0,0|10|Slice 2|0,255,0|30|Slice 3|0,0,255|20}
8 | *
9 | *
10 | * Colors should be optional, if no color is specified for set, let QtCharts handle it.
11 | * {P0|Slice 1|value1|Slice 2|value2|Slice 3|value3}
12 | * Example: {P0|Slice 1|10|Slice 2|30|Slice 3|20}
13 | *
14 | */
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 |
27 | #include
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 |
36 | #include "flexipieslice.h"
37 |
38 | #include "config.h"
39 | #include "abstractwidget.h"
40 |
41 | namespace Ui {
42 | class PieChart;
43 | }
44 |
45 | struct pie_chart_plot_item_t {
46 | qreal value;
47 | QString name;
48 | QColor color;
49 | bool colorIsSet;
50 | };
51 |
52 | class PieChart : public AbstractWidget
53 | {
54 | Q_OBJECT
55 |
56 | public:
57 | enum {Type = 3 };
58 |
59 | int type() const
60 | {
61 | return Type;
62 | }
63 |
64 | enum LegendPosition {POS_TOP, POS_RIGHT, POS_BOTTOM, POS_LEFT, POS_DETACHED };
65 |
66 | explicit PieChart(QWidget *parent = 0);
67 | ~PieChart();
68 |
69 | void serialPacket(QStringList packet);
70 | QString getId() { return id; }
71 |
72 | void reset();
73 | void xmlStream(QXmlStreamWriter *writer);
74 | void xmlParse(QXmlStreamReader* xml);
75 |
76 | static bool validPacket(QString packet);
77 |
78 |
79 | public slots:
80 | void setId(QString str);
81 | void setTitle(QString str);
82 | void settingsChanged();
83 |
84 | void plot();
85 |
86 | private:
87 | void updateDetachedLegendLayout();
88 | void blockAllSignals(bool block);
89 |
90 | private:
91 | Ui::PieChart *ui;
92 | QString id;
93 |
94 | QList items;
95 |
96 | QChart *chart;
97 | };
98 |
99 | #endif // PIECHART_H
100 |
--------------------------------------------------------------------------------
/widgets/bargraph.h:
--------------------------------------------------------------------------------
1 | #ifndef BARGRAPH_H
2 | #define BARGRAPH_H
3 |
4 | /*!
5 | * Packets:
6 | * {P0|Column 1;Column 2;Column 3|Set Name 1|255,0,0|val_col1 val_col2 val_col3|Set Name 2|255,0,0|val_col1 val_col2 val_col3}
7 | * Example: {P0|Jan;Feb;Mar|Jane|255,0,0|25 15 17|John|255,0,0|8 9 23}
8 | *
9 | *
10 | * Colors should be optional, if no color is specified for set, let QtCharts handle it.
11 | * {P0|Column 1;Column 2;Column 3|Set Name|val1 val2 val3 val4}
12 | *
13 | */
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 |
25 | #include
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 |
34 | #include "config.h"
35 | #include "abstractwidget.h"
36 |
37 | namespace Ui {
38 | class BarGraph;
39 | }
40 |
41 | struct bar_graph_plot_item_t {
42 | QList values;
43 | QString set_name;
44 | QColor color;
45 | bool colorIsSet;
46 | };
47 |
48 | class BarGraph : public AbstractWidget
49 | {
50 | Q_OBJECT
51 |
52 | public:
53 | enum { Type = 2 };
54 | int type() const
55 | {
56 | return Type;
57 | }
58 |
59 | enum BarChartType {TYPE_NORMAL, TYPE_STACKED, TYPE_PERCENT, TYPE_HORIZONTAL, TYPE_HORIZONTAL_STACKED, TYPE_HORIZONTAL_PERCENT };
60 | enum LegendPosition {POS_TOP, POS_RIGHT, POS_BOTTOM, POS_LEFT, POS_DETACHED };
61 |
62 | explicit BarGraph(QWidget *parent = 0);
63 | ~BarGraph();
64 |
65 | void serialPacket(QStringList packet);
66 | QString getId() { return id; }
67 |
68 | void reset();
69 | void xmlStream(QXmlStreamWriter *writer);
70 | void xmlParse(QXmlStreamReader* xml);
71 |
72 | static bool validPacket(QString packet);
73 |
74 | private:
75 | void updateDetachedLegendLayout();
76 | void blockAllSignals(bool block);
77 |
78 | private slots:
79 | void legendMarkerClicked();
80 |
81 | public slots:
82 | void setId(QString str);
83 | void setTitle(QString str);
84 | void settingsChanged();
85 |
86 | void plot();
87 |
88 |
89 | private:
90 | Ui::BarGraph *ui;
91 | QString id;
92 |
93 | QChart *chart;
94 |
95 | QList items;
96 | QStringList categories;
97 |
98 | bool readyToPlot;
99 | };
100 |
101 | #endif // BARGRAPH_H
102 |
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #define MAX_RECENT_OPEN_MENU_ENTRIES 10
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 |
12 | #include
13 |
14 | #include "settings.h"
15 | #include "config.h"
16 | #include "terminal.h"
17 | #include "widgets/helper.h"
18 | #include "debugtools.h"
19 | #include "aboutdialog.h"
20 |
21 | #include "widgets/abstractwidget.h"
22 | //#include "widgets/linegraph.h"
23 | #include "widgets/bargraph.h"
24 | #include "widgets/piechart.h"
25 | #include "widgets/linechart.h"
26 | #include "widgets/scatterchart.h"
27 | //#include "mapper.h"
28 |
29 | namespace Ui {
30 | class MainWindow;
31 | }
32 |
33 |
34 |
35 |
36 | class MainWindow : public QMainWindow
37 | {
38 | Q_OBJECT
39 |
40 | public:
41 | explicit MainWindow(QWidget *parent = 0);
42 | ~MainWindow();
43 | void readSettings();
44 |
45 | public slots:
46 | void openDash(QString fileName);
47 |
48 | private slots:
49 | void readData();
50 | void sendData(QByteArray data);
51 |
52 | void parseData(QByteArray data);
53 |
54 | void openSerialPort();
55 | void closeSerialPort();
56 |
57 | void addLineGraph();
58 | void addLineChart();
59 | void addBarGraph();
60 | void addPieChart();
61 | void addScatterChart();
62 | void addMap();
63 | void deleteWidget();
64 |
65 | void openSettings();
66 |
67 | void showAbout();
68 |
69 | void newDash();
70 | void normalSave();
71 | void saveAs();
72 | void saveDash(QString fileName);
73 | void openDashDialog();
74 | void unsavedChanges(bool bb);
75 | void settingsChanged();
76 |
77 | void openTerminal();
78 |
79 | void saveSerialSettings();
80 |
81 | void lockStateChanged(bool checked);
82 |
83 | void addToRecentFiles(QString fileName);
84 | void recentFileMenuItemClicked();
85 | void clearRecentFilesMenu();
86 |
87 | private:
88 | void constructRecentFilesMenu();
89 |
90 |
91 | protected:
92 | void closeEvent(QCloseEvent * e);
93 |
94 | private:
95 | Ui::MainWindow *ui;
96 | QSerialPort *serial;
97 | Settings * settings;
98 |
99 | QByteArray allData;
100 |
101 | QList widgets;
102 |
103 | int tick;
104 | int packetsDropped;
105 |
106 | Terminal * terminal;
107 | DebugTools * debugToolsDialog;
108 |
109 | QComboBox * baudrateComboBox;
110 | QComboBox * serialPortComboBox;
111 |
112 | AboutDialog about;
113 |
114 | QStringList recentFiles;
115 | };
116 |
117 | #endif // MAINWINDOW_H
118 |
--------------------------------------------------------------------------------
/widgets/linechart.h:
--------------------------------------------------------------------------------
1 | #ifndef LINECHART_H
2 | #define LINECHART_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 |
24 | #include "config.h"
25 | #include "abstractwidget.h"
26 | #include "xychartplotitem.h"
27 |
28 | #define AUTO_ADD_MARGIN_PERC 1.10 //How much % extra will be added to auto determined axes values
29 |
30 |
31 | namespace Ui {
32 | class LineChart;
33 | }
34 |
35 | //struct line_graph_plot_item_t {
36 | // QList values;
37 | // QString series_name;
38 | // QColor color;
39 | // bool colorIsSet;
40 | //};
41 |
42 |
43 |
44 | class XYChartPlotItem;
45 |
46 | class LineChart : public AbstractWidget
47 | {
48 | Q_OBJECT
49 |
50 | public:
51 | enum {Type = 1 /* must be unique */ };
52 | enum LegendPosition {POS_TOP, POS_RIGHT, POS_BOTTOM, POS_LEFT, POS_DETACHED };
53 |
54 | int type() const
55 | {
56 | return Type;
57 | }
58 |
59 | enum PlotType {PLOT_TIME, PLOT_XY};
60 |
61 | explicit LineChart(QWidget *parent = 0);
62 | ~LineChart();
63 |
64 | void serialPacket(QStringList packet);
65 | QString getId() { return id; }
66 |
67 | void reset();
68 | void xmlStream(QXmlStreamWriter *writer);
69 | void xmlParse(QXmlStreamReader* xml);
70 |
71 | static bool validPacket(QString packet);
72 |
73 | private:
74 | void updateDetachedLegendLayout();
75 |
76 |
77 | public slots:
78 | void setId(QString str);
79 | void setTitle(QString str);
80 | void settingsChanged();
81 |
82 | void plot();
83 |
84 | void clear();
85 |
86 | private slots:
87 | void samplingSizeChanged(int value);
88 | void refreshRateChanged(int value);
89 | void setFileForWriting();
90 | void startStopAutoWriting(bool start);
91 | void startStopPlotting();
92 | void savePlot();
93 | void blockAllSignals(bool block);
94 |
95 | void legendMarkerClicked();
96 | void legendMarkerHovered(bool hovering);
97 |
98 | private:
99 | Ui::LineChart *ui;
100 | QString id;
101 |
102 | QChart *chart;
103 | QHash items;
104 | QTimer* timer;
105 |
106 | QDateTimeAxis *dateAxisX;
107 | QValueAxis* axisY;
108 | QValueAxis *axisX;
109 |
110 | QFile *autoWriteFile;
111 | QTextStream autoWriteStream;
112 |
113 | bool doPlotting;
114 | };
115 |
116 | #endif // LINECHART_H
117 |
--------------------------------------------------------------------------------
/widgets/mapper.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Mapper
4 |
5 |
6 |
7 | 0
8 | 0
9 | 461
10 | 336
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 | :/images/04_maps.png:/images/04_maps.png
19 |
20 |
21 | -
22 |
23 |
24 | 0
25 |
26 |
27 |
28 | Map
29 |
30 |
31 |
-
32 |
33 |
34 | 1
35 |
36 |
37 | <html><head/><body><p align="center"><span style=" font-size:11pt; font-weight:600;">Sample map plot</span></p></body></html>
38 |
39 |
40 |
41 | -
42 |
43 |
-
44 |
45 |
46 | Location:
47 |
48 |
49 |
50 | -
51 |
52 |
53 | Riga, Latvia
54 |
55 |
56 |
57 |
58 |
59 | -
60 |
61 |
62 |
63 | 0
64 | 0
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | Settings
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | GMapWidget
83 | QWidget
84 |
85 | 1
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/widgets/gmapwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "gmapwidget.h"
2 |
3 | #include
4 | #include
5 | #include
6 | //http://qt-project.org/forums/viewthread/12342 <-- Source was downloaded from here, and JUST
7 | // some functionality was added as necessary, but the core is developed by steven.
8 | GMapWidget::GMapWidget(QWidget *parent)
9 | : QWebView(parent)
10 | {
11 | m_accessManager = new QNetworkAccessManager(this);
12 | m_initMap = false;
13 |
14 | connect(m_accessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotNetworkReply(QNetworkReply*)));
15 |
16 | connect(this, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool)));
17 |
18 | load(QUrl("qrc:/index.html"));
19 | }
20 |
21 | void GMapWidget::loadMap()
22 | {
23 | load(QUrl("qrc:/index.html"));
24 |
25 |
26 | }
27 |
28 | // wait till the load finished signal before initializing the map trough javascript functions!
29 | // somethimes the geocoding is faster than the webview can load the google map runtime
30 | void GMapWidget::slotLoadFinished(bool ok)
31 | {
32 | if(!m_initMap && ok) {
33 | m_initMap = true;
34 |
35 | // load a default location on map init
36 | setGMapCenter("Riga, Latvia");
37 | }
38 | }
39 |
40 | // geocode location strings to Latitude / Longitude positions
41 | void GMapWidget::setGMapCenter(const QString &location)
42 | {
43 | QUrl url("http://maps.googleapis.com/maps/api/geocode/xml");
44 |
45 | QUrlQuery q;
46 | q.addQueryItem("address", location);
47 | q.addQueryItem("sensor", "false");
48 |
49 | url.setQuery( q );
50 |
51 | QNetworkRequest request(url);
52 |
53 | m_accessManager->get(request);
54 |
55 |
56 | }
57 |
58 | // overload with QPointF
59 | void GMapWidget::setGMapCenter(const QPointF &pos)
60 | {
61 | setGMapCenter(pos.x(), pos.y());
62 | }
63 |
64 | // overload with qreal
65 | void GMapWidget::setGMapCenter(qreal lat, qreal lng)
66 | {
67 | runScript(QString("setGMapCenter(%1,%2)").arg(lat).arg(lng));
68 | }
69 |
70 | // set a zoom level on the map
71 | void GMapWidget::setGMapZoom(int zoomLevel)
72 | {
73 | runScript(QString("setGMapZoom(%1)").arg(zoomLevel));
74 | }
75 |
76 | void GMapWidget::addMarker(float lat, float lng, QString name)
77 | {
78 | runScript( QString("newMarker(%1,%2,'%3')").arg(lat).arg(lng).arg(name) );
79 | }
80 |
81 | // read out a geocode xml reply from google
82 | void GMapWidget::slotNetworkReply(QNetworkReply *reply)
83 | {
84 | QXmlStreamReader reader(reply->readAll());
85 |
86 | while(!reader.atEnd()) {
87 |
88 | reader.readNext();
89 |
90 | if(reader.name() == "geometry") {
91 |
92 | reader.readNextStartElement();
93 |
94 | if(reader.name() == "location") {
95 |
96 | reader.readNextStartElement();
97 |
98 | if(reader.name() == "lat") {
99 |
100 | QPointF pos;
101 |
102 | pos.setX(reader.readElementText().toFloat());
103 |
104 | reader.readNextStartElement();
105 |
106 | if(reader.name() == "lng") {
107 |
108 | pos.setY(reader.readElementText().toFloat());
109 |
110 | setGMapCenter(pos);
111 |
112 | return;
113 | }
114 | }
115 | }
116 | }
117 | }
118 | }
119 |
120 | // run a javascript function
121 | void GMapWidget::runScript(const QString &script)
122 | {
123 | page()->mainFrame()->evaluateJavaScript(script);
124 | }
125 |
--------------------------------------------------------------------------------
/aboutdialog.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | AboutDialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 435
10 | 240
11 |
12 |
13 |
14 | About
15 |
16 |
17 |
18 | :/images/help-about.png:/images/help-about.png
19 |
20 |
21 |
22 |
23 | 0
24 | 10
25 | 161
26 | 151
27 |
28 |
29 |
30 |
31 |
32 |
33 | :/appicon.ico
34 |
35 |
36 | true
37 |
38 |
39 |
40 |
41 |
42 | 170
43 | 10
44 | 260
45 | 221
46 |
47 |
48 |
49 | -
50 |
51 |
52 | <html><head/><body><p><span style=" font-size:10pt; font-weight:600;">FlexiPlot Alpha 4</span></p></body></html>
53 |
54 |
55 |
56 | -
57 |
58 |
59 | Based on Qt ...
60 |
61 |
62 |
63 | -
64 |
65 |
66 | Built On Jan...
67 |
68 |
69 |
70 | -
71 |
72 |
73 | <html><head/><body><p>Developed by Raivis Strogonovs<br/><a href="https://morf.lv"><span style=" text-decoration: underline; color:#0000ff;">https://morf.lv</span></a><br/></p><p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.</p><p><br/></p></body></html>
74 |
75 |
76 | true
77 |
78 |
79 | true
80 |
81 |
82 |
83 | -
84 |
85 |
-
86 |
87 |
88 | Qt::Horizontal
89 |
90 |
91 |
92 | 40
93 | 20
94 |
95 |
96 |
97 |
98 | -
99 |
100 |
101 | Close
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/settings.cpp:
--------------------------------------------------------------------------------
1 | #include "settings.h"
2 | #include "ui_settings.h"
3 |
4 | Settings::Settings(QWidget *parent) :
5 | QDialog(parent),
6 | ui(new Ui::Settings)
7 | {
8 | ui->setupUi(this);
9 |
10 | QList ports = QSerialPortInfo::availablePorts();
11 |
12 | foreach(QSerialPortInfo port, ports)
13 | ui->serialPort->addItem(port.portName());
14 |
15 | foreach(qint32 baudrate, QSerialPortInfo::standardBaudRates())
16 | ui->baudrate->addItem(QString::number( baudrate ));
17 |
18 |
19 |
20 | connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(saveSettings()));
21 | connect(ui->colorBtn, SIGNAL(clicked(bool)), this, SLOT(backgroundColor()));
22 | loadSettings();
23 | }
24 |
25 | void Settings::backgroundColor()
26 | {
27 | currentBackgroundColor = QColorDialog::getColor(currentBackgroundColor, this);
28 |
29 | if(currentBackgroundColor.isValid())
30 | {
31 | ui->colorBtn->setStyleSheet( "QPushButton { background-color:"+ currentBackgroundColor.name() +";\nborder: 1px solid #000; }" );
32 | }
33 | }
34 |
35 |
36 | //SAves settings in the registry
37 | void Settings::saveSettings()
38 | {
39 | QSettings settings;
40 | settings.setValue( "Serial/port", ui->serialPort->currentText());
41 | settings.setValue( "Serial/baudrate", ui->baudrate->currentText() );
42 | settings.setValue( "Serial/data_bits", ui->dataBits->currentText().toInt() );
43 | settings.setValue( "Serial/flow_control", (QSerialPort::FlowControl) ui->flowControl->currentIndex() );
44 | switch(ui->parity->currentIndex())
45 | {
46 | case 0: settings.setValue( "Serial/parity", QSerialPort::NoParity ); break;
47 | case 1: settings.setValue( "Serial/parity", QSerialPort::EvenParity ); break;
48 | case 2: settings.setValue( "Serial/parity", QSerialPort::OddParity ); break;
49 | case 3: settings.setValue( "Serial/parity", QSerialPort::SpaceParity ); break;
50 | case 4: settings.setValue( "Serial/parity", QSerialPort::MarkParity ); break;
51 | default: ;
52 | }
53 |
54 | switch(ui->stopBits->currentIndex())
55 | {
56 | case 0: settings.setValue( "Serial/stop_bits", QSerialPort::OneStop ); break;
57 | case 1: settings.setValue( "Serial/stop_bits", QSerialPort::OneAndHalfStop ); break;
58 | case 2: settings.setValue( "Serial/stop_bits", QSerialPort::TwoStop ); break;
59 | default: ;
60 | }
61 |
62 | settings.setValue( "UI/tabbed", ui->tabCheckBox->isChecked() );
63 | settings.setValue( "UI/backgroundColor", currentBackgroundColor );
64 |
65 | emit settingsChanged();
66 |
67 | }
68 |
69 | //loads settings from the registry
70 | void Settings::loadSettings()
71 | {
72 | QSettings settings;
73 |
74 | ui->serialPort->setCurrentText( settings.value("Serial/port").toString() );
75 | ui->baudrate->setCurrentText( settings.value("Serial/baudrate").toString() );
76 | ui->dataBits->setCurrentText( QString::number( settings.value("Serial/data_bits").toInt() ) );
77 | ui->flowControl->setCurrentIndex( settings.value("Serial/flow_control").toInt() );
78 | switch( settings.value("Serial/parity").toInt() )
79 | {
80 | case QSerialPort::NoParity: ui->parity->setCurrentIndex(0); break;
81 | case QSerialPort::EvenParity: ui->parity->setCurrentIndex(1); break;
82 | case QSerialPort::OddParity: ui->parity->setCurrentIndex(2); break;
83 | case QSerialPort::SpaceParity: ui->parity->setCurrentIndex(3); break;
84 | case QSerialPort::MarkParity: ui->parity->setCurrentIndex(4); break;
85 | default: ;
86 | }
87 | switch(settings.value("Serial/stop_bits").toInt())
88 | {
89 | case QSerialPort::OneStop: ui->stopBits->setCurrentIndex(0); break;
90 | case QSerialPort::OneAndHalfStop: ui->stopBits->setCurrentIndex(1); break;
91 | case QSerialPort::TwoStop: ui->stopBits->setCurrentIndex(2); break;
92 | default: ;
93 | }
94 |
95 | ui->tabCheckBox->setChecked( settings.value("UI/tabbed").toBool() );
96 |
97 | currentBackgroundColor = QColor( settings.value( "UI/backgroundColor","#a0a0a0" ).toString() );
98 | ui->colorBtn->setStyleSheet( "QPushButton { background-color:"+ currentBackgroundColor.name() +";\nborder: 1px solid #000; }" );
99 |
100 | }
101 |
102 | Settings::~Settings()
103 | {
104 | delete ui;
105 | }
106 |
--------------------------------------------------------------------------------
/debugtools.cpp:
--------------------------------------------------------------------------------
1 | #include "debugtools.h"
2 | #include "ui_debugtools.h"
3 |
4 | DebugTools::DebugTools(QWidget *parent) :
5 | QDialog(parent),
6 | ui(new Ui::DebugTools)
7 | {
8 | ui->setupUi(this);
9 |
10 | connect(ui->sendPacketBtn, SIGNAL(clicked(bool)), this, SLOT(sendPacket()));
11 | connect(ui->historyListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(sentHistoryListItemClicked()));
12 | connect(ui->historyListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(sentHistoryListItemDoubleClicked()));
13 |
14 | connect(ui->clearBtn, SIGNAL(clicked(bool)), this, SLOT(clear()));
15 |
16 | ui->packetLineEdit->installEventFilter( this );
17 |
18 | QList sizes;
19 | sizes << 150 << 50;
20 | ui->splitter->setSizes(sizes);
21 | connect(ui->examplesTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(exampleItemSelected()));
22 |
23 |
24 | loadHistory();
25 |
26 | ui->historyListWidget->scrollToBottom();
27 | ui->historyListWidget->setCurrentRow( ui->historyListWidget->count() - 1 );
28 | }
29 |
30 | void DebugTools::exampleItemSelected()
31 | {
32 | if( ui->examplesTreeWidget->currentItem()->parent() == NULL )
33 | return;
34 |
35 | ui->packetLineEdit->setText( ui->examplesTreeWidget->currentItem()->text(0) );
36 | }
37 |
38 | void DebugTools::saveHistory()
39 | {
40 | QStringList itemListStrList;
41 | for(int i=0; ihistoryListWidget->count(); i++)
42 | itemListStrList << ui->historyListWidget->item(i)->text();
43 |
44 | QSettings settings;
45 | settings.setValue("debug_tools/history", itemListStrList );
46 | }
47 |
48 | void DebugTools::loadHistory()
49 | {
50 | QSettings settings;
51 | QStringList savedHistoryList = settings.value("debug_tools/history", QStringList()).toStringList();
52 | foreach(QString str, savedHistoryList )
53 | ui->historyListWidget->addItem( str );
54 | }
55 |
56 | void DebugTools::clear()
57 | {
58 | qDebug() << "Clearing packet injector history";
59 |
60 | ui->packetLineEdit->clear();
61 | ui->historyListWidget->clear();
62 |
63 | QSettings settings;
64 | settings.setValue("debug_tools/history", QStringList() );
65 | }
66 |
67 | bool DebugTools::eventFilter(QObject *obj, QEvent *e)
68 | {
69 | if(obj == ui->packetLineEdit)
70 | {
71 | if(e->type() == QEvent::KeyPress)
72 | {
73 | QKeyEvent * keyEvent = static_cast(e);
74 | if(keyEvent->key() == Qt::Key_Up)
75 | {
76 | if(ui->historyListWidget->count() > 0)
77 | {
78 | if(ui->packetLineEdit->text().isEmpty() == false && ui->historyListWidget->currentRow() != 0)
79 | {
80 | ui->historyListWidget->setCurrentRow( ui->historyListWidget->currentRow() - 1 );
81 | }
82 | ui->packetLineEdit->setText( ui->historyListWidget->currentItem()->text() );
83 | }
84 | return true;
85 | } else if(keyEvent->key() == Qt::Key_Down)
86 | {
87 | if(ui->historyListWidget->count() > 0)
88 | {
89 | if(ui->packetLineEdit->text().isEmpty() == false && ui->historyListWidget->currentRow() < ui->historyListWidget->count() - 1)
90 | {
91 | ui->historyListWidget->setCurrentRow( ui->historyListWidget->currentRow() + 1 );
92 | }
93 | ui->packetLineEdit->setText( ui->historyListWidget->currentItem()->text() );
94 | }
95 | return true;
96 | }
97 | }
98 | }
99 |
100 | return QDialog::eventFilter( obj, e );
101 | }
102 |
103 | void DebugTools::sentHistoryListItemDoubleClicked()
104 | {
105 | ui->packetLineEdit->setText( ui->historyListWidget->currentItem()->text() );
106 | sendPacket();
107 | }
108 |
109 | void DebugTools::sentHistoryListItemClicked()
110 | {
111 | ui->packetLineEdit->setText( ui->historyListWidget->currentItem()->text() );
112 | }
113 |
114 |
115 | void DebugTools::sendPacket()
116 | {
117 | if(ui->packetLineEdit->text().length() == 0)
118 | return;
119 |
120 | QString packet = ui->packetLineEdit->text();
121 | packet.append("\r\n");
122 |
123 | emit packetSent( packet.toLatin1() );
124 |
125 | if(ui->historyListWidget->count() > 0)
126 | {
127 | if(ui->historyListWidget->item( ui->historyListWidget->count()-1 )->text() != ui->packetLineEdit->text())
128 | ui->historyListWidget->addItem( ui->packetLineEdit->text() );
129 | }
130 | else
131 | ui->historyListWidget->addItem( ui->packetLineEdit->text() );
132 |
133 | ui->historyListWidget->setCurrentRow( ui->historyListWidget->count()-1 );
134 | ui->historyListWidget->scrollToBottom();
135 |
136 | ui->packetLineEdit->clear();
137 |
138 | saveHistory();
139 | }
140 |
141 | DebugTools::~DebugTools()
142 | {
143 | delete ui;
144 | }
145 |
--------------------------------------------------------------------------------
/widgets/xychartplotitem.cpp:
--------------------------------------------------------------------------------
1 | #include "xychartplotitem.h"
2 |
3 |
4 | XYChartPlotItem::XYChartPlotItem(QXYSeries *m_series, QString name, UpdateType updateType )
5 | {
6 | this->m_series = m_series;
7 | this->m_series->setName( name );
8 | colorIsSet = false;
9 | this->name = name;
10 | this->updateType = updateType;
11 |
12 | m_samplingSize = 500;
13 | }
14 |
15 | void XYChartPlotItem::update()
16 | {
17 | m_series->replace( points );
18 | }
19 |
20 | void XYChartPlotItem::addData(QPointF p)
21 | {
22 | switch(updateType)
23 | {
24 | case UPDATE_MANUAL:
25 | // m_series->append( p );
26 | if(m_samplingSize == -1)
27 | {
28 | points.push_back(p);
29 | /*if(points.length() > m_samplingSize)
30 | this->deleteFirst();*/
31 | }
32 | else
33 | {
34 | if (points.count() < m_samplingSize)
35 | {
36 | //This is fine, but it is faster for QtCharts to render if we don't have large numbers
37 | //since RT line chart can't have nice timestamp, there is no reason not to alter X with sample index
38 | // points.push_back( p );
39 |
40 | points.push_back( QPointF(points.length(), p.y()) );
41 | }
42 | else
43 | {
44 | QVector newPoints;
45 | for (int i = 0; i < points.count()-1; i++)
46 | newPoints.append(QPointF(i, points.at(i+1).y()));
47 |
48 | newPoints.push_back( QPointF(m_samplingSize, p.y()) );
49 | points = newPoints;
50 | }
51 | }
52 |
53 | break;
54 |
55 | case UPDATE_INSTANTLY:
56 | points.append(p); //Do we really need this? Maybe for convinience when getting data. Double the memory though
57 | m_series->append(p);
58 | if(m_samplingSize > 0 && m_series->count() > m_samplingSize)
59 | {
60 | this->deleteFirst();
61 | m_series->remove(0);
62 | }
63 | break;
64 |
65 |
66 | default: qWarning() << "Unknown update type";
67 |
68 | }
69 |
70 |
71 | }
72 |
73 | void XYChartPlotItem::setColor(QColor color)
74 | {
75 | m_series->setColor( color );
76 | colorIsSet = true;
77 | this->color = color;
78 | }
79 |
80 | void XYChartPlotItem::deleteFirst()
81 | {
82 | points.takeFirst();
83 | }
84 |
85 | void XYChartPlotItem::clear()
86 | {
87 | points.clear();
88 | }
89 |
90 | QPointF XYChartPlotItem::maxValues()
91 | {
92 | QPointF result;
93 | foreach(QPointF p, points)
94 | {
95 | if(result.isNull())
96 | {
97 | result.setX(p.x());
98 | result.setY(p.y());
99 | }
100 | else
101 | {
102 | if(p.x() > result.x() )
103 | result.setX(p.x());
104 | if(p.y() > result.y() )
105 | result.setY(p.y());
106 | }
107 | }
108 |
109 | return result;
110 | }
111 |
112 | QPointF XYChartPlotItem::minValues()
113 | {
114 | QPointF result;
115 | foreach(QPointF p, points)
116 | {
117 | if(result.isNull())
118 | {
119 | result.setX(p.x());
120 | result.setY(p.y());
121 | }
122 | else
123 | {
124 | if(p.x() < result.x() )
125 | result.setX(p.x());
126 | if(p.y() < result.y() )
127 | result.setY(p.y());
128 | }
129 | }
130 | return result;
131 | }
132 |
133 | xy_items_max_min_values_t XYChartPlotItem::getMaxMinValues(QHash items)
134 | {
135 | xy_items_max_min_values_t result;
136 |
137 | QPointF maxValues;
138 | QPointF minValues;
139 | foreach(QString key, items.keys())
140 | {
141 | XYChartPlotItem * item = items[key];
142 |
143 | if(!item->series()->isVisible())
144 | continue;
145 |
146 | QPointF itemMaxValues = item->maxValues();
147 |
148 | if(maxValues.isNull())
149 | {
150 | maxValues.setX( itemMaxValues.x() );
151 | maxValues.setY( itemMaxValues.y() );
152 | }
153 | else
154 | {
155 | if(itemMaxValues.x() > maxValues.x())
156 | maxValues.setX( itemMaxValues.x() );
157 | if(itemMaxValues.y() > maxValues.y())
158 | maxValues.setY( itemMaxValues.y() );
159 | }
160 |
161 |
162 | QPointF itemMinValues = item->minValues();
163 | if(minValues.isNull())
164 | {
165 | minValues.setX( itemMinValues.x() );
166 | minValues.setY( itemMinValues.y() );
167 | }
168 | else
169 | {
170 | if(itemMinValues.x() < minValues.x())
171 | minValues.setX( itemMinValues.x() );
172 | if(itemMinValues.y() < minValues.y())
173 | minValues.setY( itemMinValues.y() );
174 | }
175 | }
176 |
177 | result.minValues = minValues;
178 | result.maxValues = maxValues;
179 |
180 | return result;
181 | }
182 |
--------------------------------------------------------------------------------
/widgets/linegraph.h:
--------------------------------------------------------------------------------
1 | #ifndef PLOTTER_H
2 | #define PLOTTER_H
3 |
4 |
5 | /*!
6 | * Packets:
7 | *
8 | * Real Time Plotting:
9 | * {P0|Line Name|255,0,0|value|Other Line Name|255,0,0|value}
10 | * Example: Sample real-time packet with 3 curves XYZ
11 | * {P0|X|255,0,0|100|Y|0,255,0|150|Z|0,0,255|200}
12 | *
13 | *
14 | * Sample XY plot (supports only one curve):
15 | * {P0|Some XY plot|255,0,0|1 255 2 200 3 150 4 100}
16 | * {Plot ID|Curve name|Color|X Y X Y X Y X Y.....}
17 | * Note: If for each X value there won't be Y value, the plot will be ignored
18 | *
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 |
31 | #include
32 |
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 |
50 |
51 | #include "plotitem.h"
52 | #include "config.h"
53 | #include "abstractwidget.h"
54 |
55 |
56 | namespace Ui {
57 | class Plotter;
58 | }
59 |
60 | struct graph_t
61 | {
62 | double x;
63 | double y;
64 | QColor color;
65 | QString name;
66 | QTime xT;
67 | };
68 |
69 | class StockTimeScaleDraw;
70 | class PlotPicker;
71 |
72 |
73 | class LineGraph : public AbstractWidget
74 | {
75 | Q_OBJECT
76 |
77 | public:
78 | enum { Type = 1 };
79 | int type() const
80 | {
81 | // Enable the use of qgraphicsitem_cast with this item.
82 | return Type;
83 | }
84 |
85 | enum PlotType {PLOT_TIME, PLOT_XY};
86 |
87 | explicit LineGraph(QWidget *parent = 0);
88 | ~LineGraph();
89 |
90 | void serialPacket(QStringList packet);
91 | QString getId() { return id; }
92 |
93 | void reset();
94 | void xmlStream(QXmlStreamWriter *writer);
95 | void xmlParse(QXmlStreamReader* xml);
96 |
97 | static bool validPacket(QString packet);
98 |
99 | public slots:
100 | void plot();
101 | void legendChecked( const QVariant &, bool on );
102 | void showCurve( QwtPlotItem *item, bool on );
103 | void setId(QString str);
104 | void setTitle(QString str);
105 | void setBuffer(int value);
106 | void setRefreshRate(int ms);
107 | void setDateFormat(QString format);
108 | void setXAxisLabel(QString str);
109 | void setYAxisLabel(QString str);
110 | void typeChanged(int type);
111 | void startStopPlotting();
112 | void settingsChanged();
113 | void openColorDialog();
114 | void savePlot();
115 | void setFileForWriting();
116 | void startStopAutoWriting(bool start);
117 |
118 | private:
119 | Ui::Plotter *ui;
120 |
121 |
122 | QHash plotItems;
123 |
124 | QwtPlotPanner *plotPanner;
125 | QwtPlotMagnifier *plotMagnifier;
126 |
127 | QString id;
128 | QTimer *timer;
129 | double x;
130 | double minX;
131 |
132 | int buffer;
133 |
134 | bool doPlotting;
135 |
136 | PlotPicker *plotPicker;
137 |
138 | QColor currentColor;
139 |
140 | QFile *autoWriteFile;
141 | QTextStream autoWriteStream;
142 | };
143 |
144 |
145 |
146 | class StockTimeScaleDraw: public QwtScaleDraw
147 | {
148 | public:
149 | StockTimeScaleDraw(QString fmt) : format(fmt) { }
150 |
151 | virtual QwtText label(double v) const
152 | {
153 | QDateTime t = QDateTime::fromMSecsSinceEpoch(v);
154 | return t.toString(format);
155 | }
156 | private:
157 | const QString format;
158 | };
159 |
160 | class PlotPicker : QwtPlotPicker
161 | {
162 | public:
163 | PlotPicker( QWidget *canvas, QString format ):
164 | QwtPlotPicker( canvas )
165 | {
166 | setRubberBand( QwtPlotPicker::NoRubberBand );
167 | setTrackerMode( QwtPlotPicker::AlwaysOn );
168 | this->format = format;
169 | this->date = true;
170 |
171 | this->setStateMachine( new QwtPickerClickPointMachine() );
172 |
173 | }
174 |
175 | void setFormat(QString f) { format = f; }
176 | void showDate(bool bb) { date = bb; }
177 |
178 | protected:
179 | virtual QwtText trackerTextF( const QPointF &pos ) const
180 | {
181 |
182 | const QDateTime dt = QwtDate::toDateTime( pos.x() );
183 |
184 | QString s;
185 |
186 | if(date)
187 | {
188 | s += QDateTime::fromMSecsSinceEpoch(pos.x()).toString(format) + " | " + QString::number(pos.y());
189 | }
190 | else
191 | s += QString::number(pos.x()) + " | " + QString::number(pos.y());
192 |
193 | QwtText text( s );
194 | text.setColor( Qt::white );
195 |
196 | QColor c = rubberBandPen().color();
197 | text.setBorderPen( QPen( c ) );
198 | text.setBorderRadius( 2 );
199 | c.setAlpha( 170 );
200 | text.setBackgroundBrush( c );
201 |
202 | return text;
203 | }
204 |
205 |
206 |
207 | private:
208 | QString format;
209 | bool date;
210 | };
211 |
212 |
213 |
214 | #endif // PLOTTER_H
215 |
--------------------------------------------------------------------------------
/terminal.cpp:
--------------------------------------------------------------------------------
1 | #include "terminal.h"
2 | #include "ui_terminal.h"
3 |
4 |
5 | Terminal::Terminal(QWidget *parent) :
6 | QDialog(parent),
7 | ui(new Ui::Terminal)
8 | {
9 | ui->setupUi(this);
10 |
11 | connect(ui->sendBtn, SIGNAL(clicked(bool)), this, SLOT(sendInput()));
12 |
13 | connect(ui->sentCmdList, SIGNAL(clicked(QModelIndex)), this, SLOT(sentCmdListItemClicked()));
14 | connect(ui->sentCmdList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(sentCmdListItemDoubleClicked()));
15 |
16 | ui->cmdEdit->installEventFilter( this );
17 |
18 | connect(ui->clearBtn, SIGNAL(clicked(bool)), this, SLOT(clear()));
19 |
20 | loadHistory();
21 |
22 | ui->sentCmdList->setCurrentRow( ui->sentCmdList->count() - 1 );
23 | }
24 |
25 | void Terminal::saveHistory()
26 | {
27 | QStringList itemListStrList;
28 | for(int i=0; isentCmdList->count(); i++)
29 | itemListStrList << ui->sentCmdList->item(i)->text();
30 |
31 | QSettings settings;
32 | settings.setValue("terminal/history", itemListStrList );
33 | }
34 |
35 | void Terminal::loadHistory()
36 | {
37 | QSettings settings;
38 | QStringList savedHistoryList = settings.value("terminal/history", QStringList()).toStringList();
39 | foreach(QString str, savedHistoryList )
40 | ui->sentCmdList->addItem( str );
41 | }
42 |
43 | void Terminal::clear()
44 | {
45 | ui->cmdEdit->clear();
46 | ui->sentCmdList->clear();
47 | ui->terminalBrowser->clear();
48 |
49 | QSettings settings;
50 | settings.setValue("terminal/history", QStringList() );
51 | }
52 |
53 | bool Terminal::eventFilter(QObject *obj, QEvent *e)
54 | {
55 | if(obj == ui->cmdEdit)
56 | {
57 | if(e->type() == QEvent::KeyPress)
58 | {
59 | QKeyEvent * keyEvent = static_cast(e);
60 | if(keyEvent->key() == Qt::Key_Up)
61 | {
62 | if(ui->sentCmdList->count() > 0)
63 | {
64 | if(ui->cmdEdit->text().isEmpty() == false && ui->sentCmdList->currentRow() != 0)
65 | {
66 | ui->sentCmdList->setCurrentRow( ui->sentCmdList->currentRow() - 1 );
67 | }
68 | ui->cmdEdit->setText( ui->sentCmdList->currentItem()->text() );
69 | }
70 | return true;
71 | } else if(keyEvent->key() == Qt::Key_Down)
72 | {
73 | if(ui->sentCmdList->count() > 0)
74 | {
75 | if(ui->cmdEdit->text().isEmpty() == false && ui->sentCmdList->currentRow() < ui->sentCmdList->count() - 1)
76 | {
77 | ui->sentCmdList->setCurrentRow( ui->sentCmdList->currentRow() + 1 );
78 | }
79 | ui->cmdEdit->setText( ui->sentCmdList->currentItem()->text() );
80 | }
81 | return true;
82 | }
83 | }
84 | }
85 |
86 | return QDialog::eventFilter( obj, e );
87 | }
88 |
89 | void Terminal::sentCmdListItemDoubleClicked()
90 | {
91 | ui->cmdEdit->setText( ui->sentCmdList->currentItem()->text() );
92 | sendInput();
93 | }
94 |
95 | void Terminal::sentCmdListItemClicked()
96 | {
97 | ui->cmdEdit->setText( ui->sentCmdList->currentItem()->text() );
98 | }
99 |
100 | void Terminal::sendInput()
101 | {
102 | if(ui->cmdEdit->text().length() == 0)
103 | return;
104 |
105 | QByteArray dataToSend = ui->cmdEdit->text().toLatin1();
106 |
107 | switch(ui->lineEndCombobox->currentIndex())
108 | {
109 | case NL_END: dataToSend.append('\n'); break;
110 | case CR_END: dataToSend.append('\r'); break;
111 | case BOTH_NL_CR_END: dataToSend.append("\n\r"); break;
112 | default /*NO_END*/: break;
113 | }
114 |
115 | emit writeToSerial( dataToSend );
116 |
117 | if(ui->sentCmdList->count() > 0)
118 | {
119 | if(ui->sentCmdList->item( ui->sentCmdList->count()-1 )->text() != ui->cmdEdit->text())
120 | ui->sentCmdList->addItem( ui->cmdEdit->text() );
121 | }
122 | else
123 | ui->sentCmdList->addItem( ui->cmdEdit->text() );
124 |
125 | ui->sentCmdList->setCurrentRow( ui->sentCmdList->count()-1 );
126 | ui->sentCmdList->scrollToBottom();
127 |
128 | ui->cmdEdit->clear();
129 |
130 | saveHistory();
131 | }
132 |
133 | Terminal::~Terminal()
134 | {
135 | delete ui;
136 | }
137 |
138 | void Terminal::appendOutput(QByteArray data)
139 | {
140 | appendOutput( QString(data) );
141 | }
142 |
143 | void Terminal::appendOutput(QString data)
144 | {
145 | // ui->terminalBrowser->append( data );
146 |
147 | if(ui->filterPlotPacketsCheckBox->isChecked())
148 | {
149 | QString tempStr( data.mid(1,data.size()-4) );
150 |
151 | // QRegExp rx_timeplot("[a-zA-Z0-9]+(\\|[a-zA-Z0-9 ]+\\|\\d{1,3},\\d{1,3},\\d{1,3}\\|(\\-*\\d+(\\.{0,1}\\d+)*|nan|inf))+");
152 | // QRegExp rx_xy_plot("[a-zA-Z0-9]+\\|[a-zA-Z0-9 ]+\\|\\d{1,3},\\d{1,3},\\d{1,3}\\|(\\-*\\d+\\s\\-*\\d+\\s*)+");
153 | if( Helper::validPacket(tempStr) )
154 | {
155 | return;
156 | }
157 | }
158 |
159 | QTextCursor oldCursor = ui->terminalBrowser->textCursor();
160 | int oldScrollValue = ui->terminalBrowser->verticalScrollBar()->value();
161 |
162 |
163 |
164 | if(ui->TimeStampCheckBox->isChecked())
165 | {
166 | ui->terminalBrowser->moveCursor (QTextCursor::End);
167 | ui->terminalBrowser->insertPlainText ( QDateTime::currentDateTime().toString("HH:mm:ss:zzz") + ": \t");
168 | ui->terminalBrowser->moveCursor (QTextCursor::End);
169 | }
170 |
171 | if(ui->hexOutputCheckBox->isChecked())
172 | {
173 | data = QString( data.toLatin1().toHex() ) + "\n";
174 | data = data.toUpper();
175 | for (int i = 2; i <= data.size(); i+=3)
176 | data.insert(i, ' ');
177 | }
178 |
179 | ui->terminalBrowser->moveCursor (QTextCursor::End);
180 | ui->terminalBrowser->insertPlainText (data);
181 | ui->terminalBrowser->moveCursor (QTextCursor::End);
182 |
183 |
184 | if(ui->autoScrollCheckBox->isChecked() == false)
185 | {
186 | ui->terminalBrowser->setTextCursor( oldCursor );
187 | ui->terminalBrowser->verticalScrollBar()->setValue( oldScrollValue );
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/terminal.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Terminal
4 |
5 |
6 |
7 | 0
8 | 0
9 | 595
10 | 551
11 |
12 |
13 |
14 | Terminal
15 |
16 |
17 |
18 | :/images/utilities-terminal.png:/images/utilities-terminal.png
19 |
20 |
21 | -
22 |
23 |
24 | 0
25 |
26 |
-
27 |
28 |
29 | Output:
30 |
31 |
32 |
33 | -
34 |
35 |
36 | Qt::Horizontal
37 |
38 |
39 |
40 | 40
41 | 20
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 | For convinience filters out all the packets sent for plotting. Clears up terminal for easier debugging even while plotting
50 |
51 |
52 | Filter Plotting Packets
53 |
54 |
55 |
56 | -
57 |
58 |
59 | Auto Scroll
60 |
61 |
62 | true
63 |
64 |
65 |
66 |
67 |
68 | -
69 |
70 |
71 | QTextEdit::NoWrap
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 |
81 | -
82 |
83 |
84 | History:
85 |
86 |
87 |
88 | -
89 |
90 |
91 |
92 | 0
93 | 0
94 |
95 |
96 |
97 |
98 | 0
99 | 120
100 |
101 |
102 |
103 |
104 | 16777215
105 | 120
106 |
107 |
108 |
109 |
110 | -
111 |
112 |
113 | 0
114 |
115 |
-
116 |
117 |
118 | Input:
119 |
120 |
121 |
122 | -
123 |
124 |
125 | -
126 |
127 |
128 | Send
129 |
130 |
131 |
132 |
133 |
134 | -
135 |
136 |
137 | 0
138 |
139 |
-
140 |
141 |
142 | Clear
143 |
144 |
145 |
146 | -
147 |
148 |
149 |
150 | 120
151 | 0
152 |
153 |
154 |
-
155 |
156 | No Line Ending
157 |
158 |
159 | -
160 |
161 | Newline
162 |
163 |
164 | -
165 |
166 | Carriage return
167 |
168 |
169 | -
170 |
171 | Both Newline and Carriage Return
172 |
173 |
174 |
175 |
176 | -
177 |
178 |
179 | Qt::Horizontal
180 |
181 |
182 |
183 | 40
184 | 20
185 |
186 |
187 |
188 |
189 | -
190 |
191 |
192 | Hex Output
193 |
194 |
195 |
196 | -
197 |
198 |
199 | Time Stamp
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
--------------------------------------------------------------------------------
/debugtools.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | DebugTools
4 |
5 |
6 |
7 | 0
8 | 0
9 | 704
10 | 406
11 |
12 |
13 |
14 | Debug Tools
15 |
16 |
17 | -
18 |
19 |
20 | Packet Injector
21 |
22 |
23 |
-
24 |
25 |
26 |
27 | 0
28 | 0
29 |
30 |
31 |
32 | Qt::Horizontal
33 |
34 |
35 |
36 |
37 | 0
38 |
39 |
-
40 |
41 |
42 | 0
43 |
44 |
-
45 |
46 |
47 | History:
48 |
49 |
50 |
51 | -
52 |
53 |
54 | Qt::Horizontal
55 |
56 |
57 |
58 | 40
59 | 20
60 |
61 |
62 |
63 |
64 | -
65 |
66 |
67 | Qt::NoFocus
68 |
69 |
70 | Clear
71 |
72 |
73 |
74 |
75 |
76 | -
77 |
78 |
79 |
80 |
81 |
82 |
83 | -
84 |
85 |
86 |
87 | 0
88 | 25
89 |
90 |
91 |
92 | Examples:
93 |
94 |
95 |
96 | -
97 |
98 |
99 |
100 | Packet
101 |
102 |
103 |
-
104 |
105 | Pie Chart
106 |
107 |
108 |
109 | :/images/piechart.ico:/images/piechart.ico
110 |
111 |
-
112 |
113 | {P0|Slice 1|10|Slice 2|30|Slice 3|20}
114 |
115 |
116 | -
117 |
118 | {P0|Slice 1|255,0,0|10.0048|Slice 2|0,255,0|30|Slice 3|0,0,255|20}
119 |
120 |
121 |
122 | -
123 |
124 | Bar Chart
125 |
126 |
127 |
128 | :/images/view-statistics.png:/images/view-statistics.png
129 |
130 |
-
131 |
132 | {P0|Jan;Feb;Mar|Jane|25 15 17|John|8 9 23}
133 |
134 |
135 | -
136 |
137 | {P0|Jan;Feb;Mar|Jane|255,0,0|25 15 17|John|0,255,0|8 9 23}
138 |
139 |
140 |
141 | -
142 |
143 | Line Chart
144 |
145 |
146 |
147 | :/images/linechart.ico:/images/linechart.ico
148 |
149 |
-
150 |
151 | {P0|Quadratic|255,0,0|-5 25 -4 16 -3 9 -2 4 -1 1 0 0 1 1 2 4 3 9 4 16 5 25}
152 |
153 |
154 | -
155 |
156 | {P0|Roll|255,0,0|25|Pitch|0,255,0|56}
157 |
158 |
159 | -
160 |
161 | {P0|Random|1 15 2 8 3 -6 4 15|Quadratic|-5 25 -4 16 -3 9 -2 4 -1 1 0 0 1 1 2 4 3 9 4 16 5 25}
162 |
163 |
164 | -
165 |
166 | {P0|Random|255,0,0|1 15 2 8 3 -6 4 15|Quadratic|0,255,0|-5 25 -4 16 -3 9 -2 4 -1 1 0 0 1 1 2 4 3 9 4 16 5 25}
167 |
168 |
169 |
170 | -
171 |
172 | Scatter Chart
173 |
174 |
175 |
176 | :/images/scatter.png:/images/scatter.png
177 |
178 |
-
179 |
180 | {P0|Random|1 1 2 2 3 3 0 6 5 4 2 3 0.5 9}
181 |
182 |
183 | -
184 |
185 | {P0|Random|255,0,0|1 1 2 2 3 3 0 6 5 4 2 3 0.5 9}
186 |
187 |
188 | -
189 |
190 | {P0|Random|1 1 2 2 3 3 0 6 5 4 2 3 0.5 9|Random2|5 8 6 9 2 2 4 5 6 7 3 1 5 4}
191 |
192 |
193 | -
194 |
195 | {P0|Random|1 1|Random2|5 8}
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | -
206 |
207 |
-
208 |
209 |
210 | Packet:
211 |
212 |
213 |
214 | -
215 |
216 |
217 | {P0|Roll|255,0,0|25}
218 |
219 |
220 |
221 | -
222 |
223 |
224 | Send
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 | packetLineEdit
237 | sendPacketBtn
238 |
239 |
240 |
241 |
242 |
243 |
244 |
--------------------------------------------------------------------------------
/settings.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Settings
4 |
5 |
6 |
7 | 0
8 | 0
9 | 549
10 | 329
11 |
12 |
13 |
14 | Settings
15 |
16 |
17 |
18 | :/images/settings.png:/images/settings.png
19 |
20 |
21 | -
22 |
23 |
24 | Serial
25 |
26 |
27 |
-
28 |
29 |
-
30 |
31 |
32 | Serial Port:
33 |
34 |
35 |
36 | -
37 |
38 |
39 | true
40 |
41 |
42 |
43 |
44 |
45 | -
46 |
47 |
-
48 |
49 |
50 | Baudrate:
51 |
52 |
53 |
54 | -
55 |
56 |
57 | true
58 |
59 |
60 |
61 |
62 |
63 | -
64 |
65 |
66 | 0
67 |
68 |
-
69 |
70 |
71 | Data Bits:
72 |
73 |
74 |
75 | -
76 |
77 |
78 | 3
79 |
80 |
-
81 |
82 | 5
83 |
84 |
85 | -
86 |
87 | 6
88 |
89 |
90 | -
91 |
92 | 7
93 |
94 |
95 | -
96 |
97 | 8
98 |
99 |
100 |
101 |
102 |
103 |
104 | -
105 |
106 |
107 | 0
108 |
109 |
-
110 |
111 |
112 | Flow Control:
113 |
114 |
115 |
116 | -
117 |
118 |
-
119 |
120 | No Flow Control
121 |
122 |
123 | -
124 |
125 | Hardware Flow Control (RTS/CTS)
126 |
127 |
128 | -
129 |
130 | Software Flow Control (XON/XOFF)
131 |
132 |
133 |
134 |
135 |
136 |
137 | -
138 |
139 |
140 | 0
141 |
142 |
-
143 |
144 |
145 | Parity:
146 |
147 |
148 |
149 | -
150 |
151 |
-
152 |
153 | No Parity
154 |
155 |
156 | -
157 |
158 | Even
159 |
160 |
161 | -
162 |
163 | Odd
164 |
165 |
166 | -
167 |
168 | Space
169 |
170 |
171 | -
172 |
173 | Mark
174 |
175 |
176 |
177 |
178 |
179 |
180 | -
181 |
182 |
183 | 0
184 |
185 |
-
186 |
187 |
188 | Stop Bits:
189 |
190 |
191 |
192 | -
193 |
194 |
-
195 |
196 | One Stop Bit
197 |
198 |
199 | -
200 |
201 | One & Half Stop Bit
202 |
203 |
204 | -
205 |
206 | Two Stop Bits
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | -
217 |
218 |
219 | UI
220 |
221 |
222 |
-
223 |
224 |
-
225 |
226 |
227 | Tabbed windows
228 |
229 |
230 |
231 | -
232 |
233 |
234 | Background Color:
235 |
236 |
237 |
238 | -
239 |
240 |
-
241 |
242 |
243 | Qt::Horizontal
244 |
245 |
246 |
247 | 40
248 | 20
249 |
250 |
251 |
252 |
253 | -
254 |
255 |
256 |
257 | 100
258 | 0
259 |
260 |
261 |
262 | PointingHandCursor
263 |
264 |
265 |
266 | QPushButton {
267 | background-color: #a0a0a0; border: 1px solid black;
268 | }
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 | true
277 |
278 |
279 | false
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 | -
291 |
292 |
293 | Qt::Horizontal
294 |
295 |
296 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 | buttonBox
308 | accepted()
309 | Settings
310 | accept()
311 |
312 |
313 | 248
314 | 254
315 |
316 |
317 | 157
318 | 274
319 |
320 |
321 |
322 |
323 | buttonBox
324 | rejected()
325 | Settings
326 | reject()
327 |
328 |
329 | 316
330 | 260
331 |
332 |
333 | 286
334 | 274
335 |
336 |
337 |
338 |
339 |
340 |
--------------------------------------------------------------------------------
/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 488
10 | 440
11 |
12 |
13 |
14 | FlexiPlot[*]
15 |
16 |
17 |
18 | :/appicon.ico:/appicon.ico
19 |
20 |
21 |
22 | -
23 |
24 |
25 | Qt::ScrollBarAsNeeded
26 |
27 |
28 | Qt::ScrollBarAsNeeded
29 |
30 |
31 | QMdiArea::SubWindowView
32 |
33 |
34 |
35 |
36 |
37 |
115 |
116 |
117 | TopToolBarArea
118 |
119 |
120 | false
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | :/images/application-exit.png:/images/application-exit.png
143 |
144 |
145 | Exit
146 |
147 |
148 |
149 |
150 |
151 | :/images/Connect.png:/images/Connect.png
152 |
153 |
154 | Connect
155 |
156 |
157 | Connect To Device
158 |
159 |
160 | Ctrl+F
161 |
162 |
163 |
164 |
165 |
166 | :/images/Disconnect.png:/images/Disconnect.png
167 |
168 |
169 | Disconnect
170 |
171 |
172 | Disconnect From Device
173 |
174 |
175 | Ctrl+D
176 |
177 |
178 |
179 |
180 |
181 | :/images/settings.png:/images/settings.png
182 |
183 |
184 | Settings
185 |
186 |
187 |
188 |
189 |
190 | :/images/linechart.ico:/images/linechart.ico
191 |
192 |
193 | Add Line Chart
194 |
195 |
196 | Ctrl+1
197 |
198 |
199 |
200 |
201 |
202 | :/images/help-about.png:/images/help-about.png
203 |
204 |
205 | About
206 |
207 |
208 |
209 |
210 |
211 | :/images/document-new.png:/images/document-new.png
212 |
213 |
214 | New
215 |
216 |
217 | Ctrl+N
218 |
219 |
220 |
221 |
222 |
223 | :/images/document-open-folder.png:/images/document-open-folder.png
224 |
225 |
226 | Open
227 |
228 |
229 | Ctrl+O
230 |
231 |
232 |
233 |
234 |
235 | :/images/document-save.png:/images/document-save.png
236 |
237 |
238 | Save
239 |
240 |
241 | Ctrl+S
242 |
243 |
244 |
245 |
246 |
247 | :/images/document-save-as.png:/images/document-save-as.png
248 |
249 |
250 | Save As
251 |
252 |
253 |
254 |
255 |
256 | :/images/window-duplicate.png:/images/window-duplicate.png
257 |
258 |
259 | Cascade
260 |
261 |
262 | Alt+C
263 |
264 |
265 |
266 |
267 |
268 | :/images/view-split-left-right.png:/images/view-split-left-right.png
269 |
270 |
271 | Tile
272 |
273 |
274 | Alt+T
275 |
276 |
277 |
278 |
279 |
280 | :/images/04_maps.png:/images/04_maps.png
281 |
282 |
283 | Add Map
284 |
285 |
286 |
287 |
288 |
289 | :/images/utilities-terminal.png:/images/utilities-terminal.png
290 |
291 |
292 | terminal
293 |
294 |
295 | Opens Serial Terminal
296 |
297 |
298 |
299 |
300 |
301 | :/images/view-statistics.png:/images/view-statistics.png
302 |
303 |
304 | Add Bar Graph
305 |
306 |
307 | Ctrl+2
308 |
309 |
310 |
311 |
312 | true
313 |
314 |
315 | false
316 |
317 |
318 |
319 | :/images/system-lock-screen.png:/images/system-lock-screen.png
320 |
321 |
322 | Lock Widget Position
323 |
324 |
325 | <html><head/><body><p>Lock widgets in their current size and position</p></body></html>
326 |
327 |
328 | If checked allows graphs to be moved around. Uncheck to fix them in a position
329 |
330 |
331 | Ctrl+L
332 |
333 |
334 |
335 |
336 | Debug Tools
337 |
338 |
339 |
340 |
341 |
342 | :/images/piechart.ico:/images/piechart.ico
343 |
344 |
345 | Add Pie Chart
346 |
347 |
348 | Ctrl+3
349 |
350 |
351 |
352 |
353 | Clear Menu
354 |
355 |
356 |
357 |
358 | false
359 |
360 |
361 | (empty)
362 |
363 |
364 |
365 |
366 |
367 | :/images/scatter.png:/images/scatter.png
368 |
369 |
370 | Add Scatter Chart
371 |
372 |
373 | Ctrl+4
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
--------------------------------------------------------------------------------
/widgets/piechart.cpp:
--------------------------------------------------------------------------------
1 | #include "piechart.h"
2 | #include "ui_piechart.h"
3 |
4 | QT_CHARTS_USE_NAMESPACE
5 |
6 | PieChart::PieChart(QWidget *parent) :
7 | AbstractWidget(parent),
8 | ui(new Ui::PieChart)
9 | {
10 | ui->setupUi(this);
11 |
12 | chart = new QChart();
13 |
14 | chart->setTitle( ui->titleEdit->text() );
15 | QFont tFont = chart->titleFont();
16 | tFont.setPointSizeF( 15 );
17 | tFont.setBold( true );
18 | chart->setTitleFont( tFont );
19 |
20 |
21 | chart->setAnimationOptions( QChart::AllAnimations );
22 |
23 | ui->chartView->setChart( chart );
24 | ui->chartView->setRenderHint(QPainter::Antialiasing);
25 |
26 |
27 | connect(ui->idEdit, SIGNAL(textEdited(QString)), this, SLOT(setId(QString)));
28 | connect(ui->titleEdit, SIGNAL(textEdited(QString)), this, SLOT(setTitle(QString)));
29 |
30 | connect(ui->hPosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
31 | connect(ui->vPosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
32 | connect(ui->sizeFactorSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
33 | connect(ui->startAngleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
34 | connect(ui->endAngleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
35 | connect(ui->holeSizeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
36 | connect(ui->explodeSliceCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
37 | connect(ui->animationComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
38 | connect(ui->themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
39 | connect(ui->antialiasingCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
40 |
41 | ui->legendDetachedParamGroup->setVisible(false);
42 | connect(ui->legendShowCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
43 | connect(ui->legendBoldCheckBox, SIGNAL(clicked(bool)), this, SLOT(settingsChanged()));
44 | connect(ui->legendItalicCheckBox, SIGNAL(clicked(bool)), this, SLOT(settingsChanged()));
45 | connect(ui->legendUnderlineCheckBox, SIGNAL(clicked(bool)), this, SLOT(settingsChanged()));
46 | connect(ui->legendFontSizeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
47 | connect(ui->legendFontComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(settingsChanged()));
48 | connect(ui->legendPositionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
49 | connect(ui->legendHPosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
50 | connect(ui->legendVPosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
51 | connect(ui->legendWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
52 | connect(ui->legendHeightSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
53 |
54 | connect(ui->labelArmLengthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
55 | connect(ui->labelPosComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
56 | connect(ui->showLabelsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
57 |
58 | }
59 |
60 | void PieChart::settingsChanged()
61 | {
62 | qDebug() << "Settings changed by: " << QObject::sender();
63 | Config::getInstance()->setUnsavedChanges(true);
64 | plot();
65 | }
66 |
67 | bool PieChart::validPacket(QString packet)
68 | {
69 | /* Regular expresion for multi column packet:
70 | * Colo Test cases:
71 | * P0|Slice 1|255,0,0|10.0048|Slice 2|0,255,0|30|Slice 3|0,0,255|20
72 | *
73 | * Regexp:
74 | * [a-zA-Z0-9]+(\|[a-zA-Z0-9 ]+\|\d{1,3},\d{1,3},\d{1,3}\|(\-*\d+(\.{0,1}\d+)*)*)+
75 | *
76 | *
77 | * No Color Test Cases:
78 | * P0|Slice 1|10|Slice 2|30|Slice 3|20
79 | *
80 | * Regexp:
81 | * [a-zA-Z0-9]+(\|[a-zA-Z0-9 ]+\|(\-*\d+(\.{0,1}\d+)*)*)+
82 | *
83 | */
84 |
85 | QRegExp fullPacket("[a-zA-Z0-9]+(\\|[a-zA-Z0-9 ]+\\|\\d{1,3},\\d{1,3},\\d{1,3}\\|(\\-*\\d+(\\.{0,1}\\d+)*)*)+");
86 | QRegExp noColorPacket("[a-zA-Z0-9]+(\\|[a-zA-Z0-9 ]+\\|(\\-*\\d+(\\.{0,1}\\d+)*)*)+");
87 |
88 |
89 | return fullPacket.exactMatch(packet) || noColorPacket.exactMatch( packet );
90 | }
91 |
92 | void PieChart::reset()
93 | {
94 | items.clear();
95 | chart->removeAllSeries();
96 | }
97 |
98 | void PieChart::serialPacket(QStringList packet)
99 | {
100 | // qDebug() << packet;
101 |
102 | items.clear();
103 |
104 | for(int i=1; iremoveAllSeries();
142 |
143 | chart->setAnimationOptions( (QChart::AnimationOption)ui->animationComboBox->currentIndex() );
144 | ui->chartView->setRenderHint(QPainter::Antialiasing, ui->antialiasingCheckBox->isChecked());
145 |
146 | //create series
147 | QPieSeries * series = new QPieSeries();
148 | // series->setLabelsVisible();
149 |
150 | series->setHorizontalPosition( ui->hPosSpinBox->value() );
151 | series->setVerticalPosition( ui->vPosSpinBox->value() );
152 | series->setPieSize( ui->sizeFactorSpinBox->value() );
153 | series->setPieStartAngle( ui->startAngleSpinBox->value() );
154 | series->setPieEndAngle( ui->endAngleSpinBox->value() );
155 | series->setHoleSize( ui->holeSizeSpinBox->value() );
156 |
157 | foreach( pie_chart_plot_item_t sliceItem, items )
158 | {
159 | FlexiPieSlice * slice = new FlexiPieSlice( sliceItem.name, sliceItem.value );
160 | slice->setExplodeOnHover( ui->explodeSliceCheckBox->isChecked() );
161 | if(sliceItem.colorIsSet)
162 | {
163 | //slice->setPen(QPen(sliceItem.color, 2));
164 | slice->setBrush(sliceItem.color);
165 | }
166 | *series << slice;
167 | }
168 |
169 | chart->addSeries(series);
170 |
171 | //Legend settings
172 | chart->legend()->setVisible(ui->legendShowCheckBox->isChecked());
173 |
174 | if(ui->legendPositionComboBox->currentIndex() == POS_DETACHED && chart->legend()->isAttachedToChart() )
175 | {
176 | chart->legend()->detachFromChart();
177 | chart->legend()->setBackgroundVisible(true);
178 | chart->legend()->setBrush(QBrush(QColor(128, 128, 128, 128)));
179 | chart->legend()->setPen(QPen(QColor(192, 192, 192, 192)));
180 |
181 | ui->legendDetachedParamGroup->setVisible(true);
182 | }
183 | else if(ui->legendPositionComboBox->currentIndex() != POS_DETACHED)
184 | {
185 | chart->legend()->attachToChart();
186 | chart->legend()->setBackgroundVisible(false);
187 | ui->legendDetachedParamGroup->setVisible(false);
188 | }
189 |
190 | switch(ui->legendPositionComboBox->currentIndex())
191 | {
192 | case POS_TOP: chart->legend()->setAlignment(Qt::AlignTop); break;
193 | case POS_RIGHT: chart->legend()->setAlignment(Qt::AlignRight); break;
194 | case POS_BOTTOM: chart->legend()->setAlignment(Qt::AlignBottom); break;
195 | case POS_LEFT: chart->legend()->setAlignment(Qt::AlignLeft); break;
196 | case POS_DETACHED: updateDetachedLegendLayout(); break;
197 | default: chart->legend()->setAlignment(Qt::AlignBottom);
198 | }
199 | QFont lFont = ui->legendFontComboBox->currentFont();
200 | lFont.setBold( ui->legendBoldCheckBox->isChecked() );
201 | lFont.setItalic( ui->legendItalicCheckBox->isChecked() );
202 | lFont.setUnderline( ui->legendUnderlineCheckBox->isChecked() );
203 | lFont.setPointSizeF( ui->legendFontSizeSpinBox->value() );
204 | chart->legend()->setFont( lFont );
205 |
206 |
207 | //Label config
208 | series->setLabelsVisible( ui->showLabelsCheckBox->isChecked() );
209 | if(ui->showLabelsCheckBox->isChecked())
210 | {
211 | foreach( QPieSlice* slice, series->slices())
212 | slice->setLabelArmLengthFactor( ui->labelArmLengthSpinBox->value() );
213 | series->setLabelsPosition( (QPieSlice::LabelPosition)ui->labelPosComboBox->currentIndex() );
214 | }
215 |
216 | //Configure theme
217 | chart->setTheme( (QChart::ChartTheme) ui->themeComboBox->currentIndex() );
218 | QFont tFont = chart->titleFont();
219 | tFont.setPointSizeF( 15 );
220 | tFont.setBold( true );
221 | chart->setTitleFont( tFont );
222 | }
223 |
224 | void PieChart::updateDetachedLegendLayout()
225 | {
226 | chart->legend()->setGeometry(QRectF( ui->legendHPosSpinBox->value(),
227 | ui->legendVPosSpinBox->value(),
228 | ui->legendWidthSpinBox->value(),
229 | ui->legendHeightSpinBox->value()));
230 | chart->legend()->update();
231 | }
232 |
233 | void PieChart::xmlStream(QXmlStreamWriter *writer)
234 | {
235 | writer->writeTextElement("id", this->id);
236 | writer->writeTextElement("title", ui->titleEdit->text());
237 |
238 | writer->writeTextElement("hpos", QString::number(ui->hPosSpinBox->value()) );
239 | writer->writeTextElement("vpos", QString::number(ui->hPosSpinBox->value()) );
240 | writer->writeTextElement("size_factor", QString::number(ui->sizeFactorSpinBox->value()) );
241 | writer->writeTextElement("start_angle", QString::number(ui->startAngleSpinBox->value()) );
242 | writer->writeTextElement("end_angle", QString::number(ui->endAngleSpinBox->value()) );
243 | writer->writeTextElement("hole_size", QString::number(ui->holeSizeSpinBox->value()) );
244 | writer->writeTextElement("explode_slice_on_hover", QString::number(ui->explodeSliceCheckBox->isChecked()) );
245 | writer->writeTextElement("animation", QString::number(ui->animationComboBox->currentIndex()) );
246 | writer->writeTextElement("theme", QString::number(ui->themeComboBox->currentIndex()) );
247 | writer->writeTextElement("antialiasing", QString::number(ui->antialiasingCheckBox->isChecked()) );
248 |
249 | writer->writeTextElement("legend_enabled", QString::number(ui->legendShowCheckBox->isChecked()) );
250 | writer->writeTextElement("legend_position", QString::number(ui->legendPositionComboBox->currentIndex()) );
251 | writer->writeTextElement("legend_hpos", QString::number(ui->legendHPosSpinBox->value()) );
252 | writer->writeTextElement("legend_vpos", QString::number(ui->legendVPosSpinBox->value()) );
253 | writer->writeTextElement("legend_width", QString::number(ui->legendWidthSpinBox->value()) );
254 | writer->writeTextElement("legend_height", QString::number(ui->legendHeightSpinBox->value()) );
255 | writer->writeTextElement("legend_font", ui->legendFontComboBox->currentText() );
256 | writer->writeTextElement("legend_bold", QString::number(ui->legendBoldCheckBox->isChecked()) );
257 | writer->writeTextElement("legend_italic", QString::number(ui->legendItalicCheckBox->isChecked()) );
258 | writer->writeTextElement("legend_underline", QString::number(ui->legendUnderlineCheckBox->isChecked()) );
259 | writer->writeTextElement("legend_font_size", QString::number(ui->legendFontSizeSpinBox->value()) );
260 |
261 | writer->writeTextElement("labels_enabled", QString::number(ui->showLabelsCheckBox->isChecked()) );
262 | writer->writeTextElement("label_arm_length", QString::number(ui->labelArmLengthSpinBox->value()) );
263 | writer->writeTextElement("labels_position", QString::number(ui->labelPosComboBox->currentIndex()) );
264 | }
265 |
266 | void PieChart::xmlParse(QXmlStreamReader *xml)
267 | {
268 | blockAllSignals(true);
269 | /* Let's check that we're really getting a person. */
270 | if(xml->tokenType() != QXmlStreamReader::StartElement &&
271 | xml->name() == "Widget") {
272 | return;
273 | }
274 |
275 | /* Next element... */
276 | xml->readNext();
277 |
278 | while(!(xml->tokenType() == QXmlStreamReader::EndElement && xml->name() == "Widget"))
279 | {
280 | if(xml->name() == "WindowGeometry")
281 | {
282 | QXmlStreamAttributes attributes = xml->attributes();
283 |
284 | if(attributes.hasAttribute("x") && attributes.hasAttribute("y")
285 | && attributes.hasAttribute("width") && attributes.hasAttribute("height"))
286 | {
287 | this->parentWidget()->setGeometry(
288 | attributes.value("x").toInt(),
289 | attributes.value("y").toInt(),
290 | attributes.value("width").toInt(),
291 | attributes.value("height").toInt()
292 | );
293 | }
294 |
295 | }
296 |
297 | if(xml->name() == "id")
298 | {
299 | QString str = xml->readElementText();
300 | id = str;
301 | ui->idEdit->setText(str);
302 | //this->setWindowTitle(QString("Plot: %1").arg(str));
303 | }
304 |
305 | if(xml->name() == "title")
306 | {
307 | QString str = xml->readElementText();
308 | chart->setTitle( str );
309 | ui->titleEdit->setText(str);
310 |
311 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(ui->titleEdit->text()).arg(ui->idEdit->text()));
312 | }
313 |
314 | if(xml->name() == "hpos")
315 | {
316 | double realVal = xml->readElementText().toDouble();
317 | ui->hPosSpinBox->setValue(realVal);
318 | }
319 |
320 | if(xml->name() == "vpos")
321 | {
322 | double realVal = xml->readElementText().toDouble();
323 | ui->vPosSpinBox->setValue(realVal);
324 | }
325 |
326 | if(xml->name() == "size_factor")
327 | {
328 | double realVal = xml->readElementText().toDouble();
329 | ui->sizeFactorSpinBox->setValue(realVal);
330 | }
331 |
332 | if(xml->name() == "start_angle")
333 | {
334 | double realVal = xml->readElementText().toDouble();
335 | ui->startAngleSpinBox->setValue(realVal);
336 | }
337 |
338 | if(xml->name() == "end_angle")
339 | {
340 | double realVal = xml->readElementText().toDouble();
341 | ui->endAngleSpinBox->setValue(realVal);
342 | }
343 |
344 | if(xml->name() == "hole_size")
345 | {
346 | double realVal = xml->readElementText().toDouble();
347 | ui->holeSizeSpinBox->setValue(realVal);
348 | }
349 |
350 | if(xml->name() == "explode_slice_on_hover")
351 | {
352 | int intVal = xml->readElementText().toInt();
353 | if(intVal > 0)
354 | ui->explodeSliceCheckBox->setCheckState( Qt::Checked );
355 | else
356 | ui->explodeSliceCheckBox->setCheckState( Qt::Unchecked );
357 | }
358 |
359 | if(xml->name() == "animation")
360 | {
361 | int intVal = xml->readElementText().toInt();
362 | ui->animationComboBox->setCurrentIndex(intVal);
363 | }
364 |
365 | if(xml->name() == "theme")
366 | {
367 | int intVal = xml->readElementText().toInt();
368 | ui->themeComboBox->setCurrentIndex(intVal);
369 | }
370 |
371 | if(xml->name() == "antialiasing")
372 | {
373 | int intVal = xml->readElementText().toInt();
374 | if(intVal > 0)
375 | ui->antialiasingCheckBox->setCheckState( Qt::Checked );
376 | else
377 | ui->antialiasingCheckBox->setCheckState( Qt::Unchecked );
378 | }
379 |
380 | if(xml->name() == "legend_enabled")
381 | {
382 | int intVal = xml->readElementText().toInt();
383 | if(intVal > 0)
384 | ui->legendShowCheckBox->setCheckState( Qt::Checked );
385 | else
386 | ui->legendShowCheckBox->setCheckState( Qt::Unchecked );
387 | }
388 |
389 | if(xml->name() == "legend_position")
390 | {
391 | int intVal = xml->readElementText().toInt();
392 | ui->legendPositionComboBox->setCurrentIndex(intVal);
393 | // if(intVal == POS_DETACHED)
394 | // ui->legendDetachedParamGroup->setVisible(true);
395 | }
396 |
397 | if(xml->name() == "legend_hpos")
398 | {
399 | double realVal = xml->readElementText().toDouble();
400 | ui->legendHPosSpinBox->setValue(realVal);
401 | }
402 |
403 | if(xml->name() == "legend_vpos")
404 | {
405 | double realVal = xml->readElementText().toDouble();
406 | ui->legendVPosSpinBox->setValue(realVal);
407 | }
408 |
409 | if(xml->name() == "legend_width")
410 | {
411 | double realVal = xml->readElementText().toDouble();
412 | ui->legendWidthSpinBox->setValue(realVal);
413 | }
414 |
415 | if(xml->name() == "legend_height")
416 | {
417 | double realVal = xml->readElementText().toDouble();
418 | ui->legendHeightSpinBox->setValue(realVal);
419 | }
420 |
421 | if(xml->name() == "legend_font")
422 | {
423 | QString str = xml->readElementText();
424 | ui->legendFontComboBox->setCurrentText( str );
425 | }
426 |
427 | if(xml->name() == "legend_bold")
428 | {
429 | int intVal = xml->readElementText().toInt();
430 | ui->legendBoldCheckBox->setChecked( (bool)intVal );
431 | }
432 |
433 | if(xml->name() == "legend_italic")
434 | {
435 | int intVal = xml->readElementText().toInt();
436 | ui->legendItalicCheckBox->setChecked( (bool)intVal );
437 | }
438 |
439 | if(xml->name() == "legend_underline")
440 | {
441 | int intVal = xml->readElementText().toInt();
442 | ui->legendUnderlineCheckBox->setChecked( (bool)intVal );
443 | }
444 |
445 | if(xml->name() == "legend_font_size")
446 | {
447 | double realVal = xml->readElementText().toDouble();
448 | ui->legendFontSizeSpinBox->setValue(realVal);
449 | }
450 |
451 | if(xml->name() == "labels_enabled")
452 | {
453 | int intVal = xml->readElementText().toInt();
454 | if(intVal > 0)
455 | ui->showLabelsCheckBox->setCheckState( Qt::Checked );
456 | else
457 | ui->showLabelsCheckBox->setCheckState( Qt::Unchecked );
458 | }
459 |
460 | if(xml->name() == "label_arm_length")
461 | {
462 | double realVal = xml->readElementText().toDouble();
463 | ui->labelArmLengthSpinBox->setValue(realVal);
464 | }
465 |
466 | if(xml->name() == "labels_position")
467 | {
468 | int intVal = xml->readElementText().toInt();
469 | ui->labelPosComboBox->setCurrentIndex(intVal);
470 | }
471 |
472 |
473 |
474 |
475 |
476 | /* ...and next... */
477 | xml->readNext();
478 | }
479 |
480 | blockAllSignals(false);
481 | settingsChanged();
482 | }
483 |
484 | void PieChart::setId(QString str)
485 | {
486 | id = str;
487 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(ui->titleEdit->text()).arg(str));
488 |
489 | ui->idEdit->blockSignals(true);
490 | ui->idEdit->setText( str );
491 | ui->idEdit->blockSignals(false);
492 |
493 | Config::getInstance()->setUnsavedChanges(true);
494 | }
495 |
496 | void PieChart::setTitle(QString str)
497 | {
498 | chart->setTitle( str );
499 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(str).arg(id));
500 | Config::getInstance()->setUnsavedChanges(true);
501 | }
502 |
503 | void PieChart::blockAllSignals(bool block)
504 | {
505 | ui->idEdit->blockSignals(block);
506 | ui->titleEdit->blockSignals(block);
507 |
508 | ui->hPosSpinBox->blockSignals(block);
509 | ui->vPosSpinBox->blockSignals(block);
510 | ui->sizeFactorSpinBox->blockSignals(block);
511 | ui->startAngleSpinBox->blockSignals(block);
512 | ui->endAngleSpinBox->blockSignals(block);
513 | ui->holeSizeSpinBox->blockSignals(block);
514 | ui->explodeSliceCheckBox->blockSignals(block);
515 | ui->animationComboBox->blockSignals(block);
516 | ui->themeComboBox->blockSignals(block);
517 | ui->antialiasingCheckBox->blockSignals(block);
518 |
519 | ui->legendShowCheckBox->blockSignals(block);
520 | ui->legendBoldCheckBox->blockSignals(block);
521 | ui->legendItalicCheckBox->blockSignals(block);
522 | ui->legendUnderlineCheckBox->blockSignals(block);
523 | ui->legendFontSizeSpinBox->blockSignals(block);
524 | ui->legendFontComboBox->blockSignals(block);
525 | ui->legendPositionComboBox->blockSignals(block);
526 | ui->legendHPosSpinBox->blockSignals(block);
527 | ui->legendVPosSpinBox->blockSignals(block);
528 | ui->legendWidthSpinBox->blockSignals(block);
529 | ui->legendHeightSpinBox->blockSignals(block);
530 |
531 | ui->labelArmLengthSpinBox->blockSignals(block);
532 | ui->labelPosComboBox->blockSignals(block);
533 | ui->showLabelsCheckBox->blockSignals(block);
534 | }
535 |
536 | PieChart::~PieChart()
537 | {
538 | delete ui;
539 | }
540 |
--------------------------------------------------------------------------------
/widgets/bargraph.cpp:
--------------------------------------------------------------------------------
1 | #include "bargraph.h"
2 | #include "ui_bargraph.h"
3 |
4 | QT_CHARTS_USE_NAMESPACE
5 |
6 | BarGraph::BarGraph(QWidget *parent) :
7 | AbstractWidget(parent),
8 | ui(new Ui::BarGraph)
9 | {
10 | ui->setupUi(this);
11 |
12 |
13 |
14 |
15 | chart = new QChart();
16 |
17 |
18 | chart->setTitle( ui->titleEdit->text() );
19 | QFont tFont = chart->titleFont();
20 | tFont.setPointSizeF( 15 );
21 | tFont.setBold( true );
22 | chart->setTitleFont( tFont );
23 |
24 | chart->setAnimationOptions(QChart::SeriesAnimations);
25 |
26 | chart->createDefaultAxes();
27 |
28 | chart->legend()->setVisible(true);
29 | chart->legend()->setAlignment(Qt::AlignBottom);
30 |
31 | // QChartView *chartView = new QChartView(chart);
32 | ui->chartView->setChart( chart );
33 | ui->chartView->setRenderHint(QPainter::Antialiasing);
34 |
35 | // this->layout()->addWidget( chartView );
36 |
37 | this->setWindowTitle(ui->titleEdit->text());
38 |
39 | connect(ui->idEdit, SIGNAL(textEdited(QString)), this, SLOT(setId(QString)));
40 | connect(ui->titleEdit, SIGNAL(textEdited(QString)), this, SLOT(setTitle(QString)));
41 | connect(ui->nameXaxis, SIGNAL(textEdited(QString)), this, SLOT(settingsChanged()));
42 | connect(ui->nameYaxis, SIGNAL(textEdited(QString)), this, SLOT(settingsChanged()));
43 |
44 | connect(ui->barChartTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
45 | connect(ui->animationComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
46 | connect(ui->themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
47 | connect(ui->antialiasingCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
48 |
49 |
50 | ui->legendDetachedParamGroup->setVisible(false);
51 | connect(ui->legendShowCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
52 | connect(ui->legendBoldCheckBox, SIGNAL(clicked(bool)), this, SLOT(settingsChanged()));
53 | connect(ui->legendItalicCheckBox, SIGNAL(clicked(bool)), this, SLOT(settingsChanged()));
54 | connect(ui->legendUnderlineCheckBox, SIGNAL(clicked(bool)), this, SLOT(settingsChanged()));
55 | connect(ui->legendFontSizeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
56 | connect(ui->legendFontComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(settingsChanged()));
57 | connect(ui->legendPositionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
58 | connect(ui->legendHPosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
59 | connect(ui->legendVPosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
60 | connect(ui->legendWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
61 | connect(ui->legendHeightSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
62 |
63 | connect(ui->showLabelsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
64 | connect(ui->labelAngleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
65 | connect(ui->labelFormatEdit, SIGNAL(textChanged(QString)), this, SLOT(settingsChanged()));
66 | connect(ui->labelPosComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
67 |
68 | connect(ui->autoScaleValueAxisCheckBox, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
69 | connect(ui->maxValueAxisSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
70 | connect(ui->minValueAxisSpinBox, SIGNAL(valueChanged(double)), this, SLOT(settingsChanged()));
71 |
72 |
73 | readyToPlot = true;
74 | }
75 |
76 | void BarGraph::settingsChanged()
77 | {
78 | if(!readyToPlot)
79 | return;
80 |
81 | qDebug() << "Settings changed by: " << QObject::sender();
82 | Config::getInstance()->setUnsavedChanges(true);
83 | plot();
84 | }
85 |
86 | void BarGraph::setTitle(QString str)
87 | {
88 | chart->setTitle( str );
89 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(str).arg(id));
90 | Config::getInstance()->setUnsavedChanges(true);
91 | }
92 |
93 | bool BarGraph::validPacket(QString packet)
94 | {
95 | /* Regular expresion for multi column packet:
96 | * Colo Test cases:
97 | * P0|Jan;Feb;Mar|Jane|255,0,0|25 15 17|John|255,0,0|8 9 23
98 | * P0|Jan|Jane|255,0,0|25|John|255,0,0|8
99 | * Regexp:
100 | * [a-zA-Z0-9]+\|[a-zA-Z0-9 \;]+(\|[a-zA-Z0-9 ]+\|\d{1,3},\d{1,3},\d{1,3}\|(\-*\d+(\.{0,1}\d+)*\s?)*)+
101 | *
102 | *
103 | * No Color Test Cases:
104 | * P0|Jan;Feb;Mar|Jane|25 15 17|John|8 9 23
105 | * P0|Jan|Jane|25|John|8
106 | *
107 | * Regexp:
108 | * [a-zA-Z0-9]+\|[a-zA-Z0-9 \;]+(\|[a-zA-Z0-9 ]+\|(\-*\d+(\.{0,1}\d+)*\s?)*)+
109 | *
110 | */
111 | QRegExp fullPacket("[a-zA-Z0-9]+\\|[a-zA-Z0-9 \\;]+(\\|[a-zA-Z0-9 ]+\\|\\d{1,3},\\d{1,3},\\d{1,3}\\|(\\-*\\d+(\\.{0,1}\\d+)*\\s?)*)+");
112 | QRegExp noColorPacket("[a-zA-Z0-9]+\\|[a-zA-Z0-9 \\;]+(\\|[a-zA-Z0-9 ]+\\|(\\-*\\d+(\\.{0,1}\\d+)*\\s?)*)+");
113 |
114 | // qDebug() << fullPacket.exactMatch(packet) << noColorPacket.exactMatch( packet );
115 |
116 | return fullPacket.exactMatch(packet) || noColorPacket.exactMatch( packet );
117 | }
118 |
119 | void BarGraph::serialPacket(QStringList packet)
120 | {
121 | // qDebug() << packet;
122 | categories = packet[1].split(";");
123 |
124 | // qDebug() << categories;
125 |
126 | items.clear();
127 |
128 | for(int i=2; iseries() );
169 | qDeleteAll( chart->axes() );
170 |
171 | chart->setAnimationOptions( (QChart::AnimationOption)ui->animationComboBox->currentIndex() );
172 | ui->chartView->setRenderHint(QPainter::Antialiasing, ui->antialiasingCheckBox->isChecked());
173 |
174 | QAbstractBarSeries* series;
175 | switch( ui->barChartTypeComboBox->currentIndex() ) {
176 | case TYPE_NORMAL: series = new QBarSeries(); break;
177 | case TYPE_STACKED: series = new QStackedBarSeries(); break;
178 | case TYPE_PERCENT: series = new QPercentBarSeries(); break;
179 | case TYPE_HORIZONTAL: series = new QHorizontalBarSeries(); break;
180 | case TYPE_HORIZONTAL_STACKED: series = new QHorizontalStackedBarSeries(); break;
181 | case TYPE_HORIZONTAL_PERCENT: series = new QHorizontalPercentBarSeries(); break;
182 | default: series = new QBarSeries();
183 | }
184 |
185 | // series->setLabelsVisible( true );
186 |
187 | foreach(bar_graph_plot_item_t item, items)
188 | {
189 | QBarSet *set = new QBarSet(item.set_name);
190 | if(item.colorIsSet)
191 | set->setColor( item.color );
192 | set->append( item.values );
193 |
194 | series->append( set );
195 | }
196 |
197 | chart->addSeries(series);
198 |
199 | QBarCategoryAxis *axis = new QBarCategoryAxis();
200 | axis->append(categories);
201 |
202 |
203 | chart->createDefaultAxes();
204 | if( ui->barChartTypeComboBox->currentIndex() == TYPE_NORMAL ||
205 | ui->barChartTypeComboBox->currentIndex() == TYPE_STACKED ||
206 | ui->barChartTypeComboBox->currentIndex() == TYPE_PERCENT)
207 | {
208 | chart->setAxisX(axis, series);
209 |
210 | if(!ui->autoScaleValueAxisCheckBox->isChecked())
211 | {
212 | QAbstractAxis *aValueAxis = chart->axes(Qt::Vertical).at(0);
213 | QValueAxis *valueAxis = qobject_cast( aValueAxis );
214 | // qDebug() << chart->axes(Qt::Vertical).at(0) << ay << ay->max();
215 | valueAxis->setMax( ui->maxValueAxisSpinBox->value() );
216 | valueAxis->setMin( ui->minValueAxisSpinBox->value() );
217 | }
218 | }
219 | else
220 | {
221 | chart->setAxisY(axis, series);
222 |
223 | if(!ui->autoScaleValueAxisCheckBox->isChecked())
224 | {
225 | QAbstractAxis *aValueAxis = chart->axes(Qt::Horizontal).at(0);
226 | QValueAxis *valueAxis = qobject_cast( aValueAxis );
227 | // qDebug() << chart->axes(Qt::Vertical).at(0) << ay << ay->max();
228 | valueAxis->setMax( ui->maxValueAxisSpinBox->value() );
229 | valueAxis->setMin( ui->minValueAxisSpinBox->value() );
230 | }
231 | }
232 |
233 | chart->axisX()->setTitleText( ui->nameXaxis->text() );
234 | chart->axisY()->setTitleText( ui->nameYaxis->text() );
235 |
236 |
237 |
238 |
239 | //Legend settings
240 | chart->legend()->setVisible(ui->legendShowCheckBox->isChecked());
241 |
242 | //Hmm I haven't figured out yet, how to temprarly hide a set in series... only to delete
243 | /*foreach(QLegendMarker* marker, chart->legend()->markers())
244 | {
245 | disconnect(marker, SIGNAL(clicked()), this, SLOT(legendMarkerClicked()));
246 | connect(marker, SIGNAL(clicked()), this, SLOT(legendMarkerClicked()));
247 | }*/
248 |
249 | if(ui->legendPositionComboBox->currentIndex() == POS_DETACHED && chart->legend()->isAttachedToChart() )
250 | {
251 | chart->legend()->detachFromChart();
252 | chart->legend()->setBackgroundVisible(true);
253 | chart->legend()->setBrush(QBrush(QColor(128, 128, 128, 128)));
254 | chart->legend()->setPen(QPen(QColor(192, 192, 192, 192)));
255 |
256 | ui->legendDetachedParamGroup->setVisible(true);
257 | }
258 | else if(ui->legendPositionComboBox->currentIndex() != POS_DETACHED)
259 | {
260 | chart->legend()->attachToChart();
261 | chart->legend()->setBackgroundVisible(false);
262 | ui->legendDetachedParamGroup->setVisible(false);
263 | }
264 |
265 | switch(ui->legendPositionComboBox->currentIndex())
266 | {
267 | case POS_TOP: chart->legend()->setAlignment(Qt::AlignTop); break;
268 | case POS_RIGHT: chart->legend()->setAlignment(Qt::AlignRight); break;
269 | case POS_BOTTOM: chart->legend()->setAlignment(Qt::AlignBottom); break;
270 | case POS_LEFT: chart->legend()->setAlignment(Qt::AlignLeft); break;
271 | case POS_DETACHED: updateDetachedLegendLayout(); break;
272 | default: chart->legend()->setAlignment(Qt::AlignBottom);
273 | }
274 | QFont lFont = ui->legendFontComboBox->currentFont();
275 | lFont.setBold( ui->legendBoldCheckBox->isChecked() );
276 | lFont.setItalic( ui->legendItalicCheckBox->isChecked() );
277 | lFont.setUnderline( ui->legendUnderlineCheckBox->isChecked() );
278 | lFont.setPointSizeF( ui->legendFontSizeSpinBox->value() );
279 | chart->legend()->setFont( lFont );
280 |
281 |
282 | //Label config
283 | series->setLabelsVisible( ui->showLabelsCheckBox->isChecked() );
284 | if(ui->showLabelsCheckBox->isChecked())
285 | {
286 | series->setLabelsAngle( ui->labelAngleSpinBox->value() );
287 | series->setLabelsFormat( ui->labelFormatEdit->text() );
288 | series->setLabelsPosition( (QAbstractBarSeries::LabelsPosition)ui->labelPosComboBox->currentIndex() );
289 | }
290 |
291 |
292 | chart->setTheme( (QChart::ChartTheme) ui->themeComboBox->currentIndex() );
293 | QFont tFont = chart->titleFont();
294 | tFont.setPointSizeF( 15 );
295 | tFont.setBold( true );
296 | chart->setTitleFont( tFont );
297 |
298 |
299 |
300 |
301 | }
302 |
303 | void BarGraph::updateDetachedLegendLayout()
304 | {
305 | chart->legend()->setGeometry(QRectF( ui->legendHPosSpinBox->value(),
306 | ui->legendVPosSpinBox->value(),
307 | ui->legendWidthSpinBox->value(),
308 | ui->legendHeightSpinBox->value()));
309 | chart->legend()->update();
310 | }
311 |
312 | void BarGraph::xmlStream(QXmlStreamWriter *writer)
313 | {
314 | writer->writeTextElement("id", this->id);
315 | writer->writeTextElement("title", ui->titleEdit->text());
316 | writer->writeTextElement("xname", ui->nameXaxis->text());
317 | writer->writeTextElement("yname", ui->nameYaxis->text());
318 |
319 | writer->writeTextElement("type", QString::number(ui->barChartTypeComboBox->currentIndex()) );
320 | writer->writeTextElement("animation", QString::number(ui->animationComboBox->currentIndex()) );
321 | writer->writeTextElement("theme", QString::number(ui->themeComboBox->currentIndex()) );
322 | writer->writeTextElement("antialiasing", QString::number(ui->antialiasingCheckBox->isChecked()) );
323 |
324 | writer->writeTextElement("legend_enabled", QString::number(ui->legendShowCheckBox->isChecked()) );
325 | writer->writeTextElement("legend_position", QString::number(ui->legendPositionComboBox->currentIndex()) );
326 | writer->writeTextElement("legend_hpos", QString::number(ui->legendHPosSpinBox->value()) );
327 | writer->writeTextElement("legend_vpos", QString::number(ui->legendVPosSpinBox->value()) );
328 | writer->writeTextElement("legend_width", QString::number(ui->legendWidthSpinBox->value()) );
329 | writer->writeTextElement("legend_height", QString::number(ui->legendHeightSpinBox->value()) );
330 | writer->writeTextElement("legend_font", ui->legendFontComboBox->currentText() );
331 | writer->writeTextElement("legend_bold", QString::number(ui->legendBoldCheckBox->isChecked()) );
332 | writer->writeTextElement("legend_italic", QString::number(ui->legendItalicCheckBox->isChecked()) );
333 | writer->writeTextElement("legend_underline", QString::number(ui->legendUnderlineCheckBox->isChecked()) );
334 | writer->writeTextElement("legend_font_size", QString::number(ui->legendFontSizeSpinBox->value()) );
335 |
336 | writer->writeTextElement("labels_enabled", QString::number(ui->showLabelsCheckBox->isChecked()) );
337 | writer->writeTextElement("labels_angle", QString::number(ui->labelAngleSpinBox->value()) );
338 | writer->writeTextElement("labels_position", QString::number(ui->labelPosComboBox->currentIndex()) );
339 | writer->writeTextElement("labels_format", ui->labelFormatEdit->text() );
340 |
341 | writer->writeTextElement("auto_scale_value_axis", QString::number(ui->autoScaleValueAxisCheckBox->isChecked() ) );
342 | writer->writeTextElement("min_scale_value_axis", QString::number(ui->minValueAxisSpinBox->value()) );
343 | writer->writeTextElement("max_scale_value_axis", QString::number(ui->maxValueAxisSpinBox->value()) );
344 |
345 |
346 | }
347 |
348 | void BarGraph::xmlParse(QXmlStreamReader *xml)
349 | {
350 | readyToPlot = false;
351 | blockAllSignals(true);
352 | /* Let's check that we're really getting a person. */
353 | if(xml->tokenType() != QXmlStreamReader::StartElement &&
354 | xml->name() == "Widget") {
355 | return;
356 | }
357 |
358 | /* Next element... */
359 | xml->readNext();
360 |
361 | while(!(xml->tokenType() == QXmlStreamReader::EndElement && xml->name() == "Widget"))
362 | {
363 | if(xml->name() == "WindowGeometry")
364 | {
365 | QXmlStreamAttributes attributes = xml->attributes();
366 |
367 | if(attributes.hasAttribute("x") && attributes.hasAttribute("y")
368 | && attributes.hasAttribute("width") && attributes.hasAttribute("height"))
369 | {
370 | this->parentWidget()->setGeometry(
371 | attributes.value("x").toInt(),
372 | attributes.value("y").toInt(),
373 | attributes.value("width").toInt(),
374 | attributes.value("height").toInt()
375 | );
376 | }
377 |
378 | }
379 |
380 | if(xml->name() == "id")
381 | {
382 | QString str = xml->readElementText();
383 | id = str;
384 | ui->idEdit->setText(str);
385 | //this->setWindowTitle(QString("Plot: %1").arg(str));
386 | }
387 |
388 | if(xml->name() == "title")
389 | {
390 | QString str = xml->readElementText();
391 | chart->setTitle( str );
392 | ui->titleEdit->setText(str);
393 |
394 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(ui->titleEdit->text()).arg(ui->idEdit->text()));
395 | }
396 |
397 | if(xml->name() == "xname")
398 | {
399 | QString str = xml->readElementText();
400 | ui->nameXaxis->setText(str);
401 | }
402 |
403 | if(xml->name() == "yname")
404 | {
405 | QString str = xml->readElementText();
406 | ui->nameYaxis->setText(str);
407 | }
408 |
409 | if(xml->name() == "type")
410 | {
411 | int intVal = xml->readElementText().toInt();
412 | ui->barChartTypeComboBox->setCurrentIndex(intVal);
413 | }
414 |
415 | if(xml->name() == "animation")
416 | {
417 | int intVal = xml->readElementText().toInt();
418 | ui->animationComboBox->setCurrentIndex(intVal);
419 | }
420 |
421 | if(xml->name() == "theme")
422 | {
423 | int intVal = xml->readElementText().toInt();
424 | ui->themeComboBox->setCurrentIndex(intVal);
425 | }
426 |
427 | if(xml->name() == "antialiasing")
428 | {
429 | int intVal = xml->readElementText().toInt();
430 | if(intVal > 0)
431 | ui->antialiasingCheckBox->setCheckState( Qt::Checked );
432 | else
433 | ui->antialiasingCheckBox->setCheckState( Qt::Unchecked );
434 | }
435 |
436 | if(xml->name() == "legend_enabled")
437 | {
438 | int intVal = xml->readElementText().toInt();
439 | if(intVal > 0)
440 | ui->legendShowCheckBox->setCheckState( Qt::Checked );
441 | else
442 | ui->legendShowCheckBox->setCheckState( Qt::Unchecked );
443 | }
444 |
445 | if(xml->name() == "legend_position")
446 | {
447 | int intVal = xml->readElementText().toInt();
448 | ui->legendPositionComboBox->setCurrentIndex(intVal);
449 | // if(intVal == POS_DETACHED)
450 | // ui->legendDetachedParamGroup->setVisible(true);
451 | }
452 |
453 | if(xml->name() == "legend_hpos")
454 | {
455 | double realVal = xml->readElementText().toDouble();
456 | ui->legendHPosSpinBox->setValue(realVal);
457 | }
458 |
459 | if(xml->name() == "legend_vpos")
460 | {
461 | double realVal = xml->readElementText().toDouble();
462 | ui->legendVPosSpinBox->setValue(realVal);
463 | }
464 |
465 | if(xml->name() == "legend_width")
466 | {
467 | double realVal = xml->readElementText().toDouble();
468 | ui->legendWidthSpinBox->setValue(realVal);
469 | }
470 |
471 | if(xml->name() == "legend_height")
472 | {
473 | double realVal = xml->readElementText().toDouble();
474 | ui->legendHeightSpinBox->setValue(realVal);
475 | }
476 |
477 | if(xml->name() == "legend_font")
478 | {
479 | QString str = xml->readElementText();
480 | ui->legendFontComboBox->setCurrentText( str );
481 | }
482 |
483 | if(xml->name() == "legend_bold")
484 | {
485 | int intVal = xml->readElementText().toInt();
486 | ui->legendBoldCheckBox->setChecked( (bool)intVal );
487 | }
488 |
489 | if(xml->name() == "legend_italic")
490 | {
491 | int intVal = xml->readElementText().toInt();
492 | ui->legendItalicCheckBox->setChecked( (bool)intVal );
493 | }
494 |
495 | if(xml->name() == "legend_underline")
496 | {
497 | int intVal = xml->readElementText().toInt();
498 | ui->legendUnderlineCheckBox->setChecked( (bool)intVal );
499 | }
500 |
501 | if(xml->name() == "legend_font_size")
502 | {
503 | double realVal = xml->readElementText().toDouble();
504 | ui->legendFontSizeSpinBox->setValue(realVal);
505 | }
506 |
507 | if(xml->name() == "labels_enabled")
508 | {
509 | int intVal = xml->readElementText().toInt();
510 | if(intVal > 0)
511 | ui->showLabelsCheckBox->setCheckState( Qt::Checked );
512 | else
513 | ui->showLabelsCheckBox->setCheckState( Qt::Unchecked );
514 | }
515 |
516 | if(xml->name() == "labels_angle")
517 | {
518 | double realVal = xml->readElementText().toDouble();
519 | ui->labelAngleSpinBox->setValue(realVal);
520 | }
521 |
522 | if(xml->name() == "labels_position")
523 | {
524 | int intVal = xml->readElementText().toInt();
525 | ui->labelPosComboBox->setCurrentIndex(intVal);
526 | }
527 |
528 | if(xml->name() == "labels_format")
529 | {
530 | QString str = xml->readElementText();
531 | ui->labelFormatEdit->setText( str );
532 | }
533 |
534 | if(xml->name() == "auto_scale_value_axis")
535 | {
536 | int intVal = xml->readElementText().toInt();
537 | if(intVal > 0)
538 | ui->autoScaleValueAxisCheckBox->setCheckState( Qt::Checked );
539 | else
540 | ui->autoScaleValueAxisCheckBox->setCheckState( Qt::Unchecked );
541 | }
542 |
543 | if(xml->name() == "min_scale_value_axis")
544 | {
545 | double realVal = xml->readElementText().toDouble();
546 | ui->minValueAxisSpinBox->setValue(realVal);
547 | }
548 |
549 | if(xml->name() == "max_scale_value_axis")
550 | {
551 | double realVal = xml->readElementText().toDouble();
552 | ui->maxValueAxisSpinBox->setValue(realVal);
553 | }
554 |
555 |
556 | /* ...and next... */
557 | xml->readNext();
558 | }
559 |
560 | readyToPlot = true;
561 | blockAllSignals(false);
562 | settingsChanged();
563 | }
564 |
565 | void BarGraph::reset()
566 | {
567 | qDeleteAll( chart->series() );
568 | qDeleteAll( chart->axes() );
569 | }
570 |
571 | void BarGraph::setId(QString str)
572 | {
573 | id = str;
574 | this->setWindowTitle(QString("%1 \t|\t ID: %2").arg(ui->titleEdit->text()).arg(str));
575 |
576 | ui->idEdit->blockSignals(true);
577 | ui->idEdit->setText( str );
578 | ui->idEdit->blockSignals(false);
579 |
580 | Config::getInstance()->setUnsavedChanges(true);
581 |
582 | }
583 |
584 | //Hmm I haven't figured out yet, how to temprarly hide a set in series... only to delete
585 | void BarGraph::legendMarkerClicked()
586 | {
587 | QLegendMarker* marker = qobject_cast(QObject::sender());
588 | Q_ASSERT(marker);
589 |
590 | qDebug() << marker->type();
591 |
592 | switch(marker->type())
593 | {
594 | case QLegendMarker::LegendMarkerTypeBar:
595 | {
596 | QAbstractBarSeries * barSeries = qobject_cast( marker->series() );
597 | Q_ASSERT(barSeries);
598 |
599 |
600 | qDebug() << barSeries->barSets().at(0);
601 |
602 | QBarLegendMarker* barMarker = qobject_cast(marker);
603 | Q_ASSERT(barMarker);
604 | qDebug() << barMarker->barset();
605 |
606 | barSeries->take(barMarker->barset());
607 |
608 |
609 | break;
610 | }
611 | default: qDebug() << "Unknown marker"; break;
612 | }
613 | }
614 |
615 | void BarGraph::blockAllSignals(bool block)
616 | {
617 | ui->idEdit->blockSignals(block);
618 | ui->titleEdit->blockSignals(block);
619 | ui->nameXaxis->blockSignals(block);
620 | ui->nameYaxis->blockSignals(block);
621 |
622 | ui->barChartTypeComboBox->blockSignals(block);
623 | ui->animationComboBox->blockSignals(block);
624 | ui->themeComboBox->blockSignals(block);
625 |
626 | ui->legendShowCheckBox->blockSignals(block);
627 | ui->legendBoldCheckBox->blockSignals(block);
628 | ui->legendItalicCheckBox->blockSignals(block);
629 | ui->legendUnderlineCheckBox->blockSignals(block);
630 | ui->legendFontSizeSpinBox->blockSignals(block);
631 | ui->legendFontComboBox->blockSignals(block);
632 | ui->legendPositionComboBox->blockSignals(block);
633 | ui->legendHPosSpinBox->blockSignals(block);
634 | ui->legendVPosSpinBox->blockSignals(block);
635 | ui->legendWidthSpinBox->blockSignals(block);
636 | ui->legendHeightSpinBox->blockSignals(block);
637 |
638 | ui->showLabelsCheckBox->blockSignals(block);
639 | ui->labelAngleSpinBox->blockSignals(block);
640 | ui->labelFormatEdit->blockSignals(block);
641 | ui->labelPosComboBox->blockSignals(block);
642 |
643 | ui->autoScaleValueAxisCheckBox->blockSignals(block);
644 | ui->minValueAxisSpinBox->blockSignals(block);
645 | ui->maxValueAxisSpinBox->blockSignals(block);
646 | }
647 |
648 | BarGraph::~BarGraph()
649 | {
650 | delete ui;
651 | }
652 |
--------------------------------------------------------------------------------
/widgets/plotter.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Plotter
4 |
5 |
6 |
7 | 0
8 | 0
9 | 412
10 | 357
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | 0
21 |
22 |
23 |
24 | Plot
25 |
26 |
27 |
-
28 |
29 |
30 |
31 | 0
32 | 0
33 |
34 |
35 |
36 |
37 | -
38 |
39 |
-
40 |
41 |
42 | Save current plot to CSV
43 |
44 |
45 | Save
46 |
47 |
48 |
49 | :/images/document-save.png:/images/document-save.png
50 |
51 |
52 |
53 | -
54 |
55 |
56 | Qt::Horizontal
57 |
58 |
59 |
60 | 40
61 | 20
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 | <html><head/><body><p>Starts/stops data collecting from Serial</p><p>When stopped, you'll be able to zoom in/out and move the graph to further inspect the data.</p></body></html>
70 |
71 |
72 |
73 |
74 |
75 |
76 | :/images/media-playback-start.png
77 | :/images/media-playback-stop.png:/images/media-playback-start.png
78 |
79 |
80 | true
81 |
82 |
83 | true
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | Settings
94 |
95 |
96 | -
97 |
98 |
99 | true
100 |
101 |
102 |
103 |
104 | 0
105 | 0
106 | 230
107 | 678
108 |
109 |
110 |
111 |
-
112 |
113 |
114 | Basic
115 |
116 |
117 |
-
118 |
119 |
120 | QFormLayout::AllNonFixedFieldsGrow
121 |
122 |
-
123 |
124 |
125 | <html><head/><body><p>The ID of the graph, for serial thread to properly forward the incoming data from micro-controller.</p><p>You can have the same IDs if you wish, both will receive the packet from the serial thread.</p></body></html>
126 |
127 |
128 | ID:
129 |
130 |
131 |
132 | -
133 |
134 |
135 | p1
136 |
137 |
138 |
139 | -
140 |
141 |
142 | <html><head/><body><p>Can select the graph to plot in real time or XY plot</p><p><span style=" font-size:10pt;">Sample real-time packet with 3 curves XYZ:</span></p><p>{<span style=" color:#ff0000;">P0|X|255,0,0|100</span><span style=" color:#00ff7f;">|Y|0,255,0|150</span><span style=" color:#5555ff;">|Z|0,0,255|200</span>}</p><p>{Plot ID|Curve 1|Color|Value|Curve 2|Color|Value}</p><p><span style=" font-weight:600;">Note: color is in RGB format with comma seperating the values (R,G,B)</span></p><p><span style=" font-size:10pt;">Sample XY plot (supports only one curve):</span></p><p>{P0|Some XY plot|255,0,0|1 255 2 200 3 150 4 100}</p><p>{Plot ID|Curve name|Color|X Y X Y X Y X Y.....}</p><p><span style=" font-weight:600;">Note: If for each X value there won't be Y value, the plot will be ignored</span><br/></p></body></html>
143 |
144 |
145 | Type:
146 |
147 |
148 |
149 | -
150 |
151 |
-
152 |
153 | Time plot
154 |
155 |
156 | -
157 |
158 | XY-Plot
159 |
160 |
161 |
162 |
163 | -
164 |
165 |
166 | Title
167 |
168 |
169 |
170 | -
171 |
172 |
173 | A Simple Plotting Demonstration
174 |
175 |
176 |
177 | -
178 |
179 |
180 | <html><head/><body><p>Applicable only to real time plot, basically, how many data points will be stored in the memory before deleting them. </p></body></html>
181 |
182 |
183 | Buffer
184 |
185 |
186 |
187 | -
188 |
189 |
190 | 10
191 |
192 |
193 | 1000000
194 |
195 |
196 | 100
197 |
198 |
199 |
200 | -
201 |
202 |
203 | <html><head/><body><p>How often the plot will be updated. You shouldn't need less than 50ms, however if you want to improve performance of the application, it is advisable to increase the refresh rate. </p></body></html>
204 |
205 |
206 | Refresh rate (ms)
207 |
208 |
209 |
210 | -
211 |
212 |
213 | 10
214 |
215 |
216 | 10000
217 |
218 |
219 | 50
220 |
221 |
222 |
223 | -
224 |
225 |
226 | Name of X Axis:
227 |
228 |
229 |
230 | -
231 |
232 |
233 | -
234 |
235 |
236 | Name of Y Axis
237 |
238 |
239 |
240 | -
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 | -
249 |
250 |
251 | Scaling
252 |
253 |
254 |
-
255 |
256 |
257 | QFormLayout::AllNonFixedFieldsGrow
258 |
259 |
-
260 |
261 |
262 | Automatically scales the graph to show all values on Y axis
263 |
264 |
265 | Auto Scaling Y
266 |
267 |
268 | true
269 |
270 |
271 |
272 | -
273 |
274 |
275 | Min Y
276 |
277 |
278 |
279 | -
280 |
281 |
282 | -10000000.000000000000000
283 |
284 |
285 | 10000000.000000000000000
286 |
287 |
288 | -200.000000000000000
289 |
290 |
291 |
292 | -
293 |
294 |
295 | Max Y
296 |
297 |
298 |
299 | -
300 |
301 |
302 | -10000000.000000000000000
303 |
304 |
305 | 10000000.000000000000000
306 |
307 |
308 | 200.000000000000000
309 |
310 |
311 |
312 | -
313 |
314 |
315 | Automatically scales graph to include all X values (manual scaling works only on XY plot)
316 |
317 |
318 | Auto Scaling X
319 |
320 |
321 | true
322 |
323 |
324 |
325 | -
326 |
327 |
328 | Min X
329 |
330 |
331 |
332 | -
333 |
334 |
335 | -10000000.000000000000000
336 |
337 |
338 | 10000000.000000000000000
339 |
340 |
341 | -200.000000000000000
342 |
343 |
344 |
345 | -
346 |
347 |
348 | -10000000.000000000000000
349 |
350 |
351 | 10000000.000000000000000
352 |
353 |
354 | 200.000000000000000
355 |
356 |
357 |
358 | -
359 |
360 |
361 | Max X
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 | -
371 |
372 |
373 | Misc
374 |
375 |
376 |
-
377 |
378 |
-
379 |
380 |
381 | <html><head/><body><p>Format of the date in real time plot. Some of the available formats: </p><p><span style=" font-weight:600;">"dd:mm:yyyy | hh:mm:ss:zzz"</span></p><p>Where it shows<span style=" font-weight:600;"> day:month:year | hours:minutes:seconds:milliseconds</span></p></body></html>
382 |
383 |
384 |
385 |
386 |
387 | Date Format
388 |
389 |
390 |
391 | -
392 |
393 |
394 | hh:mm:ss
395 |
396 |
397 |
398 | -
399 |
400 |
401 | Automatically fills the graph
402 |
403 |
404 | Auto filling
405 |
406 |
407 | true
408 |
409 |
410 |
411 | -
412 |
413 |
414 | Auto Fill Opacity:
415 |
416 |
417 |
418 | -
419 |
420 |
421 | 20
422 |
423 |
424 | 100
425 |
426 |
427 |
428 | -
429 |
430 |
431 | Background Color:
432 |
433 |
434 |
435 | -
436 |
437 |
-
438 |
439 |
440 | Qt::Horizontal
441 |
442 |
443 |
444 | 40
445 | 20
446 |
447 |
448 |
449 |
450 | -
451 |
452 |
453 |
454 | 50
455 | 0
456 |
457 |
458 |
459 |
460 | 50
461 | 16777215
462 |
463 |
464 |
465 | background-color:#ffffff;
466 | border: 2px solid #000;
467 |
468 |
469 |
470 |
471 |
472 |
473 | -
474 |
475 |
476 | Choose background color
477 |
478 |
479 |
480 |
481 |
482 |
483 | :/images/kcoloredit.png:/images/kcoloredit.png
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 | -
495 |
496 |
497 |
498 | 0
499 | 0
500 |
501 |
502 |
503 |
504 | 0
505 | 0
506 |
507 |
508 |
509 | Auto Write
510 |
511 |
512 |
-
513 |
514 |
-
515 |
516 |
517 | Will write all results directly to the file you have specified. Similar to save button, but does it instantly and automatically. Useful for when one needs to do analysis later. Results will be in CSV
518 |
519 |
520 | Write To File
521 |
522 |
523 |
524 | -
525 |
526 |
527 | File:
528 |
529 |
530 |
531 | -
532 |
533 |
-
534 |
535 |
536 | true
537 |
538 |
539 |
540 | -
541 |
542 |
543 |
544 |
545 |
546 |
547 | :/images/document-open-folder.png:/images/document-open-folder.png
548 |
549 |
550 |
551 |
552 |
553 | -
554 |
555 |
556 | Specify what seperator should the save and auto file write function use
557 |
558 |
559 | Seperator:
560 |
561 |
562 |
563 | -
564 |
565 |
566 | ;
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 | QwtPlot
588 | QWidget
589 |
590 | 1
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
--------------------------------------------------------------------------------
/widgets/linegraph.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Plotter
4 |
5 |
6 |
7 | 0
8 | 0
9 | 412
10 | 357
11 |
12 |
13 |
14 | Line Chart
15 |
16 |
17 |
18 | :/images/linechart.ico:/images/linechart.ico
19 |
20 |
21 |
22 | 0
23 |
24 |
25 | 0
26 |
27 |
28 | 0
29 |
30 |
31 | 0
32 |
33 |
34 | 0
35 |
36 | -
37 |
38 |
39 | 0
40 |
41 |
42 |
43 | Chart
44 |
45 |
46 |
-
47 |
48 |
49 |
50 | 0
51 | 0
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
-
59 |
60 |
61 | Save current plot to CSV
62 |
63 |
64 | Save
65 |
66 |
67 |
68 | :/images/document-save.png:/images/document-save.png
69 |
70 |
71 |
72 | -
73 |
74 |
75 | Qt::Horizontal
76 |
77 |
78 |
79 | 40
80 | 20
81 |
82 |
83 |
84 |
85 | -
86 |
87 |
88 | <html><head/><body><p>Starts/stops data collecting from Serial</p><p>When stopped, you'll be able to zoom in/out and move the graph to further inspect the data.</p></body></html>
89 |
90 |
91 |
92 |
93 |
94 |
95 | :/images/media-playback-start.png
96 | :/images/media-playback-stop.png:/images/media-playback-start.png
97 |
98 |
99 | true
100 |
101 |
102 | true
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | Settings
113 |
114 |
115 | -
116 |
117 |
118 | true
119 |
120 |
121 |
122 |
123 | 0
124 | 0
125 | 369
126 | 678
127 |
128 |
129 |
130 |
-
131 |
132 |
133 | Basic
134 |
135 |
136 |
-
137 |
138 |
139 | QFormLayout::AllNonFixedFieldsGrow
140 |
141 |
-
142 |
143 |
144 | <html><head/><body><p>The ID of the graph, for serial thread to properly forward the incoming data from micro-controller.</p><p>You can have the same IDs if you wish, both will receive the packet from the serial thread.</p></body></html>
145 |
146 |
147 | ID:
148 |
149 |
150 |
151 | -
152 |
153 |
154 | p1
155 |
156 |
157 |
158 | -
159 |
160 |
161 | <html><head/><body><p>Can select the graph to plot in real time or XY plot</p><p><span style=" font-size:10pt;">Sample real-time packet with 3 curves XYZ:</span></p><p>{<span style=" color:#ff0000;">P0|X|255,0,0|100</span><span style=" color:#00ff7f;">|Y|0,255,0|150</span><span style=" color:#5555ff;">|Z|0,0,255|200</span>}</p><p>{Plot ID|Curve 1|Color|Value|Curve 2|Color|Value}</p><p><span style=" font-weight:600;">Note: color is in RGB format with comma seperating the values (R,G,B)</span></p><p><span style=" font-size:10pt;">Sample XY plot (supports only one curve):</span></p><p>{P0|Some XY plot|255,0,0|1 255 2 200 3 150 4 100}</p><p>{Plot ID|Curve name|Color|X Y X Y X Y X Y.....}</p><p><span style=" font-weight:600;">Note: If for each X value there won't be Y value, the plot will be ignored</span><br/></p></body></html>
162 |
163 |
164 | Type:
165 |
166 |
167 |
168 | -
169 |
170 |
-
171 |
172 | Time plot
173 |
174 |
175 | -
176 |
177 | XY-Plot
178 |
179 |
180 |
181 |
182 | -
183 |
184 |
185 | Title
186 |
187 |
188 |
189 | -
190 |
191 |
192 | A Simple Plotting Demonstration
193 |
194 |
195 |
196 | -
197 |
198 |
199 | <html><head/><body><p>Applicable only to real time plot, basically, how many data points will be stored in the memory before deleting them. </p></body></html>
200 |
201 |
202 | Buffer
203 |
204 |
205 |
206 | -
207 |
208 |
209 | 10
210 |
211 |
212 | 1000000
213 |
214 |
215 | 100
216 |
217 |
218 |
219 | -
220 |
221 |
222 | <html><head/><body><p>How often the plot will be updated. You shouldn't need less than 50ms, however if you want to improve performance of the application, it is advisable to increase the refresh rate. </p></body></html>
223 |
224 |
225 | Refresh rate (ms)
226 |
227 |
228 |
229 | -
230 |
231 |
232 | 10
233 |
234 |
235 | 10000
236 |
237 |
238 | 50
239 |
240 |
241 |
242 | -
243 |
244 |
245 | Name of X Axis:
246 |
247 |
248 |
249 | -
250 |
251 |
252 | -
253 |
254 |
255 | Name of Y Axis
256 |
257 |
258 |
259 | -
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 | -
268 |
269 |
270 | Scaling
271 |
272 |
273 |
-
274 |
275 |
276 | QFormLayout::AllNonFixedFieldsGrow
277 |
278 |
-
279 |
280 |
281 | Automatically scales the graph to show all values on Y axis
282 |
283 |
284 | Auto Scaling Y
285 |
286 |
287 | true
288 |
289 |
290 |
291 | -
292 |
293 |
294 | Min Y
295 |
296 |
297 |
298 | -
299 |
300 |
301 | -10000000.000000000000000
302 |
303 |
304 | 10000000.000000000000000
305 |
306 |
307 | -200.000000000000000
308 |
309 |
310 |
311 | -
312 |
313 |
314 | Max Y
315 |
316 |
317 |
318 | -
319 |
320 |
321 | -10000000.000000000000000
322 |
323 |
324 | 10000000.000000000000000
325 |
326 |
327 | 200.000000000000000
328 |
329 |
330 |
331 | -
332 |
333 |
334 | Automatically scales graph to include all X values (manual scaling works only on XY plot)
335 |
336 |
337 | Auto Scaling X
338 |
339 |
340 | true
341 |
342 |
343 |
344 | -
345 |
346 |
347 | Min X
348 |
349 |
350 |
351 | -
352 |
353 |
354 | -10000000.000000000000000
355 |
356 |
357 | 10000000.000000000000000
358 |
359 |
360 | -200.000000000000000
361 |
362 |
363 |
364 | -
365 |
366 |
367 | -10000000.000000000000000
368 |
369 |
370 | 10000000.000000000000000
371 |
372 |
373 | 200.000000000000000
374 |
375 |
376 |
377 | -
378 |
379 |
380 | Max X
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 | -
390 |
391 |
392 | Misc
393 |
394 |
395 |
-
396 |
397 |
-
398 |
399 |
400 | <html><head/><body><p>Format of the date in real time plot. Some of the available formats: </p><p><span style=" font-weight:600;">"dd:mm:yyyy | hh:mm:ss:zzz"</span></p><p>Where it shows<span style=" font-weight:600;"> day:month:year | hours:minutes:seconds:milliseconds</span></p></body></html>
401 |
402 |
403 |
404 |
405 |
406 | Date Format
407 |
408 |
409 |
410 | -
411 |
412 |
413 | hh:mm:ss
414 |
415 |
416 |
417 | -
418 |
419 |
420 | Automatically fills the graph
421 |
422 |
423 | Auto filling
424 |
425 |
426 | true
427 |
428 |
429 |
430 | -
431 |
432 |
433 | Auto Fill Opacity:
434 |
435 |
436 |
437 | -
438 |
439 |
440 | 20
441 |
442 |
443 | 100
444 |
445 |
446 |
447 | -
448 |
449 |
450 | Background Color:
451 |
452 |
453 |
454 | -
455 |
456 |
-
457 |
458 |
459 | Qt::Horizontal
460 |
461 |
462 |
463 | 40
464 | 20
465 |
466 |
467 |
468 |
469 | -
470 |
471 |
472 |
473 | 50
474 | 0
475 |
476 |
477 |
478 |
479 | 50
480 | 16777215
481 |
482 |
483 |
484 | background-color:#ffffff;
485 | border: 2px solid #000;
486 |
487 |
488 |
489 |
490 |
491 |
492 | -
493 |
494 |
495 | Choose background color
496 |
497 |
498 |
499 |
500 |
501 |
502 | :/images/kcoloredit.png:/images/kcoloredit.png
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 | -
514 |
515 |
516 |
517 | 0
518 | 0
519 |
520 |
521 |
522 |
523 | 0
524 | 0
525 |
526 |
527 |
528 | Auto Write
529 |
530 |
531 |
-
532 |
533 |
-
534 |
535 |
536 | Will write all results directly to the file you have specified. Similar to save button, but does it instantly and automatically. Useful for when one needs to do analysis later. Results will be in CSV
537 |
538 |
539 | Write To File
540 |
541 |
542 |
543 | -
544 |
545 |
546 | File:
547 |
548 |
549 |
550 | -
551 |
552 |
-
553 |
554 |
555 | true
556 |
557 |
558 |
559 | -
560 |
561 |
562 |
563 |
564 |
565 |
566 | :/images/document-open-folder.png:/images/document-open-folder.png
567 |
568 |
569 |
570 |
571 |
572 | -
573 |
574 |
575 | Specify what seperator should the save and auto file write function use
576 |
577 |
578 | Seperator:
579 |
580 |
581 |
582 | -
583 |
584 |
585 | ;
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 | QwtPlot
607 | QWidget
608 |
609 | 1
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
--------------------------------------------------------------------------------