##// END OF EJS Templates
Remove variable from graph (2)...
Alexandre Leroux -
r250:2f78c65d4fcb
parent child
Show More
@@ -1,57 +1,59
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14
14
15 class QCPRange;
15 class QCPRange;
16 class Variable;
16 class Variable;
17
17
18 namespace Ui {
18 namespace Ui {
19 class VisualizationGraphWidget;
19 class VisualizationGraphWidget;
20 } // namespace Ui
20 } // namespace Ui
21
21
22 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
22 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
23 Q_OBJECT
23 Q_OBJECT
24
24
25 public:
25 public:
26 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
26 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
27 virtual ~VisualizationGraphWidget();
27 virtual ~VisualizationGraphWidget();
28
28
29 void addVariable(std::shared_ptr<Variable> variable);
29 void addVariable(std::shared_ptr<Variable> variable);
30 /// Removes a variable from the graph
31 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
30
32
31 // IVisualizationWidget interface
33 // IVisualizationWidget interface
32 void accept(IVisualizationWidgetVisitor *visitor) override;
34 void accept(IVisualizationWidgetVisitor *visitor) override;
33 bool canDrop(const Variable &variable) const override;
35 bool canDrop(const Variable &variable) const override;
34 QString name() const override;
36 QString name() const override;
35
37
36 void updateDisplay(std::shared_ptr<Variable> variable);
38 void updateDisplay(std::shared_ptr<Variable> variable);
37
39
38
40
39 private:
41 private:
40 Ui::VisualizationGraphWidget *ui;
42 Ui::VisualizationGraphWidget *ui;
41
43
42 class VisualizationGraphWidgetPrivate;
44 class VisualizationGraphWidgetPrivate;
43 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
45 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
44
46
45 private slots:
47 private slots:
46 /// Slot called when right clicking on the graph (displays a menu)
48 /// Slot called when right clicking on the graph (displays a menu)
47 void onGraphMenuRequested(const QPoint &pos) noexcept;
49 void onGraphMenuRequested(const QPoint &pos) noexcept;
48
50
49 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
51 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
50
52
51 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
53 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
52 void onMouseWheel(QWheelEvent *event) noexcept;
54 void onMouseWheel(QWheelEvent *event) noexcept;
53
55
54 void onDataCacheVariableUpdated();
56 void onDataCacheVariableUpdated();
55 };
57 };
56
58
57 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
59 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,215 +1,226
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphHelper.h"
3 #include "Visualization/VisualizationGraphHelper.h"
4 #include "ui_VisualizationGraphWidget.h"
4 #include "ui_VisualizationGraphWidget.h"
5
5
6 #include <Data/ArrayData.h>
6 #include <Data/ArrayData.h>
7 #include <Data/IDataSeries.h>
7 #include <Data/IDataSeries.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <unordered_map>
12 #include <unordered_map>
13
13
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15
15
16 namespace {
16 namespace {
17
17
18 /// Key pressed to enable zoom on horizontal axis
18 /// Key pressed to enable zoom on horizontal axis
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20
20
21 /// Key pressed to enable zoom on vertical axis
21 /// Key pressed to enable zoom on vertical axis
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23
23
24 } // namespace
24 } // namespace
25
25
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27
27
28 // 1 variable -> n qcpplot
28 // 1 variable -> n qcpplot
29 std::unordered_multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *>
29 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
30 m_VariableToPlotMultiMap;
31 };
30 };
32
31
33 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
32 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
34 : QWidget{parent},
33 : QWidget{parent},
35 ui{new Ui::VisualizationGraphWidget},
34 ui{new Ui::VisualizationGraphWidget},
36 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
35 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
37 {
36 {
38 ui->setupUi(this);
37 ui->setupUi(this);
39
38
40 ui->graphNameLabel->setText(name);
39 ui->graphNameLabel->setText(name);
41
40
42 // 'Close' options : widget is deleted when closed
41 // 'Close' options : widget is deleted when closed
43 setAttribute(Qt::WA_DeleteOnClose);
42 setAttribute(Qt::WA_DeleteOnClose);
44 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
43 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
45 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
44 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
46
45
47 // Set qcpplot properties :
46 // Set qcpplot properties :
48 // - Drag (on x-axis) and zoom are enabled
47 // - Drag (on x-axis) and zoom are enabled
49 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
48 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
50 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
49 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
51 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
50 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
52 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
51 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
53 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
52 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
54 &QCPAxis::rangeChanged),
53 &QCPAxis::rangeChanged),
55 this, &VisualizationGraphWidget::onRangeChanged);
54 this, &VisualizationGraphWidget::onRangeChanged);
56
55
57 // Activates menu when right clicking on the graph
56 // Activates menu when right clicking on the graph
58 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
57 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
59 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
58 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
60 &VisualizationGraphWidget::onGraphMenuRequested);
59 &VisualizationGraphWidget::onGraphMenuRequested);
61 }
60 }
62
61
63
62
64 VisualizationGraphWidget::~VisualizationGraphWidget()
63 VisualizationGraphWidget::~VisualizationGraphWidget()
65 {
64 {
66 delete ui;
65 delete ui;
67 }
66 }
68
67
69 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
68 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
70 {
69 {
71 // Uses delegate to create the qcpplot components according to the variable
70 // Uses delegate to create the qcpplot components according to the variable
72 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
71 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
73
72
74 for (auto createdPlottable : qAsConst(createdPlottables)) {
73 for (auto createdPlottable : qAsConst(createdPlottables)) {
75 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
74 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
76 }
75 }
77
76
78 connect(variable.get(), SIGNAL(dataCacheUpdated()), this, SLOT(onDataCacheVariableUpdated()));
77 connect(variable.get(), SIGNAL(dataCacheUpdated()), this, SLOT(onDataCacheVariableUpdated()));
79 }
78 }
80
79
80 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
81 {
82 }
83
81 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
84 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
82 {
85 {
83 if (visitor) {
86 if (visitor) {
84 visitor->visit(this);
87 visitor->visit(this);
85 }
88 }
86 else {
89 else {
87 qCCritical(LOG_VisualizationGraphWidget())
90 qCCritical(LOG_VisualizationGraphWidget())
88 << tr("Can't visit widget : the visitor is null");
91 << tr("Can't visit widget : the visitor is null");
89 }
92 }
90 }
93 }
91
94
92 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
95 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
93 {
96 {
94 /// @todo : for the moment, a graph can always accomodate a variable
97 /// @todo : for the moment, a graph can always accomodate a variable
95 Q_UNUSED(variable);
98 Q_UNUSED(variable);
96 return true;
99 return true;
97 }
100 }
98
101
99 QString VisualizationGraphWidget::name() const
102 QString VisualizationGraphWidget::name() const
100 {
103 {
101 return ui->graphNameLabel->text();
104 return ui->graphNameLabel->text();
102 }
105 }
103
106
104 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
107 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
105 {
108 {
106 QMenu graphMenu{};
109 QMenu graphMenu{};
107
110
111 // Iterates on variables (unique keys)
112 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
113 end = impl->m_VariableToPlotMultiMap.cend();
114 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
115 // 'Remove variable' action
116 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
117 [ this, var = it->first ]() { removeVariable(var); });
118 }
108
119
109 if (!graphMenu.isEmpty()) {
120 if (!graphMenu.isEmpty()) {
110 graphMenu.exec(mapToGlobal(pos));
121 graphMenu.exec(mapToGlobal(pos));
111 }
122 }
112 }
123 }
113
124
114 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
125 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
115 {
126 {
116
127
117 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
128 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
118
129
119 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
130 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
120 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
131 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
121
132
122 auto variable = it->first;
133 auto variable = it->first;
123 qCInfo(LOG_VisualizationGraphWidget())
134 qCInfo(LOG_VisualizationGraphWidget())
124 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
135 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
125 << variable->dataSeries()->xAxisData()->size();
136 << variable->dataSeries()->xAxisData()->size();
126 auto dateTime = SqpDateTime{t2.lower, t2.upper};
137 auto dateTime = SqpDateTime{t2.lower, t2.upper};
127
138
128 if (!variable->contains(dateTime)) {
139 if (!variable->contains(dateTime)) {
129
140
130 auto variableDateTimeWithTolerance = dateTime;
141 auto variableDateTimeWithTolerance = dateTime;
131 if (variable->intersect(dateTime)) {
142 if (variable->intersect(dateTime)) {
132 auto variableDateTime = variable->dateTime();
143 auto variableDateTime = variable->dateTime();
133 if (variableDateTime.m_TStart < dateTime.m_TStart) {
144 if (variableDateTime.m_TStart < dateTime.m_TStart) {
134
145
135 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
146 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
136 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
147 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
137 // Tolerance have to be added to the right
148 // Tolerance have to be added to the right
138 // add 10% tolerance for right (end) side
149 // add 10% tolerance for right (end) side
139 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
150 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
140 variableDateTimeWithTolerance.m_TEnd += tolerance;
151 variableDateTimeWithTolerance.m_TEnd += tolerance;
141 }
152 }
142 if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
153 if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
143 auto diffStartToKeepDelta = dateTime.m_TStart - dateTime.m_TStart;
154 auto diffStartToKeepDelta = dateTime.m_TStart - dateTime.m_TStart;
144 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
155 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
145 // Tolerance have to be added to the left
156 // Tolerance have to be added to the left
146 // add 10% tolerance for left (start) side
157 // add 10% tolerance for left (start) side
147 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
158 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
148 variableDateTimeWithTolerance.m_TStart -= tolerance;
159 variableDateTimeWithTolerance.m_TStart -= tolerance;
149 }
160 }
150 }
161 }
151 else {
162 else {
152 // add 10% tolerance for each side
163 // add 10% tolerance for each side
153 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
164 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
154 variableDateTimeWithTolerance.m_TStart -= tolerance;
165 variableDateTimeWithTolerance.m_TStart -= tolerance;
155 variableDateTimeWithTolerance.m_TEnd += tolerance;
166 variableDateTimeWithTolerance.m_TEnd += tolerance;
156 }
167 }
157 variable->setDateTime(dateTime);
168 variable->setDateTime(dateTime);
158
169
159 // CHangement detected, we need to ask controller to request data loading
170 // CHangement detected, we need to ask controller to request data loading
160 sqpApp->variableController().requestDataLoading(variable,
171 sqpApp->variableController().requestDataLoading(variable,
161 variableDateTimeWithTolerance);
172 variableDateTimeWithTolerance);
162 }
173 }
163 }
174 }
164 }
175 }
165
176
166 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
177 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
167 {
178 {
168 auto zoomOrientations = QFlags<Qt::Orientation>{};
179 auto zoomOrientations = QFlags<Qt::Orientation>{};
169
180
170 // Lambda that enables a zoom orientation if the key modifier related to this orientation
181 // Lambda that enables a zoom orientation if the key modifier related to this orientation
171 // has
182 // has
172 // been pressed
183 // been pressed
173 auto enableOrientation
184 auto enableOrientation
174 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
185 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
175 auto orientationEnabled = event->modifiers().testFlag(modifier);
186 auto orientationEnabled = event->modifiers().testFlag(modifier);
176 zoomOrientations.setFlag(orientation, orientationEnabled);
187 zoomOrientations.setFlag(orientation, orientationEnabled);
177 };
188 };
178 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
189 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
179 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
190 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
180
191
181 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
192 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
182 }
193 }
183
194
184 void VisualizationGraphWidget::onDataCacheVariableUpdated()
195 void VisualizationGraphWidget::onDataCacheVariableUpdated()
185 {
196 {
186 // NOTE:
197 // NOTE:
187 // We don't want to call the method for each component of a variable unitarily, but for
198 // We don't want to call the method for each component of a variable unitarily, but for
188 // all
199 // all
189 // its components at once (eg its three components in the case of a vector).
200 // its components at once (eg its three components in the case of a vector).
190
201
191 // The unordered_multimap does not do this easily, so the question is whether to:
202 // The unordered_multimap does not do this easily, so the question is whether to:
192 // - use an ordered_multimap and the algos of std to group the values by key
203 // - use an ordered_multimap and the algos of std to group the values by key
193 // - use a map (unique keys) and store as values directly the list of components
204 // - use a map (unique keys) and store as values directly the list of components
194
205
195 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
206 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
196 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
207 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
197 auto variable = it->first;
208 auto variable = it->first;
198 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
209 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
199 variable->dataSeries(), variable->dateTime());
210 variable->dataSeries(), variable->dateTime());
200 }
211 }
201 }
212 }
202
213
203 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
214 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
204 {
215 {
205 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
216 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
206
217
207 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
218 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
208
219
209 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
220 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
210 abstractPlotableVect.push_back(it->second);
221 abstractPlotableVect.push_back(it->second);
211 }
222 }
212
223
213 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
224 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
214 variable->dateTime());
225 variable->dateTime());
215 }
226 }
General Comments 0
You need to be logged in to leave comments. Login now