mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-15 05:22:53 +08:00
Implement multiplot widget (##33)
This commit is contained in:
parent
410ed97eb3
commit
4779f704bb
@ -21,3 +21,156 @@
|
||||
*/
|
||||
|
||||
#include "MultiPlot.h"
|
||||
#include "CSV/Player.h"
|
||||
#include "UI/Dashboard.h"
|
||||
#include "Misc/ThemeManager.h"
|
||||
|
||||
using namespace Widgets;
|
||||
|
||||
/**
|
||||
* Constructor function, configures widget style & signal/slot connections.
|
||||
*/
|
||||
MultiPlot::MultiPlot(const int index)
|
||||
: m_index(index)
|
||||
{
|
||||
// Get pointers to serial studio modules
|
||||
auto dash = UI::Dashboard::getInstance();
|
||||
auto theme = Misc::ThemeManager::getInstance();
|
||||
|
||||
// Invalid index, abort initialization
|
||||
if (m_index < 0 || m_index >= dash->multiPlotCount())
|
||||
return;
|
||||
|
||||
// Set window palette
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Base, theme->datasetWindowBackground());
|
||||
palette.setColor(QPalette::Window, theme->datasetWindowBackground());
|
||||
setPalette(palette);
|
||||
|
||||
// Set plot palette
|
||||
palette.setColor(QPalette::Base, theme->base());
|
||||
palette.setColor(QPalette::Highlight, QColor("#f00"));
|
||||
palette.setColor(QPalette::Text, theme->widgetIndicator1());
|
||||
palette.setColor(QPalette::Dark, theme->widgetIndicator1());
|
||||
palette.setColor(QPalette::Light, theme->widgetIndicator1());
|
||||
palette.setColor(QPalette::ButtonText, theme->widgetIndicator1());
|
||||
palette.setColor(QPalette::WindowText, theme->widgetIndicator1());
|
||||
m_plot.setPalette(palette);
|
||||
m_plot.setCanvasBackground(theme->base());
|
||||
m_plot.setFrameStyle(QFrame::Plain);
|
||||
|
||||
// Configure layout
|
||||
m_layout.addWidget(&m_plot);
|
||||
m_layout.setContentsMargins(24, 24, 24, 24);
|
||||
setLayout(&m_layout);
|
||||
|
||||
// Create curves from datasets
|
||||
auto group = dash->getMultiplot(m_index);
|
||||
QVector<QString> colors = theme->widgetColors();
|
||||
for (int i = 0; i < group->datasetCount(); ++i)
|
||||
{
|
||||
// Get title
|
||||
QString title = tr("Unknown");
|
||||
if (group->getDataset(i))
|
||||
title = group->getDataset(i)->title();
|
||||
|
||||
// Create curve
|
||||
auto curve = new QwtPlotCurve(title);
|
||||
|
||||
// Get curve color
|
||||
QString color;
|
||||
if (colors.count() > i)
|
||||
color = colors.at(i);
|
||||
else if (i > 0)
|
||||
color = colors.at(colors.count() % i);
|
||||
|
||||
// Configure curve
|
||||
curve->setPen(QColor(color), 2, Qt::SolidLine);
|
||||
curve->attach(&m_plot);
|
||||
|
||||
// Register curve
|
||||
m_curves.append(curve);
|
||||
}
|
||||
|
||||
// Add plot legend to display curve names
|
||||
m_legend.setFrameStyle(QFrame::Plain);
|
||||
m_plot.insertLegend(&m_legend, QwtPlot::BottomLegend);
|
||||
|
||||
// Show plot
|
||||
updateRange();
|
||||
m_plot.replot();
|
||||
m_plot.show();
|
||||
|
||||
// React to dashboard events
|
||||
connect(dash, SIGNAL(updated()), this, SLOT(updateData()));
|
||||
connect(dash, SIGNAL(pointsChanged()), this, SLOT(updateRange()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the widget is enabled, if so, the widget shall be updated
|
||||
* to display the latest data frame.
|
||||
*
|
||||
* If the widget is disabled (e.g. the user hides it, or the external
|
||||
* window is hidden), then the new data shall be saved to the plot
|
||||
* vector, but the widget shall not be redrawn.
|
||||
*/
|
||||
void MultiPlot::updateData()
|
||||
{
|
||||
// Get group
|
||||
auto group = UI::Dashboard::getInstance()->getMultiplot(m_index);
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
// Plot each dataset
|
||||
for (int i = 0; i < group->datasetCount(); ++i)
|
||||
{
|
||||
// Get dataset
|
||||
auto dataset = group->getDataset(i);
|
||||
if (!dataset)
|
||||
continue;
|
||||
|
||||
// Add point to plot data
|
||||
memmove(m_yData[i].data(), m_yData[i].data() + 1,
|
||||
m_yData[i].count() * sizeof(double));
|
||||
m_yData[i][m_yData[i].count() - 1] = dataset->value().toDouble();
|
||||
|
||||
// Widget not enabled, do not redraw
|
||||
if (!isEnabled())
|
||||
continue;
|
||||
|
||||
// Plot new data
|
||||
m_curves.at(i)->setSamples(m_xData, m_yData[i]);
|
||||
}
|
||||
|
||||
// Plot widget again
|
||||
if (isEnabled())
|
||||
m_plot.replot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the number of horizontal divisions of the plot
|
||||
*/
|
||||
void MultiPlot::updateRange()
|
||||
{
|
||||
// Get pointer to dashboard manager
|
||||
auto dash = UI::Dashboard::getInstance();
|
||||
|
||||
// Set number of points
|
||||
m_xData.clear();
|
||||
m_yData.clear();
|
||||
m_xData.reserve(dash->points());
|
||||
auto group = UI::Dashboard::getInstance()->getMultiplot(m_index);
|
||||
for (int i = 0; i < dash->points(); ++i)
|
||||
{
|
||||
m_xData.append(i);
|
||||
m_yData.append(QVector<double>());
|
||||
m_yData[i].reserve(dash->points());
|
||||
for (int j = 0; j < dash->points(); ++j)
|
||||
m_yData[i].append(0);
|
||||
}
|
||||
|
||||
// Create curve from data
|
||||
for (int i = 0; i < group->datasetCount(); ++i)
|
||||
if (m_curves.count() > i)
|
||||
m_curves.at(i)->setSamples(m_xData, m_yData[i]);
|
||||
}
|
||||
|
@ -23,4 +23,35 @@
|
||||
#ifndef WIDGETS_MULTIPLOT_H
|
||||
#define WIDGETS_MULTIPLOT_H
|
||||
|
||||
#include <QwtPlot>
|
||||
#include <QWidget>
|
||||
#include <QwtLegend>
|
||||
#include <QComboBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QwtPlotCurve>
|
||||
|
||||
namespace Widgets
|
||||
{
|
||||
class MultiPlot : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MultiPlot(const int index = -1);
|
||||
|
||||
private slots:
|
||||
void updateData();
|
||||
void updateRange();
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
QwtPlot m_plot;
|
||||
QwtLegend m_legend;
|
||||
QVBoxLayout m_layout;
|
||||
QVector<double> m_xData;
|
||||
QVector<QwtPlotCurve *> m_curves;
|
||||
QVector<QVector<double>> m_yData;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -21,14 +21,17 @@
|
||||
*/
|
||||
|
||||
#include "Plot.h"
|
||||
#include "CSV/Player.h"
|
||||
#include "UI/Dashboard.h"
|
||||
#include "Misc/ThemeManager.h"
|
||||
|
||||
using namespace Widgets;
|
||||
|
||||
/**
|
||||
* Constructor function, configures widget style & signal/slot connections.
|
||||
*/
|
||||
Plot::Plot(const int index)
|
||||
: m_index(index)
|
||||
, m_count(0)
|
||||
{
|
||||
// Get pointers to serial studio modules
|
||||
auto dash = UI::Dashboard::getInstance();
|
||||
@ -69,7 +72,7 @@ Plot::Plot(const int index)
|
||||
|
||||
// Get curve color
|
||||
QString color;
|
||||
auto colors = theme->widgetColors();
|
||||
QVector<QString> colors = theme->widgetColors();
|
||||
if (colors.count() > m_index)
|
||||
color = colors.at(m_index);
|
||||
else
|
||||
@ -80,7 +83,7 @@ Plot::Plot(const int index)
|
||||
|
||||
// Lazy widgets, get initial properties from dataset
|
||||
#ifdef LAZY_WIDGETS
|
||||
auto dataset = UI::Dashboard::getInstance()->getBar(m_index);
|
||||
auto dataset = UI::Dashboard::getInstance()->getPlot(m_index);
|
||||
if (dataset)
|
||||
{
|
||||
// Set max/min values
|
||||
@ -102,6 +105,14 @@ Plot::Plot(const int index)
|
||||
connect(dash, SIGNAL(pointsChanged()), this, SLOT(updateRange()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the widget is enabled, if so, the widget shall be updated
|
||||
* to display the latest data frame.
|
||||
*
|
||||
* If the widget is disabled (e.g. the user hides it, or the external
|
||||
* window is hidden), then the new data shall be saved to the plot
|
||||
* vector, but the widget shall not be redrawn.
|
||||
*/
|
||||
void Plot::updateData()
|
||||
{
|
||||
auto dataset = UI::Dashboard::getInstance()->getPlot(m_index);
|
||||
@ -115,7 +126,7 @@ void Plot::updateData()
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
// Update plot properties
|
||||
// Update plot properties
|
||||
#ifndef LAZY_WIDGETS
|
||||
// Set max/min values
|
||||
auto min = dataset->min();
|
||||
@ -136,6 +147,9 @@ void Plot::updateData()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the number of horizontal divisions of the plot
|
||||
*/
|
||||
void Plot::updateRange()
|
||||
{
|
||||
// Get pointer to dashboard manager
|
||||
|
@ -44,7 +44,6 @@ private slots:
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
int m_count;
|
||||
QwtPlot m_plot;
|
||||
QwtPlotCurve m_curve;
|
||||
QVBoxLayout m_layout;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "Compass.h"
|
||||
#include "DataGroup.h"
|
||||
#include "Gyroscope.h"
|
||||
#include "MultiPlot.h"
|
||||
#include "Accelerometer.h"
|
||||
|
||||
#include <QPushButton>
|
||||
@ -237,7 +238,7 @@ void WidgetLoader::setWidgetIndex(const int index)
|
||||
m_widget = new DataGroup(relativeIndex());
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::MultiPlot:
|
||||
m_widget = new QPushButton("Multi-Plot");
|
||||
m_widget = new MultiPlot(relativeIndex());
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Plot:
|
||||
m_widget = new Plot(relativeIndex());
|
||||
|
Loading…
x
Reference in New Issue
Block a user