##// END OF EJS Templates
Merge branch 'feature/VariableModel4' into develop
Alexandre Leroux -
r185:fa2e26651269 merge
parent child
Show More
@@ -0,0 +1,30
1 #ifndef SCIQLOP_GRAPHPLOTTABLESFACTORY_H
2 #define SCIQLOP_GRAPHPLOTTABLESFACTORY_H
3
4 #include <QLoggingCategory>
5 #include <QVector>
6
7 Q_DECLARE_LOGGING_CATEGORY(LOG_GraphPlottablesFactory)
8
9 class QCPAbstractPlottable;
10 class QCustomPlot;
11 class Variable;
12
13 /**
14 * @brief The GraphPlottablesFactory class aims to create the QCustomPlot components relative to a
15 * variable, depending on the data series of this variable
16 */
17 struct GraphPlottablesFactory {
18 /**
19 * Creates (if possible) the QCustomPlot components relative to the variable passed in
20 * parameter, and adds these to the plot passed in parameter.
21 * @param variable the variable for which to create the components
22 * @param plot the plot in which to add the created components. It takes ownership of these
23 * components.
24 * @return the list of the components created
25 */
26 static QVector<QCPAbstractPlottable *> create(const Variable *variable,
27 QCustomPlot &plot) noexcept;
28 };
29
30 #endif // SCIQLOP_GRAPHPLOTTABLESFACTORY_H
@@ -0,0 +1,91
1 #include "Visualization/GraphPlottablesFactory.h"
2 #include "Visualization/qcustomplot.h"
3
4 #include <Data/ScalarSeries.h>
5
6 #include <Variable/Variable.h>
7
8 Q_LOGGING_CATEGORY(LOG_GraphPlottablesFactory, "GraphPlottablesFactory")
9
10 namespace {
11
12 /// Format for datetimes on a axis
13 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
14
15 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
16 /// non-time data
17 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
18 {
19 if (isTimeAxis) {
20 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
21 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
22
23 return dateTicker;
24 }
25 else {
26 // default ticker
27 return QSharedPointer<QCPAxisTicker>::create();
28 }
29 }
30
31 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot)
32 {
33 auto component = plot.addGraph();
34
35 if (component) {
36 // Graph data
37 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
38 true);
39
40 // Axes properties
41 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
42 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
43
44 auto setAxisProperties = [](auto axis, const auto &unit) {
45 // label (unit name)
46 axis->setLabel(unit.m_Name);
47
48 // ticker (depending on the type of unit)
49 axis->setTicker(axisTicker(unit.m_TimeUnit));
50 };
51 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
52 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
53
54 // Display all data
55 component->rescaleAxes();
56
57 plot.replot();
58 }
59 else {
60 qCDebug(LOG_GraphPlottablesFactory())
61 << QObject::tr("Can't create graph for the scalar series");
62 }
63
64 return component;
65 }
66
67 } // namespace
68
69 QVector<QCPAbstractPlottable *> GraphPlottablesFactory::create(const Variable *variable,
70 QCustomPlot &plot) noexcept
71 {
72 auto result = QVector<QCPAbstractPlottable *>{};
73
74 if (variable) {
75 // Gets the data series of the variable to call the creation of the right components
76 // according to its type
77 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
78 result.append(createScalarSeriesComponent(*scalarSeries, plot));
79 }
80 else {
81 qCDebug(LOG_GraphPlottablesFactory())
82 << QObject::tr("Can't create graph plottables : unmanaged data series type");
83 }
84 }
85 else {
86 qCDebug(LOG_GraphPlottablesFactory())
87 << QObject::tr("Can't create graph plottables : the variable is null");
88 }
89
90 return result;
91 }
@@ -27,6 +27,8
27 27 #include <SidePane/SqpSidePane.h>
28 28 #include <SqpApplication.h>
29 29 #include <TimeWidget/TimeWidget.h>
30 #include <Variable/Variable.h>
31 #include <Visualization/VisualizationController.h>
30 32
31 33 #include <QAction>
32 34 #include <QDate>
@@ -172,6 +174,10 MainWindow::MainWindow(QWidget *parent)
172 174 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
173 175 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
174 176
177 qRegisterMetaType<std::shared_ptr<Variable> >();
178 connect(&sqpApp->visualizationController(), SIGNAL(variableCreated(std::shared_ptr<Variable>)),
179 m_Ui->view, SLOT(displayVariable(std::shared_ptr<Variable>)));
180
175 181 /* QLopGUI::registerMenuBar(menuBar());
176 182 this->setWindowIcon(QIcon(":/sciqlopLOGO.svg"));
177 183 this->m_progressWidget = new QWidget();
@@ -21,30 +21,30 public:
21 21 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
22 22
23 23 /// @sa IDataSeries::xAxisUnit()
24 QString xAxisUnit() const override { return m_XAxisUnit; }
24 Unit xAxisUnit() const override { return m_XAxisUnit; }
25 25
26 26 /// @return the values dataset
27 27 std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
28 28
29 29 /// @sa IDataSeries::valuesUnit()
30 QString valuesUnit() const override { return m_ValuesUnit; }
30 Unit valuesUnit() const override { return m_ValuesUnit; }
31 31
32 32 protected:
33 33 /// Protected ctor (DataSeries is abstract)
34 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const QString &xAxisUnit,
35 std::shared_ptr<ArrayData<Dim> > valuesData, const QString &valuesUnit)
34 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, Unit xAxisUnit,
35 std::shared_ptr<ArrayData<Dim> > valuesData, Unit valuesUnit)
36 36 : m_XAxisData{xAxisData},
37 m_XAxisUnit{xAxisUnit},
37 m_XAxisUnit{std::move(xAxisUnit)},
38 38 m_ValuesData{valuesData},
39 m_ValuesUnit{valuesUnit}
39 m_ValuesUnit{std::move(valuesUnit)}
40 40 {
41 41 }
42 42
43 43 private:
44 44 std::shared_ptr<ArrayData<1> > m_XAxisData;
45 QString m_XAxisUnit;
45 Unit m_XAxisUnit;
46 46 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
47 QString m_ValuesUnit;
47 Unit m_ValuesUnit;
48 48 };
49 49
50 50 #endif // SCIQLOP_DATASERIES_H
@@ -8,6 +8,16
8 8 template <int Dim>
9 9 class ArrayData;
10 10
11 struct Unit {
12 explicit Unit(const QString &name = {}, bool timeUnit = false)
13 : m_Name{name}, m_TimeUnit{timeUnit}
14 {
15 }
16
17 QString m_Name; ///< Unit name
18 bool m_TimeUnit; ///< The unit is a unit of time
19 };
20
11 21 /**
12 22 * @brief The IDataSeries aims to declare a data series.
13 23 *
@@ -29,9 +39,9 public:
29 39 /// Returns the x-axis dataset
30 40 virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0;
31 41
32 virtual QString xAxisUnit() const = 0;
42 virtual Unit xAxisUnit() const = 0;
33 43
34 virtual QString valuesUnit() const = 0;
44 virtual Unit valuesUnit() const = 0;
35 45 };
36 46
37 47 #endif // SCIQLOP_IDATASERIES_H
@@ -14,7 +14,7 public:
14 14 * @param xAxisUnit x-axis unit
15 15 * @param valuesUnit values unit
16 16 */
17 explicit ScalarSeries(int size, const QString &xAxisUnit, const QString &valuesUnit);
17 explicit ScalarSeries(int size, Unit xAxisUnit, Unit valuesUnit);
18 18
19 19 /**
20 20 * Sets data for a specific index. The index has to be valid to be effective
@@ -21,6 +21,9 public:
21 21
22 22 void addDataSeries(std::unique_ptr<IDataSeries> dataSeries) noexcept;
23 23
24 /// @return the data of the variable, nullptr if there is no data
25 IDataSeries *dataSeries() const noexcept;
26
24 27 private:
25 28 class VariablePrivate;
26 29 spimpl::unique_impl_ptr<VariablePrivate> impl;
@@ -25,10 +25,11 public:
25 25 explicit VisualizationController(QObject *parent = 0);
26 26 virtual ~VisualizationController();
27 27
28 public slots:
29 /// Slot called when a variable has been created in SciQlop
30 void onVariableCreated(std::shared_ptr<Variable> variable) noexcept;
28 signals:
29 /// Signal emitted when a variable has been created in SciQlop
30 void variableCreated(std::shared_ptr<Variable> variable);
31 31
32 public slots:
32 33 /// Manage init/end of the controller
33 34 void initialize();
34 35 void finalize();
@@ -1,8 +1,8
1 1 #include <Data/ScalarSeries.h>
2 2
3 ScalarSeries::ScalarSeries(int size, const QString &xAxisUnit, const QString &valuesUnit)
4 : DataSeries{std::make_shared<ArrayData<1> >(size), xAxisUnit,
5 std::make_shared<ArrayData<1> >(size), valuesUnit}
3 ScalarSeries::ScalarSeries(int size, Unit xAxisUnit, Unit valuesUnit)
4 : DataSeries{std::make_shared<ArrayData<1> >(size), std::move(xAxisUnit),
5 std::make_shared<ArrayData<1> >(size), std::move(valuesUnit)}
6 6 {
7 7 }
8 8
@@ -41,3 +41,8 void Variable::addDataSeries(std::unique_ptr<IDataSeries> dataSeries) noexcept
41 41 }
42 42 /// @todo : else, merge the two data series (if possible)
43 43 }
44
45 IDataSeries *Variable::dataSeries() const noexcept
46 {
47 return impl->m_DataSeries.get();
48 }
@@ -29,12 +29,6 VisualizationController::~VisualizationController()
29 29 this->waitForFinish();
30 30 }
31 31
32 void VisualizationController::onVariableCreated(std::shared_ptr<Variable> variable) noexcept
33 {
34 /// @todo ALX : make new graph for the variable
35 qCDebug(LOG_VisualizationController()) << "new variable to display";
36 }
37
38 32 void VisualizationController::initialize()
39 33 {
40 34 qCDebug(LOG_VisualizationController()) << tr("VisualizationController init")
@@ -34,6 +34,10 private:
34 34
35 35 class VisualizationGraphWidgetPrivate;
36 36 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
37
38 private slots:
39 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
40 void onMouseWheel(QWheelEvent *event) noexcept;
37 41 };
38 42
39 43 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -6,6 +6,7
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 class Variable;
9 10 class VisualizationTabWidget;
10 11
11 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
@@ -35,6 +36,15 public:
35 36 void close() override;
36 37 QString name() const;
37 38
39 public slots:
40 /**
41 * Displays a variable in a new graph of a new zone of the current tab
42 * @param variable the variable to display
43 * @todo this is a temporary method that will be replaced by own actions for each type of
44 * visualization widget
45 */
46 void displayVariable(std::shared_ptr<Variable> variable) noexcept;
47
38 48 private:
39 49 Ui::VisualizationWidget *ui;
40 50 };
@@ -31,7 +31,7 public:
31 31 qRegisterMetaType<std::shared_ptr<Variable> >();
32 32 connect(m_VariableController.get(), SIGNAL(variableCreated(std::shared_ptr<Variable>)),
33 33 m_VisualizationController.get(),
34 SLOT(onVariableCreated(std::shared_ptr<Variable>)));
34 SIGNAL(variableCreated(std::shared_ptr<Variable>)));
35 35
36 36 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
37 37 m_VariableController->moveToThread(&m_VariableControllerThread);
@@ -1,15 +1,25
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/GraphPlottablesFactory.h"
2 3 #include "ui_VisualizationGraphWidget.h"
3 4
4 5 #include <Variable/Variable.h>
5 6
6 7 #include <unordered_map>
7 8
9 namespace {
10
11 /// Key pressed to enable zoom on horizontal axis
12 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
13
14 /// Key pressed to enable zoom on vertical axis
15 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
16
17 } // namespace
18
8 19 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
9 20
10 21 // 1 variable -> n qcpplot
11 std::unordered_map<std::shared_ptr<Variable>, std::unique_ptr<QCPAbstractPlottable> >
12 m_VariableToPlotMap;
22 std::unordered_map<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMap;
13 23 };
14 24
15 25 VisualizationGraphWidget::VisualizationGraphWidget(QWidget *parent)
@@ -18,6 +28,13 VisualizationGraphWidget::VisualizationGraphWidget(QWidget *parent)
18 28 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
19 29 {
20 30 ui->setupUi(this);
31
32 // Set qcpplot properties :
33 // - Drag (on x-axis) and zoom are enabled
34 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
35 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
36 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
37 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
21 38 }
22 39
23 40 VisualizationGraphWidget::~VisualizationGraphWidget()
@@ -27,7 +44,12 VisualizationGraphWidget::~VisualizationGraphWidget()
27 44
28 45 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
29 46 {
30 // todo: first check is variable contains data then check how many plot have to be created
47 // Uses delegate to create the qcpplot components according to the variable
48 auto createdPlottables = GraphPlottablesFactory::create(variable.get(), *ui->widget);
49
50 for (auto createdPlottable : qAsConst(createdPlottables)) {
51 impl->m_VariableToPlotMap.insert({variable, createdPlottable});
52 }
31 53 }
32 54
33 55 void VisualizationGraphWidget::accept(IVisualizationWidget *visitor)
@@ -45,3 +67,20 QString VisualizationGraphWidget::name() const
45 67 {
46 68 return QStringLiteral("MainView");
47 69 }
70
71 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
72 {
73 auto zoomOrientations = QFlags<Qt::Orientation>{};
74
75 // Lambda that enables a zoom orientation if the key modifier related to this orientation has
76 // been pressed
77 auto enableOrientation
78 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
79 auto orientationEnabled = event->modifiers().testFlag(modifier);
80 zoomOrientations.setFlag(orientation, orientationEnabled);
81 };
82 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
83 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
84
85 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
86 }
@@ -1,5 +1,7
1 1 #include "Visualization/VisualizationWidget.h"
2 #include "Visualization/VisualizationGraphWidget.h"
2 3 #include "Visualization/VisualizationTabWidget.h"
4 #include "Visualization/VisualizationZoneWidget.h"
3 5 #include "Visualization/qcustomplot.h"
4 6
5 7 #include "ui_VisualizationWidget.h"
@@ -78,3 +80,26 QString VisualizationWidget::name() const
78 80 {
79 81 return QStringLiteral("MainView");
80 82 }
83
84 void VisualizationWidget::displayVariable(std::shared_ptr<Variable> variable) noexcept
85 {
86 if (auto currentTab = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->currentWidget())) {
87 if (auto newZone = currentTab->createZone()) {
88 if (auto newGraph = newZone->createGraph()) {
89 newGraph->addVariable(variable);
90 }
91 else {
92 qCDebug(LOG_VisualizationWidget())
93 << tr("Can't display the variable : can't create the graph");
94 }
95 }
96 else {
97 qCDebug(LOG_VisualizationWidget())
98 << tr("Can't display the variable : can't create a new zone in the current tab");
99 }
100 }
101 else {
102 qCDebug(LOG_VisualizationWidget())
103 << tr("Can't display the variable : there is no current tab");
104 }
105 }
@@ -19,7 +19,7 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
19 19
20 20 // Generates scalar series containing cosinus values (one value per second)
21 21 auto scalarSeries
22 = std::make_unique<ScalarSeries>(end - start, QStringLiteral("t"), QStringLiteral(""));
22 = std::make_unique<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
23 23
24 24 auto dataIndex = 0;
25 25 for (auto time = start; time < end; ++time, ++dataIndex) {
General Comments 0
You need to be logged in to leave comments. Login now