##// END OF EJS Templates
Merge pull request 155 from SCIQLOP-Initialisation develop...
perrinel -
r189:e658778a16ed merge
parent child
Show More
@@ -0,0 +1,32
1 #ifndef SCIQLOP_GRAPHPLOTTABLESFACTORY_H
2 #define SCIQLOP_GRAPHPLOTTABLESFACTORY_H
3
4 #include <QLoggingCategory>
5 #include <QVector>
6
7 #include <memory>
8
9 Q_DECLARE_LOGGING_CATEGORY(LOG_GraphPlottablesFactory)
10
11 class QCPAbstractPlottable;
12 class QCustomPlot;
13 class Variable;
14
15 /**
16 * @brief The GraphPlottablesFactory class aims to create the QCustomPlot components relative to a
17 * variable, depending on the data series of this variable
18 */
19 struct GraphPlottablesFactory {
20 /**
21 * Creates (if possible) the QCustomPlot components relative to the variable passed in
22 * parameter, and adds these to the plot passed in parameter.
23 * @param variable the variable for which to create the components
24 * @param plot the plot in which to add the created components. It takes ownership of these
25 * components.
26 * @return the list of the components created
27 */
28 static QVector<QCPAbstractPlottable *> create(std::shared_ptr<Variable> variable,
29 QCustomPlot &plot) noexcept;
30 };
31
32 #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(std::shared_ptr<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,18 +21,18 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, const Unit &xAxisUnit,
35 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
36 36 : m_XAxisData{xAxisData},
37 37 m_XAxisUnit{xAxisUnit},
38 38 m_ValuesData{valuesData},
@@ -42,9 +42,9 protected:
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, const Unit &xAxisUnit, const 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,6 +1,6
1 1 #include <Data/ScalarSeries.h>
2 2
3 ScalarSeries::ScalarSeries(int size, const QString &xAxisUnit, const QString &valuesUnit)
3 ScalarSeries::ScalarSeries(int size, const Unit &xAxisUnit, const Unit &valuesUnit)
4 4 : DataSeries{std::make_shared<ArrayData<1> >(size), xAxisUnit,
5 5 std::make_shared<ArrayData<1> >(size), valuesUnit}
6 6 {
@@ -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, *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"
@@ -16,24 +18,36 VisualizationWidget::VisualizationWidget(QWidget *parent)
16 18 auto addTabViewButton = new QToolButton{ui->tabWidget};
17 19 addTabViewButton->setText(tr("Add View"));
18 20 addTabViewButton->setCursor(Qt::ArrowCursor);
19 addTabViewButton->setAutoRaise(true);
20 21 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
21 auto width = ui->tabWidget->cornerWidget()->width();
22 auto height = ui->tabWidget->cornerWidget()->height();
23 addTabViewButton->setMinimumHeight(height);
24 addTabViewButton->setMinimumWidth(width);
25 ui->tabWidget->setMinimumHeight(height);
26 ui->tabWidget->setMinimumWidth(width);
27
28 auto addTabView = [&]() {
22
23 auto enableMinimumCornerWidgetSize = [this](bool enable) {
24
25 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
26 auto width = enable ? tabViewCornerWidget->width() : 0;
27 auto height = enable ? tabViewCornerWidget->height() : 0;
28 tabViewCornerWidget->setMinimumHeight(height);
29 tabViewCornerWidget->setMinimumWidth(width);
30 ui->tabWidget->setMinimumHeight(height);
31 ui->tabWidget->setMinimumWidth(width);
32 };
33
34 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
29 35 auto index = ui->tabWidget->addTab(new VisualizationTabWidget(ui->tabWidget),
30 36 QString("View %1").arg(ui->tabWidget->count() + 1));
37 if (ui->tabWidget->count() > 0) {
38 enableMinimumCornerWidgetSize(false);
39 }
31 40 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
32 41 };
33 42
34 auto removeTabView = [&](int index) {
43 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
44 if (ui->tabWidget->count() == 1) {
45 enableMinimumCornerWidgetSize(true);
46 }
47
35 48 ui->tabWidget->removeTab(index);
36 49 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
50
37 51 };
38 52
39 53 ui->tabWidget->setTabsClosable(true);
@@ -78,3 +92,26 QString VisualizationWidget::name() const
78 92 {
79 93 return QStringLiteral("MainView");
80 94 }
95
96 void VisualizationWidget::displayVariable(std::shared_ptr<Variable> variable) noexcept
97 {
98 if (auto currentTab = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->currentWidget())) {
99 if (auto newZone = currentTab->createZone()) {
100 if (auto newGraph = newZone->createGraph()) {
101 newGraph->addVariable(variable);
102 }
103 else {
104 qCCritical(LOG_VisualizationWidget())
105 << tr("Can't display the variable : can't create the graph");
106 }
107 }
108 else {
109 qCCritical(LOG_VisualizationWidget())
110 << tr("Can't display the variable : can't create a new zone in the current tab");
111 }
112 }
113 else {
114 qCCritical(LOG_VisualizationWidget())
115 << tr("Can't display the variable : there is no current tab");
116 }
117 }
@@ -14,14 +14,32
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 <property name="spacing">
18 <number>3</number>
19 </property>
20 <property name="leftMargin">
21 <number>0</number>
22 </property>
23 <property name="topMargin">
24 <number>0</number>
25 </property>
26 <property name="rightMargin">
27 <number>0</number>
28 </property>
29 <property name="bottomMargin">
30 <number>0</number>
31 </property>
17 32 <item>
18 33 <widget class="QFrame" name="visualizationZoneFrame">
19 34 <property name="frameShape">
20 <enum>QFrame::StyledPanel</enum>
35 <enum>QFrame::Box</enum>
21 36 </property>
22 37 <property name="frameShadow">
23 38 <enum>QFrame::Raised</enum>
24 39 </property>
40 <property name="lineWidth">
41 <number>1</number>
42 </property>
25 43 <layout class="QVBoxLayout" name="verticalLayout"/>
26 44 </widget>
27 45 </item>
@@ -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