@@ -30,24 +30,25 @@
static const int SYMBOL_SHOW_AT_WIDTH = 5;
static const int SYMBOL_SIZE_MAX = 7;
Plot::Plot(QWidget* parent) :
QwtPlot(parent),
zoomer(this->canvas(), false),
sZoomer(this, &zoomer)
{
isAutoScaled = true;
symbolSize = 0;
numOfSamples = 1;
showSymbols = ShowSymbolsAuto;
QObject::connect(&zoomer, &Zoomer::unzoomed, this, &Plot::unzoomed);
zoomer.setZoomBase();
grid.attach(this);
legend.attach(this);
showGrid(false);
darkBackground(false);
snapshotOverlay = NULL;
@@ -238,44 +239,72 @@ void Plot::flashSnapshotOverlay(bool lig
color = QColor(Qt::black);
}
snapshotOverlay = new PlotSnapshotOverlay(this->canvas(), color);
connect(snapshotOverlay, &PlotSnapshotOverlay::done,
[this]()
delete snapshotOverlay;
});
void Plot::setSymbols(ShowSymbols shown)
showSymbols = shown;
if (showSymbols == ShowSymbolsAuto)
calcSymbolSize();
else if (showSymbols == ShowSymbolsAlways)
symbolSize = SYMBOL_SIZE_MAX;
else
updateSymbols();
replot();
void Plot::onXScaleChanged()
void Plot::calcSymbolSize()
auto sw = axisWidget(QwtPlot::xBottom);
auto paintDist = sw->scaleDraw()->scaleMap().pDist();
auto scaleDist = sw->scaleDraw()->scaleMap().sDist();
auto fullScaleDist = zoomer.zoomBase().width();
auto zoomRate = fullScaleDist / scaleDist;
float samplesInView = numOfSamples / zoomRate;
int symDisPx = round(paintDist / samplesInView);
if (symDisPx < SYMBOL_SHOW_AT_WIDTH)
symbolSize = std::min(SYMBOL_SIZE_MAX, symDisPx-SYMBOL_SHOW_AT_WIDTH+1);
void Plot::updateSymbols()
const QwtPlotItemList curves = itemList( QwtPlotItem::Rtti_PlotCurve );
if (curves.size() > 0)
for (int i = 0; i < curves.size(); i++)
QwtSymbol* symbol = NULL;
QwtPlotCurve* curve = static_cast<QwtPlotCurve*>(curves[i]);
@@ -288,17 +317,17 @@ void Plot::updateSymbols()
curve->setSymbol(symbol);
void Plot::resizeEvent(QResizeEvent * event)
QwtPlot::resizeEvent(event);
onXScaleChanged();
void Plot::onNumOfSamplesChanged(unsigned value)
void Plot::setNumOfSamples(unsigned value)
numOfSamples = value;
@@ -24,69 +24,79 @@
#include <QList>
#include <QAction>
#include <qwt_plot.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_shapeitem.h>
#include <qwt_plot_legenditem.h>
#include <qwt_plot_textlabel.h>
#include "zoomer.h"
#include "scalezoomer.h"
#include "plotsnapshotoverlay.h"
enum ShowSymbols
ShowSymbolsAuto,
ShowSymbolsAlways,
ShowSymbolsNever
};
class Plot : public QwtPlot
Q_OBJECT
friend class PlotManager;
public:
Plot(QWidget* parent = 0);
~Plot();
static QColor makeColor(unsigned int channelIndex);
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 setYAxis(bool autoScaled, double yMin = 0, double yMax = 1);
void setXAxis(double xMin, double xMax);
void setSymbols(ShowSymbols shown);
/**
* Displays an animation for snapshot.
*
* @param light show a light colored (white) animation or the opposite
*/
void flashSnapshotOverlay(bool light);
void onNumOfSamplesChanged(unsigned value);
void setNumOfSamples(unsigned value);
protected:
/// update the display of symbols depending on `symbolSize`
void updateSymbols();
private:
bool isAutoScaled;
double yMin, yMax;
double _xMin, _xMax;
unsigned numOfSamples;
int symbolSize;
Zoomer zoomer;
ScaleZoomer sZoomer;
QwtPlotGrid grid;
PlotSnapshotOverlay* snapshotOverlay;
QwtPlotLegendItem legend;
QwtPlotTextLabel demoIndicator;
ShowSymbols showSymbols;
void resetAxes();
void resizeEvent(QResizeEvent * event);
void calcSymbolSize();
private slots:
void unzoomed();
void onXScaleChanged();
#endif // PLOT_H
@@ -8,79 +8,114 @@
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 <http://www.gnu.org/licenses/>.
#include <QActionGroup>
#include "qwt_symbol.h"
#include "plot.h"
#include "plotmanager.h"
#include "utils.h"
#include "setting_defines.h"
PlotManager::PlotManager(QWidget* plotArea, ChannelInfoModel* infoModel, 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)
showMultiAction("Multi &Plot", this),
setSymbolsAction("Symbols", this)
_autoScaled = true;
_yMin = 0;
_yMax = 1;
isDemoShown = false;
_infoModel = infoModel;
_numOfSamples = 1;
// 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");
setSymbolsAction.setToolTip("Show/Hide symbols");
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);
// setup symbols menu
auto setSymbolAutoAct = setSymbolsMenu.addAction("Show When Zoomed");
setSymbolAutoAct->setCheckable(true);
setSymbolAutoAct->setChecked(true);
connect(setSymbolAutoAct, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
[this](bool checked)
if (checked) setSymbols(ShowSymbolsAuto);
auto setSymbolAlwaysAct = setSymbolsMenu.addAction("Always Show");
setSymbolAlwaysAct->setCheckable(true);
connect(setSymbolAlwaysAct, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
if (checked) setSymbols(ShowSymbolsAlways);
auto setSymbolHideAct = setSymbolsMenu.addAction("Always Hide");
setSymbolHideAct->setCheckable(true);
connect(setSymbolHideAct, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
if (checked) setSymbols(ShowSymbolsNever);
setSymbolsAction.setMenu(&setSymbolsMenu);
// add symbol actions to same group so that they appear as radio buttons
auto group = new QActionGroup(this);
group->addAction(setSymbolAutoAct);
group->addAction(setSymbolAlwaysAct);
group->addAction(setSymbolHideAct);
connect(&showGridAction, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
this, &PlotManager::showGrid);
&showMinorGridAction, &QAction::setEnabled);
connect(&showMinorGridAction, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
this, &PlotManager::showMinorGrid);
connect(&unzoomAction, &QAction::triggered, this, &PlotManager::unzoom);
connect(&darkBackgroundAction, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
this, &PlotManager::darkBackground);
connect(&showLegendAction, SELECT<bool>::OVERLOAD_OF(&QAction::triggered),
this, &PlotManager::showLegend);
@@ -243,24 +278,26 @@ void PlotManager::setupLayout(bool multi
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->setYAxis(_autoScaled, _yMin, _yMax);
plot->setNumOfSamples(_numOfSamples);
plot->setSymbols(showSymbols);
if (_xAxisAsIndex)
plot->setXAxis(0, _numOfSamples);
plot->setXAxis(_xMin, _xMax);
return plot;
@@ -354,24 +391,25 @@ void PlotManager::replot()
QList<QAction*> PlotManager::menuActions()
QList<QAction*> actions;
actions << &showGridAction;
actions << &showMinorGridAction;
actions << &unzoomAction;
actions << &darkBackgroundAction;
actions << &showLegendAction;
actions << &showMultiAction;
actions << &setSymbolsAction;
return actions;
void PlotManager::showGrid(bool show)
for (auto plot : plotWidgets)
plot->showGrid(show);
void PlotManager::showMinorGrid(bool show)
@@ -406,24 +444,33 @@ void PlotManager::unzoom()
plot->unzoom();
void PlotManager::darkBackground(bool enabled)
plot->darkBackground(enabled);
void PlotManager::setSymbols(ShowSymbols shown)
plot->setSymbols(shown);
void PlotManager::setYAxis(bool autoScaled, double yAxisMin, double yAxisMax)
_autoScaled = autoScaled;
_yMin = yAxisMin;
_yMax = yAxisMax;
plot->setYAxis(autoScaled, yAxisMin, yAxisMax);
void PlotManager::setXAxis(bool asIndex, double xMin, double xMax)
@@ -455,25 +502,25 @@ void PlotManager::flashSnapshotOverlay()
plot->flashSnapshotOverlay(darkBackgroundAction.isChecked());
void PlotManager::onNumOfSamplesChanged(unsigned value)
_numOfSamples = value;
plot->onNumOfSamplesChanged(value);
plot->setNumOfSamples(value);
if (_xAxisAsIndex) plot->setXAxis(0, value);
void PlotManager::saveSettings(QSettings* settings)
settings->beginGroup(SettingGroup_Plot);
settings->setValue(SG_Plot_DarkBackground, darkBackgroundAction.isChecked());
settings->setValue(SG_Plot_Grid, showGridAction.isChecked());
settings->setValue(SG_Plot_MinorGrid, showMinorGridAction.isChecked());
settings->setValue(SG_Plot_Legend, showLegendAction.isChecked());
settings->setValue(SG_Plot_MultiPlot, showMultiAction.isChecked());
@@ -17,24 +17,26 @@
#ifndef PLOTMANAGER_H
#define PLOTMANAGER_H
#include <QObject>
#include <QWidget>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QSettings>
#include <QMenu>
#include <qwt_plot_curve.h>
#include "framebufferseries.h"
#include "channelinfomodel.h"
class PlotManager : public QObject
explicit PlotManager(QWidget* plotArea, ChannelInfoModel* infoModel = NULL, QObject *parent = 0);
@@ -80,40 +82,44 @@ private:
QScrollArea* scrollArea;
QList<QwtPlotCurve*> curves;
QList<Plot*> plotWidgets;
ChannelInfoModel* _infoModel;
bool isDemoShown;
bool _autoScaled;
double _yMin;
double _yMax;
bool _xAxisAsIndex;
double _xMin;
double _xMax;
unsigned _numOfSamples;
// menu actions
QAction showGridAction;
QAction showMinorGridAction;
QAction unzoomAction;
QAction darkBackgroundAction;
QAction showLegendAction;
QAction showMultiAction;
QAction setSymbolsAction;
QMenu setSymbolsMenu;
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);
void onChannelInfoChanged(const QModelIndex & topLeft,
const QModelIndex & bottomRight,
const QVector<int> & roles = QVector<int> ());
Status change: