diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ add_executable(${PROGRAM_NAME} WIN32 src/demoreader.cpp src/framedreader.cpp src/framedreadersettings.cpp + src/plotmanager.cpp misc/windows_icon.rc ${UI_FILES} ${RES_FILES} diff --git a/serialplot.pro b/serialplot.pro --- a/serialplot.pro +++ b/serialplot.pro @@ -65,7 +65,8 @@ SOURCES += \ src/asciireadersettings.cpp \ src/asciireader.cpp \ src/demoreader.cpp \ - src/framedreader.cpp + src/framedreader.cpp \ + src/plotmanager.cpp HEADERS += \ src/mainwindow.h \ @@ -101,7 +102,8 @@ HEADERS += \ src/asciireadersettings.h \ src/asciireader.h \ src/demoreader.h \ - src/framedreader.h + src/framedreader.h \ + src/plotmanager.h FORMS += \ src/mainwindow.ui \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -50,11 +50,14 @@ MainWindow::MainWindow(QWidget *parent) aboutDialog(this), portControl(&serialPort), channelMan(1, 1, this), + snapshotMan(this, &channelMan), commandPanel(&serialPort), - dataFormatPanel(&serialPort, &channelMan), - snapshotMan(this, &channelMan) + dataFormatPanel(&serialPort, &channelMan) { ui->setupUi(this); + + plotMan = new PlotManager(ui->plotArea); + ui->tabWidget->insertTab(0, &portControl, "Port"); ui->tabWidget->insertTab(1, &dataFormatPanel, "Data Format"); ui->tabWidget->insertTab(2, &plotControlPanel, "Plot"); @@ -78,7 +81,7 @@ MainWindow::MainWindow(QWidget *parent) setupAboutDialog(); // init view menu - for (auto a : ui->plot->menuActions()) + for (auto a : plotMan->menuActions()) { ui->menuView->addAction(a); } @@ -114,13 +117,13 @@ MainWindow::MainWindow(QWidget *parent) this, &MainWindow::onNumOfSamplesChanged); connect(&plotControlPanel, &PlotControlPanel::scaleChanged, - ui->plot, &Plot::setAxis); + plotMan, &PlotManager::setAxis); QObject::connect(ui->actionClear, SIGNAL(triggered(bool)), this, SLOT(clearPlot())); QObject::connect(snapshotMan.takeSnapshotAction(), &QAction::triggered, - ui->plot, &Plot::flashSnapshotOverlay); + plotMan, &PlotManager::flashSnapshotOverlay); // init port signals QObject::connect(&(this->serialPort), SIGNAL(error(QSerialPort::SerialPortError)), @@ -128,7 +131,7 @@ MainWindow::MainWindow(QWidget *parent) // init data format and reader QObject::connect(&dataFormatPanel, &DataFormatPanel::dataAdded, - ui->plot, &QwtPlot::replot); + plotMan, &PlotManager::replot); QObject::connect(ui->actionPause, &QAction::triggered, &dataFormatPanel, &DataFormatPanel::pause); @@ -154,16 +157,12 @@ MainWindow::MainWindow(QWidget *parent) // init curve list for (unsigned int i = 0; i < numOfChannels; i++) { - curves.append(new QwtPlotCurve(channelMan.channelName(i))); - curves[i]->setSamples( - new FrameBufferSeries(channelMan.channelBuffer(i))); - curves[i]->setPen(Plot::makeColor(i)); - curves[i]->attach(ui->plot); + plotMan->addCurve(channelMan.channelName(i), channelMan.channelBuffer(i)); } // init auto scale - ui->plot->setAxis(plotControlPanel.autoScale(), - plotControlPanel.yMin(), plotControlPanel.yMax()); + plotMan->setAxis(plotControlPanel.autoScale(), + plotControlPanel.yMin(), plotControlPanel.yMax()); // Init sps (sample per second) counter spsLabel.setText("0sps"); @@ -177,31 +176,19 @@ MainWindow::MainWindow(QWidget *parent) QObject::connect(ui->actionDemoMode, &QAction::toggled, this, &MainWindow::enableDemo); - { // init demo indicator - QwtText demoText(" DEMO RUNNING "); // looks better with spaces - demoText.setColor(QColor("white")); - demoText.setBackgroundBrush(Qt::darkRed); - demoText.setBorderRadius(4); - demoText.setRenderFlags(Qt::AlignLeft | Qt::AlignTop); - demoIndicator.setText(demoText); - demoIndicator.hide(); - demoIndicator.attach(ui->plot); - } + QObject::connect(ui->actionDemoMode, &QAction::toggled, + plotMan, &PlotManager::showDemoIndicator); } MainWindow::~MainWindow() { - for (auto curve : curves) - { - // also deletes respective FrameBuffer - delete curve; - } - if (serialPort.isOpen()) { serialPort.close(); } + delete plotMan; + delete ui; ui = NULL; // we check if ui is deleted in messageHandler } @@ -291,19 +278,19 @@ void MainWindow::clearPlot() { channelMan.channelBuffer(ci)->clear(); } - ui->plot->replot(); + plotMan->replot(); } void MainWindow::onNumOfSamplesChanged(int value) { numOfSamples = value; channelMan.setNumOfSamples(value); - ui->plot->replot(); + plotMan->replot(); } void MainWindow::onNumOfChannelsChanged(unsigned value) { - unsigned int oldNum = curves.size(); + unsigned int oldNum = plotMan->numOfCurves(); unsigned numOfChannels = value; if (numOfChannels > oldNum) @@ -311,24 +298,15 @@ void MainWindow::onNumOfChannelsChanged( // add new channels for (unsigned int i = oldNum; i < numOfChannels; i++) { - QwtPlotCurve* curve = new QwtPlotCurve(channelMan.channelName(i)); - curve->setSamples( - new FrameBufferSeries(channelMan.channelBuffer(i))); - curve->setPen(Plot::makeColor(i)); - curve->attach(ui->plot); - curves.append(curve); + plotMan->addCurve(channelMan.channelName(i), channelMan.channelBuffer(i)); } } else if(numOfChannels < oldNum) { - // remove channels - for (unsigned int i = 0; i < oldNum - numOfChannels; i++) - { - delete curves.takeLast(); - } + plotMan->removeCurves(oldNum - numOfChannels); } - ui->plot->replot(); + plotMan->replot(); } void MainWindow::onChannelNameChanged(unsigned channel, QString name) @@ -336,10 +314,9 @@ void MainWindow::onChannelNameChanged(un // This slot is triggered also when a new channel is added, in // this case curve list doesn't contain said channel. No worries, // since `onNumOfChannelsChanged` slot will update curve list. - if ((int) channel < curves.size()) // check if channel exists in curve list + if (channel < plotMan->numOfCurves()) // check if channel exists in curve list { - curves[channel]->setTitle(name); - ui->plot->replot(); + plotMan->setTitle(channel, name); } } @@ -360,9 +337,6 @@ void MainWindow::enableDemo(bool enabled if (!serialPort.isOpen()) { dataFormatPanel.enableDemo(true); - ui->actionDemoMode->setChecked(true); - demoIndicator.show(); - ui->plot->replot(); } else { @@ -373,8 +347,6 @@ void MainWindow::enableDemo(bool enabled { dataFormatPanel.enableDemo(false); ui->actionDemoMode->setChecked(false); - demoIndicator.hide(); - ui->plot->replot(); } } diff --git a/src/mainwindow.h b/src/mainwindow.h --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -32,7 +32,6 @@ #include #include #include -#include #include "portcontrol.h" #include "commandpanel.h" @@ -42,6 +41,7 @@ #include "framebuffer.h" #include "channelmanager.h" #include "snapshotmanager.h" +#include "plotmanager.h" namespace Ui { class MainWindow; @@ -70,19 +70,15 @@ private: unsigned int numOfSamples; QList curves; - // Note: FrameBuffer s are owned by their respective QwtPlotCurve s. - // QList channelBuffers; ChannelManager channelMan; + PlotManager* plotMan; + SnapshotManager snapshotMan; QLabel spsLabel; - CommandPanel commandPanel; DataFormatPanel dataFormatPanel; PlotControlPanel plotControlPanel; - SnapshotManager snapshotMan; - - QwtPlotTextLabel demoIndicator; bool isDemoRunning(); private slots: diff --git a/src/mainwindow.ui b/src/mainwindow.ui --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -16,7 +16,7 @@ - + 0 @@ -90,7 +90,7 @@ 0 0 653 - 27 + 20 @@ -201,12 +201,6 @@ - Plot - QWidget -
plot.h
- 1 -
- HidableTabWidget QTabWidget
hidabletabwidget.h
diff --git a/src/plot.cpp b/src/plot.cpp --- a/src/plot.cpp +++ b/src/plot.cpp @@ -29,12 +29,7 @@ Plot::Plot(QWidget* parent) : QwtPlot(parent), zoomer(this->canvas(), false), - sZoomer(this, &zoomer), - showGridAction("Grid", this), - showMinorGridAction("Minor Grid", this), - unzoomAction("Unzoom", this), - darkBackgroundAction("Dark Background", this), - showLegendAction("Legend", this) + sZoomer(this, &zoomer) { isAutoScaled = true; @@ -47,40 +42,17 @@ Plot::Plot(QWidget* parent) : showGrid(false); darkBackground(false); - showGridAction.setToolTip("Show Grid"); - showMinorGridAction.setToolTip("Show Minor Grid"); - unzoomAction.setToolTip("Unzoom the Plot"); - darkBackgroundAction.setToolTip("Enable Dark Plot Background"); - showLegendAction.setToolTip("Display the Legend on Plot"); - - showGridAction.setShortcut(QKeySequence("G")); - showMinorGridAction.setShortcut(QKeySequence("M")); - - showGridAction.setCheckable(true); - showMinorGridAction.setCheckable(true); - darkBackgroundAction.setCheckable(true); - showLegendAction.setCheckable(true); + snapshotOverlay = NULL; - showGridAction.setChecked(false); - showMinorGridAction.setChecked(false); - darkBackgroundAction.setChecked(false); - showLegendAction.setChecked(true); - - showMinorGridAction.setEnabled(false); - - connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), - this, &Plot::showGrid); - connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), - &showMinorGridAction, &QAction::setEnabled); - connect(&showMinorGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), - this, &Plot::showMinorGrid); - connect(&unzoomAction, &QAction::triggered, this, &Plot::unzoom); - connect(&darkBackgroundAction, SELECT::OVERLOAD_OF(&QAction::triggered), - this, &Plot::darkBackground); - connect(&showLegendAction, SELECT::OVERLOAD_OF(&QAction::triggered), - [this](bool enabled){legend.setVisible(enabled); replot();}); - - snapshotOverlay = NULL; + // init demo indicator + QwtText demoText(" DEMO RUNNING "); // looks better with spaces + demoText.setColor(QColor("white")); + demoText.setBackgroundBrush(Qt::darkRed); + demoText.setBorderRadius(4); + demoText.setRenderFlags(Qt::AlignLeft | Qt::AlignTop); + demoIndicator.setText(demoText); + demoIndicator.hide(); + demoIndicator.attach(this); } Plot::~Plot() @@ -102,17 +74,6 @@ void Plot::setAxis(bool autoScaled, doub resetAxes(); } -QList Plot::menuActions() -{ - QList actions; - actions << &showGridAction; - actions << &showMinorGridAction; - actions << &unzoomAction; - actions << &darkBackgroundAction; - actions << &showLegendAction; - return actions; -} - void Plot::resetAxes() { if (isAutoScaled) @@ -147,6 +108,18 @@ void Plot::showMinorGrid(bool show) replot(); } +void Plot::showLegend(bool show) +{ + legend.setVisible(show); + replot(); +} + +void Plot::showDemoIndicator(bool show) +{ + demoIndicator.setVisible(show); + replot(); +} + void Plot::unzoom() { zoomer.zoom(0); @@ -208,12 +181,12 @@ QColor Plot::makeColor(unsigned int chan } } -void Plot::flashSnapshotOverlay() +void Plot::flashSnapshotOverlay(bool light) { if (snapshotOverlay != NULL) delete snapshotOverlay; QColor color; - if (darkBackgroundAction.isChecked()) + if(light) { color = QColor(Qt::white); } diff --git a/src/plot.h b/src/plot.h --- a/src/plot.h +++ b/src/plot.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "zoomer.h" #include "scalezoomer.h" @@ -40,8 +41,6 @@ public: Plot(QWidget* parent = 0); ~Plot(); - QList menuActions(); - static QColor makeColor(unsigned int channelIndex); private: @@ -52,23 +51,25 @@ private: QwtPlotGrid grid; PlotSnapshotOverlay* snapshotOverlay; QwtPlotLegendItem legend; - - QAction showGridAction; - QAction showMinorGridAction; - QAction unzoomAction; - QAction darkBackgroundAction; - QAction showLegendAction; + QwtPlotTextLabel demoIndicator; void resetAxes(); public slots: void showGrid(bool show = true); void showMinorGrid(bool show = true); + void showLegend(bool show = true); + void showDemoIndicator(bool show = true); void unzoom(); void darkBackground(bool enabled = true); void setAxis(bool autoScaled, double yMin = 0, double yMax = 1); - void flashSnapshotOverlay(); + /** + * Displays an animation for snapshot. + * + * @param light show a light colored (white) animation or the opposite + */ + void flashSnapshotOverlay(bool light); private slots: void unzoomed(); diff --git a/src/plotcontrolpanel.cpp b/src/plotcontrolpanel.cpp --- a/src/plotcontrolpanel.cpp +++ b/src/plotcontrolpanel.cpp @@ -100,7 +100,6 @@ void PlotControlPanel::onAutoScaleChecke { if (checked) { - // ui->plot->setAxis(true); ui->lYmin->setEnabled(false); ui->lYmax->setEnabled(false); ui->spYmin->setEnabled(false); @@ -115,7 +114,6 @@ void PlotControlPanel::onAutoScaleChecke ui->spYmin->setEnabled(true); ui->spYmax->setEnabled(true); - // ui->plot->setAxis(false, ui->spYmin->value(), ui->spYmax->value()); emit scaleChanged(false, ui->spYmin->value(), ui->spYmax->value()); } } diff --git a/src/plotcontrolpanel.ui b/src/plotcontrolpanel.ui --- a/src/plotcontrolpanel.ui +++ b/src/plotcontrolpanel.ui @@ -7,7 +7,7 @@ 0 0 590 - 183 + 187 @@ -147,9 +147,6 @@
- - - @@ -157,6 +154,9 @@ + + +
diff --git a/src/plotmanager.cpp b/src/plotmanager.cpp new file mode 100644 --- /dev/null +++ b/src/plotmanager.cpp @@ -0,0 +1,366 @@ +/* + Copyright © 2016 Hasan Yavuz Özderya + + This file is part of serialplot. + + serialplot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + serialplot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with serialplot. If not, see . +*/ + +#include + +#include "plot.h" +#include "plotmanager.h" +#include "utils.h" + + +PlotManager::PlotManager(QWidget* plotArea, QObject *parent) : + QObject(parent), + _plotArea(plotArea), + showGridAction("Grid", this), + showMinorGridAction("Minor Grid", this), + unzoomAction("Unzoom", this), + darkBackgroundAction("Dark Background", this), + showLegendAction("Legend", this), + showMultiAction("Multi Plot", this) +{ + _autoScaled = true; + _yMin = 0; + _yMax = 1; + isDemoShown = false; + + // initalize layout and single widget + isMulti = false; + scrollArea = NULL; + setupLayout(isMulti); + addPlotWidget(); + + // initialize menu actions + showGridAction.setToolTip("Show Grid"); + showMinorGridAction.setToolTip("Show Minor Grid"); + unzoomAction.setToolTip("Unzoom the Plot"); + darkBackgroundAction.setToolTip("Enable Dark Plot Background"); + showLegendAction.setToolTip("Display the Legend on Plot"); + showMultiAction.setToolTip("Display All Channels Separately"); + + showGridAction.setShortcut(QKeySequence("G")); + showMinorGridAction.setShortcut(QKeySequence("M")); + + showGridAction.setCheckable(true); + showMinorGridAction.setCheckable(true); + darkBackgroundAction.setCheckable(true); + showLegendAction.setCheckable(true); + showMultiAction.setCheckable(true); + + showGridAction.setChecked(false); + showMinorGridAction.setChecked(false); + darkBackgroundAction.setChecked(false); + showLegendAction.setChecked(true); + showMultiAction.setChecked(false); + + showMinorGridAction.setEnabled(false); + + connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), + this, &PlotManager::showGrid); + connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), + &showMinorGridAction, &QAction::setEnabled); + connect(&showMinorGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), + this, &PlotManager::showMinorGrid); + connect(&unzoomAction, &QAction::triggered, this, &PlotManager::unzoom); + connect(&darkBackgroundAction, SELECT::OVERLOAD_OF(&QAction::triggered), + this, &PlotManager::darkBackground); + connect(&showLegendAction, SELECT::OVERLOAD_OF(&QAction::triggered), + this, &PlotManager::showLegend); + connect(&showLegendAction, SELECT::OVERLOAD_OF(&QAction::triggered), + this, &PlotManager::showLegend); + connect(&showMultiAction, SELECT::OVERLOAD_OF(&QAction::triggered), + this, &PlotManager::setMulti); +} + +PlotManager::~PlotManager() +{ + while (curves.size()) + { + delete curves.takeLast(); + } + + // remove all widgets + while (plotWidgets.size()) + { + delete plotWidgets.takeLast(); + } + + if (scrollArea != NULL) delete scrollArea; +} + +void PlotManager::setMulti(bool enabled) +{ + if (enabled == isMulti) return; + + isMulti = enabled; + + // detach all curves + for (auto curve : curves) + { + curve->detach(); + } + + // remove all widgets + while (plotWidgets.size()) + { + delete plotWidgets.takeLast(); + } + + // setup new layout + setupLayout(isMulti); + + if (isMulti) + { + // add new widgets and attach + for (auto curve : curves) + { + curve->attach(addPlotWidget()); + } + } + else + { + // add a single widget + auto plot = addPlotWidget(); + + // attach all curves + for (auto curve : curves) + { + curve->attach(plot); + } + } +} + +void PlotManager::setupLayout(bool multiPlot) +{ + // delete previous layout if it exists + if (_plotArea->layout() != 0) + { + delete _plotArea->layout(); + } + + if (multiPlot) + { + // setup a scroll area + scrollArea = new QScrollArea(); + auto scrolledPlotArea = new QWidget(scrollArea); + scrollArea->setWidget(scrolledPlotArea); + scrollArea->setWidgetResizable(true); + + _plotArea->setLayout(new QVBoxLayout()); + _plotArea->layout()->addWidget(scrollArea); + _plotArea->layout()->setContentsMargins(0,0,0,0); + + layout = new QVBoxLayout(scrolledPlotArea); + } + else + { + // delete scrollArea left from multi layout + if (scrollArea != NULL) + { + delete scrollArea; + scrollArea = NULL; + } + + layout = new QVBoxLayout(_plotArea); + } + + layout->setContentsMargins(2,2,2,2); + layout->setSpacing(1); +} + +Plot* PlotManager::addPlotWidget() +{ + auto plot = new Plot(); + plotWidgets.append(plot); + layout->addWidget(plot); + + plot->darkBackground(darkBackgroundAction.isChecked()); + plot->showGrid(showGridAction.isChecked()); + plot->showMinorGrid(showMinorGridAction.isChecked()); + plot->showLegend(showLegendAction.isChecked()); + plot->showDemoIndicator(isDemoShown); + plot->setAxis(_autoScaled, _yMin, _yMax); + + return plot; +} + +void PlotManager::addCurve(QString title, FrameBuffer* buffer) +{ + auto curve = new QwtPlotCurve(title); + curve->setSamples(new FrameBufferSeries(buffer)); + _addCurve(curve); +} + +void PlotManager::addCurve(QString title, QVector data) +{ + auto curve = new QwtPlotCurve(title); + curve->setSamples(data); + _addCurve(curve); +} + +void PlotManager::_addCurve(QwtPlotCurve* curve) +{ + // store and init the curve + curves.append(curve); + + unsigned index = curves.size()-1; + curve->setPen(Plot::makeColor(index)); + + // create the plot for the curve if we are on multi display + Plot* plot; + if (isMulti) + { + // create a new plot widget + plot = addPlotWidget(); + } + else + { + plot = plotWidgets[0]; + } + + // show the curve + curve->attach(plot); + plot->replot(); +} + +void PlotManager::removeCurves(unsigned number) +{ + for (unsigned i = 0; i < number; i++) + { + if (!curves.isEmpty()) + { + delete curves.takeLast(); + if (isMulti) // delete corresponding widget as well + { + delete plotWidgets.takeLast(); + } + } + } +} + +unsigned PlotManager::numOfCurves() +{ + return curves.size(); +} + +void PlotManager::setTitle(unsigned index, QString title) +{ + curves[index]->setTitle(title); + + plotWidget(index)->replot(); +} + +Plot* PlotManager::plotWidget(unsigned curveIndex) +{ + if (isMulti) + { + return plotWidgets[curveIndex]; + } + else + { + return plotWidgets[0]; + } +} + +void PlotManager::replot() +{ + for (auto plot : plotWidgets) + { + plot->replot(); + } +} + +QList PlotManager::menuActions() +{ + QList actions; + actions << &showGridAction; + actions << &showMinorGridAction; + actions << &unzoomAction; + actions << &darkBackgroundAction; + actions << &showLegendAction; + actions << &showMultiAction; + return actions; +} + +void PlotManager::showGrid(bool show) +{ + for (auto plot : plotWidgets) + { + plot->showGrid(show); + } +} + +void PlotManager::showMinorGrid(bool show) +{ + for (auto plot : plotWidgets) + { + plot->showMinorGrid(show); + } +} + +void PlotManager::showLegend(bool show) +{ + for (auto plot : plotWidgets) + { + plot->showLegend(show); + } +} + +void PlotManager::showDemoIndicator(bool show) +{ + isDemoShown = show; + for (auto plot : plotWidgets) + { + plot->showDemoIndicator(show); + } +} + +void PlotManager::unzoom() +{ + for (auto plot : plotWidgets) + { + plot->unzoom(); + } +} + +void PlotManager::darkBackground(bool enabled) +{ + for (auto plot : plotWidgets) + { + plot->darkBackground(enabled); + } +} + +void PlotManager::setAxis(bool autoScaled, double yAxisMin, double yAxisMax) +{ + _autoScaled = autoScaled; + _yMin = yAxisMin; + _yMax = yAxisMax; + for (auto plot : plotWidgets) + { + plot->setAxis(autoScaled, yAxisMin, yAxisMax); + } +} + +void PlotManager::flashSnapshotOverlay() +{ + for (auto plot : plotWidgets) + { + plot->flashSnapshotOverlay(darkBackgroundAction.isChecked()); + } +} diff --git a/src/plotmanager.h b/src/plotmanager.h new file mode 100644 --- /dev/null +++ b/src/plotmanager.h @@ -0,0 +1,102 @@ +/* + Copyright © 2016 Hasan Yavuz Özderya + + This file is part of serialplot. + + serialplot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + serialplot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with serialplot. If not, see . +*/ + +#ifndef PLOTMANAGER_H +#define PLOTMANAGER_H + +#include +#include +#include +#include +#include + +#include +#include "plot.h" +#include "framebufferseries.h" + +class PlotManager : public QObject +{ + Q_OBJECT + +public: + explicit PlotManager(QWidget* plotArea, QObject *parent = 0); + ~PlotManager(); + /// Add a new curve with title and buffer. A color is + /// automatically chosen for curve. + void addCurve(QString title, FrameBuffer* buffer); + /// Alternative of `addCurve` for static curve data (snapshots). + void addCurve(QString title, QVector data); + /// Set the displayed title for a curve + void setTitle(unsigned index, QString title); + /// Removes curves from the end + void removeCurves(unsigned number); + /// Returns current number of curves known by plot manager + unsigned numOfCurves(); + /// Returns the list of actions to be inserted into the `View` menu + QList menuActions(); + +public slots: + /// Enable/Disable multiple plot display + void setMulti(bool enabled); + /// Update all plot widgets + void replot(); + /// Enable display of a "DEMO" label on each plot + void showDemoIndicator(bool show = true); + /// Set the Y axis + void setAxis(bool autoScaled, double yMin = 0, double yMax = 1); + /// Display an animation for snapshot + void flashSnapshotOverlay(); + +private: + bool isMulti; + QWidget* _plotArea; + QVBoxLayout* layout; ///< layout of the `plotArea` + QScrollArea* scrollArea; + QList curves; + QList plotWidgets; + bool isDemoShown; + bool _autoScaled; + double _yMin; + double _yMax; + + // menu actions + QAction showGridAction; + QAction showMinorGridAction; + QAction unzoomAction; + QAction darkBackgroundAction; + QAction showLegendAction; + QAction showMultiAction; + + void setupLayout(bool multiPlot); + /// Inserts a new plot widget to the current layout. + Plot* addPlotWidget(); + /// Returns the plot widget that given curve is attached to + Plot* plotWidget(unsigned curveIndex); + /// Common part of overloaded `addCurve` functions + void _addCurve(QwtPlotCurve* curve); + +private slots: + void showGrid(bool show = true); + void showMinorGrid(bool show = true); + void showLegend(bool show = true); + void unzoom(); + void darkBackground(bool enabled = true); +}; + +#endif // PLOTMANAGER_H diff --git a/src/snapshotview.cpp b/src/snapshotview.cpp --- a/src/snapshotview.cpp +++ b/src/snapshotview.cpp @@ -28,18 +28,17 @@ SnapshotView::SnapshotView(QWidget *pare _snapshot = snapshot; ui->setupUi(this); + + plotMan = new PlotManager(ui->plotArea); + ui->menuSnapshot->insertAction(ui->actionClose, snapshot->deleteAction()); this->setWindowTitle(snapshot->name()); + // initialize curves unsigned numOfChannels = snapshot->data.size(); - for (unsigned ci = 0; ci < numOfChannels; ci++) { - QwtPlotCurve* curve = new QwtPlotCurve(snapshot->channelName(ci)); - curves.append(curve); - curve->setSamples(snapshot->data[ci]); - curve->setPen(Plot::makeColor(ci)); - curve->attach(ui->plot); + plotMan->addCurve(snapshot->channelName(ci), snapshot->data[ci]); } renameDialog.setWindowTitle("Rename Snapshot"); @@ -50,7 +49,7 @@ SnapshotView::SnapshotView(QWidget *pare connect(ui->actionExport, &QAction::triggered, this, &SnapshotView::save); - for (auto a : ui->plot->menuActions()) + for (auto a : plotMan->menuActions()) { ui->menuView->addAction(a); } diff --git a/src/snapshotview.h b/src/snapshotview.h --- a/src/snapshotview.h +++ b/src/snapshotview.h @@ -29,7 +29,7 @@ #include #include -#include "plot.h" +#include "plotmanager.h" #include "snapshot.h" namespace Ui { @@ -52,6 +52,7 @@ private: QList curves; Snapshot* _snapshot; QInputDialog renameDialog; + PlotManager* plotMan; void closeEvent(QCloseEvent *event); diff --git a/src/snapshotview.ui b/src/snapshotview.ui --- a/src/snapshotview.ui +++ b/src/snapshotview.ui @@ -16,7 +16,7 @@ - + @@ -26,7 +26,7 @@ 0 0 544 - 27 + 20 @@ -73,14 +73,6 @@ - - - Plot - QWidget -
plot.h
- 1 -
-