##// END OF EJS Templates
Limits requests on mouse wheels/pans
Alexandre Leroux -
r414:4b445d4313d1 feature/AltAcquis...
parent child
Show More
@@ -1,82 +1,82
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 SqpDateTime;
16 class SqpDateTime;
17 class Variable;
17 class Variable;
18
18
19 /**
19 /**
20 * Possible types of zoom operation
20 * Possible types of zoom operation
21 */
21 */
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
23
23
24 namespace Ui {
24 namespace Ui {
25 class VisualizationGraphWidget;
25 class VisualizationGraphWidget;
26 } // namespace Ui
26 } // namespace Ui
27
27
28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
29 Q_OBJECT
29 Q_OBJECT
30
30
31 public:
31 public:
32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 virtual ~VisualizationGraphWidget();
33 virtual ~VisualizationGraphWidget();
34
34
35 void enableSynchronize(bool enable);
35 void enableSynchronize(bool enable);
36
36
37 void addVariable(std::shared_ptr<Variable> variable);
37 void addVariable(std::shared_ptr<Variable> variable);
38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
39 /// Removes a variable from the graph
39 /// Removes a variable from the graph
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
41
41
42 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
42 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
43 SqpDateTime graphRange() const noexcept;
43 SqpDateTime graphRange() const noexcept;
44 void setGraphRange(const SqpDateTime &range);
44 void setGraphRange(const SqpDateTime &range);
45
45
46 // IVisualizationWidget interface
46 // IVisualizationWidget interface
47 void accept(IVisualizationWidgetVisitor *visitor) override;
47 void accept(IVisualizationWidgetVisitor *visitor) override;
48 bool canDrop(const Variable &variable) const override;
48 bool canDrop(const Variable &variable) const override;
49 bool contains(const Variable &variable) const override;
49 bool contains(const Variable &variable) const override;
50 QString name() const override;
50 QString name() const override;
51
51
52
52
53 signals:
53 signals:
54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
55 void synchronize(const SqpDateTime &dateTime, const SqpDateTime &oldDateTime,
55 void synchronize(const SqpDateTime &dateTime, const SqpDateTime &oldDateTime,
56 VisualizationGraphWidgetZoomType zoomType);
56 VisualizationGraphWidgetZoomType zoomType);
57
57
58
58
59 private:
59 private:
60 Ui::VisualizationGraphWidget *ui;
60 Ui::VisualizationGraphWidget *ui;
61
61
62 class VisualizationGraphWidgetPrivate;
62 class VisualizationGraphWidgetPrivate;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
64
64
65 private slots:
65 private slots:
66 /// Slot called when right clicking on the graph (displays a menu)
66 /// Slot called when right clicking on the graph (displays a menu)
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
68
68
69 /// Rescale the X axe to range parameter
69 /// Rescale the X axe to range parameter
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
70 void processRangeChange();
71
71
72 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
72 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
73 void onMouseWheel(QWheelEvent *event) noexcept;
73 void onMouseWheel(QWheelEvent *event) noexcept;
74 /// Slot called when a mouse press was made, to activate the calibration of a graph
74 /// Slot called when a mouse press was made, to activate the calibration of a graph
75 void onMousePress(QMouseEvent *event) noexcept;
75 void onMousePress(QMouseEvent *event) noexcept;
76 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
76 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
77 void onMouseRelease(QMouseEvent *event) noexcept;
77 void onMouseRelease(QMouseEvent *event) noexcept;
78
78
79 void onDataCacheVariableUpdated();
79 void onDataCacheVariableUpdated();
80 };
80 };
81
81
82 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
82 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,401 +1,420
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 /// Timeout from which the mouse wheel is considered completed (in ms)
19 const auto MOUSE_WHEEL_TIMEOUT = 250;
20
18 /// Key pressed to enable zoom on horizontal axis
21 /// Key pressed to enable zoom on horizontal axis
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
22 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20
23
21 /// Key pressed to enable zoom on vertical axis
24 /// Key pressed to enable zoom on vertical axis
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
25 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23
26
24 } // namespace
27 } // namespace
25
28
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
29 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27
30
28 explicit VisualizationGraphWidgetPrivate() : m_DoSynchronize{true}, m_IsCalibration{false} {}
31 explicit VisualizationGraphWidgetPrivate()
32 : m_DoSynchronize{true}, m_IsCalibration{false}, m_RefRange{}, m_MouseWheelTimer{}
33 {
34 m_MouseWheelTimer.setSingleShot(true);
35 }
29
36
30
37
31 // Return the operation when range changed
38 // Return the operation when range changed
32 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
39 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
33
40
34 // 1 variable -> n qcpplot
41 // 1 variable -> n qcpplot
35 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
42 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
36
43
37 bool m_DoSynchronize;
44 bool m_DoSynchronize;
38 bool m_IsCalibration;
45 bool m_IsCalibration;
46 QCPRange m_RefRange;
47 QTimer m_MouseWheelTimer;
39 };
48 };
40
49
41 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
50 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
42 : QWidget{parent},
51 : QWidget{parent},
43 ui{new Ui::VisualizationGraphWidget},
52 ui{new Ui::VisualizationGraphWidget},
44 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
53 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
45 {
54 {
46 ui->setupUi(this);
55 ui->setupUi(this);
47
56
48 ui->graphNameLabel->setText(name);
57 ui->graphNameLabel->setText(name);
49
58
50 // 'Close' options : widget is deleted when closed
59 // 'Close' options : widget is deleted when closed
51 setAttribute(Qt::WA_DeleteOnClose);
60 setAttribute(Qt::WA_DeleteOnClose);
52 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
61 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
53 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
62 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
54
63
55 // Set qcpplot properties :
64 // Set qcpplot properties :
56 // - Drag (on x-axis) and zoom are enabled
65 // - Drag (on x-axis) and zoom are enabled
57 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
66 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
58 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
67 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
59 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
68 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
60 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
69 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
61 connect(ui->widget, &QCustomPlot::mouseRelease, this,
70 connect(ui->widget, &QCustomPlot::mouseRelease, this,
62 &VisualizationGraphWidget::onMouseRelease);
71 &VisualizationGraphWidget::onMouseRelease);
63 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
72 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
64 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
73
65 &QCPAxis::rangeChanged),
74 // Connects mouse wheel timer
66 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
75 connect(&impl->m_MouseWheelTimer, &QTimer::timeout, this,
76 &VisualizationGraphWidget::processRangeChange);
67
77
68 // Activates menu when right clicking on the graph
78 // Activates menu when right clicking on the graph
69 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
79 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
70 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
80 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
71 &VisualizationGraphWidget::onGraphMenuRequested);
81 &VisualizationGraphWidget::onGraphMenuRequested);
72
82
73 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
83 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
74 &VariableController::onRequestDataLoading);
84 &VariableController::onRequestDataLoading);
75 }
85 }
76
86
77
87
78 VisualizationGraphWidget::~VisualizationGraphWidget()
88 VisualizationGraphWidget::~VisualizationGraphWidget()
79 {
89 {
80 delete ui;
90 delete ui;
81 }
91 }
82
92
83 void VisualizationGraphWidget::enableSynchronize(bool enable)
93 void VisualizationGraphWidget::enableSynchronize(bool enable)
84 {
94 {
85 impl->m_DoSynchronize = enable;
95 impl->m_DoSynchronize = enable;
86 }
96 }
87
97
88 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
98 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
89 {
99 {
90 // Uses delegate to create the qcpplot components according to the variable
100 // Uses delegate to create the qcpplot components according to the variable
91 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
101 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
92
102
93 for (auto createdPlottable : qAsConst(createdPlottables)) {
103 for (auto createdPlottable : qAsConst(createdPlottables)) {
94 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
104 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
95 }
105 }
96
106
97 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
107 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
98 }
108 }
99 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
109 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
100 {
110 {
101
111
102 // when adding a variable, we need to set its time range to the current graph range
112 // when adding a variable, we need to set its time range to the current graph range
103 auto grapheRange = ui->widget->xAxis->range();
113 auto grapheRange = ui->widget->xAxis->range();
104 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
114 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
105 variable->setDateTime(dateTime);
115 variable->setDateTime(dateTime);
106
116
107 auto variableDateTimeWithTolerance = dateTime;
117 auto variableDateTimeWithTolerance = dateTime;
108
118
109 // add 20% tolerance for each side
119 // add 20% tolerance for each side
110 auto tolerance = 0.2 * (dateTime.m_TEnd - dateTime.m_TStart);
120 auto tolerance = 0.2 * (dateTime.m_TEnd - dateTime.m_TStart);
111 variableDateTimeWithTolerance.m_TStart -= tolerance;
121 variableDateTimeWithTolerance.m_TStart -= tolerance;
112 variableDateTimeWithTolerance.m_TEnd += tolerance;
122 variableDateTimeWithTolerance.m_TEnd += tolerance;
113
123
114 // Uses delegate to create the qcpplot components according to the variable
124 // Uses delegate to create the qcpplot components according to the variable
115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
125 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116
126
117 for (auto createdPlottable : qAsConst(createdPlottables)) {
127 for (auto createdPlottable : qAsConst(createdPlottables)) {
118 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
128 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
119 }
129 }
120
130
121 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
131 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
122
132
123 // CHangement detected, we need to ask controller to request data loading
133 // CHangement detected, we need to ask controller to request data loading
124 emit requestDataLoading(variable, variableDateTimeWithTolerance);
134 emit requestDataLoading(variable, variableDateTimeWithTolerance);
125 }
135 }
126
136
127 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
137 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
128 {
138 {
129 // Each component associated to the variable :
139 // Each component associated to the variable :
130 // - is removed from qcpplot (which deletes it)
140 // - is removed from qcpplot (which deletes it)
131 // - is no longer referenced in the map
141 // - is no longer referenced in the map
132 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
142 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
133 for (auto it = componentsIt.first; it != componentsIt.second;) {
143 for (auto it = componentsIt.first; it != componentsIt.second;) {
134 ui->widget->removePlottable(it->second);
144 ui->widget->removePlottable(it->second);
135 it = impl->m_VariableToPlotMultiMap.erase(it);
145 it = impl->m_VariableToPlotMultiMap.erase(it);
136 }
146 }
137
147
138 // Updates graph
148 // Updates graph
139 ui->widget->replot();
149 ui->widget->replot();
140 }
150 }
141
151
142 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
152 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
143 const SqpDateTime &range)
153 const SqpDateTime &range)
144 {
154 {
145 // Note: in case of different axes that depends on variable, we could start with a code like
155 // Note: in case of different axes that depends on variable, we could start with a code like
146 // that:
156 // that:
147 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
157 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
148 // for (auto it = componentsIt.first; it != componentsIt.second;) {
158 // for (auto it = componentsIt.first; it != componentsIt.second;) {
149 // }
159 // }
150 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
160 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
151 ui->widget->replot();
161 ui->widget->replot();
152 }
162 }
153
163
154 SqpDateTime VisualizationGraphWidget::graphRange() const noexcept
164 SqpDateTime VisualizationGraphWidget::graphRange() const noexcept
155 {
165 {
156 auto grapheRange = ui->widget->xAxis->range();
166 auto grapheRange = ui->widget->xAxis->range();
157 return SqpDateTime{grapheRange.lower, grapheRange.upper};
167 return SqpDateTime{grapheRange.lower, grapheRange.upper};
158 }
168 }
159
169
160 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
170 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
161 {
171 {
162 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
172 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
163 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
173 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
164 ui->widget->replot();
174 ui->widget->replot();
165 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
175 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
166 }
176 }
167
177
168 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
178 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
169 {
179 {
170 if (visitor) {
180 if (visitor) {
171 visitor->visit(this);
181 visitor->visit(this);
172 }
182 }
173 else {
183 else {
174 qCCritical(LOG_VisualizationGraphWidget())
184 qCCritical(LOG_VisualizationGraphWidget())
175 << tr("Can't visit widget : the visitor is null");
185 << tr("Can't visit widget : the visitor is null");
176 }
186 }
177 }
187 }
178
188
179 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
189 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
180 {
190 {
181 /// @todo : for the moment, a graph can always accomodate a variable
191 /// @todo : for the moment, a graph can always accomodate a variable
182 Q_UNUSED(variable);
192 Q_UNUSED(variable);
183 return true;
193 return true;
184 }
194 }
185
195
186 bool VisualizationGraphWidget::contains(const Variable &variable) const
196 bool VisualizationGraphWidget::contains(const Variable &variable) const
187 {
197 {
188 // Finds the variable among the keys of the map
198 // Finds the variable among the keys of the map
189 auto variablePtr = &variable;
199 auto variablePtr = &variable;
190 auto findVariable
200 auto findVariable
191 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
201 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
192
202
193 auto end = impl->m_VariableToPlotMultiMap.cend();
203 auto end = impl->m_VariableToPlotMultiMap.cend();
194 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
204 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
195 return it != end;
205 return it != end;
196 }
206 }
197
207
198 QString VisualizationGraphWidget::name() const
208 QString VisualizationGraphWidget::name() const
199 {
209 {
200 return ui->graphNameLabel->text();
210 return ui->graphNameLabel->text();
201 }
211 }
202
212
203 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
213 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
204 {
214 {
205 QMenu graphMenu{};
215 QMenu graphMenu{};
206
216
207 // Iterates on variables (unique keys)
217 // Iterates on variables (unique keys)
208 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
218 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
209 end = impl->m_VariableToPlotMultiMap.cend();
219 end = impl->m_VariableToPlotMultiMap.cend();
210 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
220 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
211 // 'Remove variable' action
221 // 'Remove variable' action
212 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
222 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
213 [ this, var = it->first ]() { removeVariable(var); });
223 [ this, var = it->first ]() { removeVariable(var); });
214 }
224 }
215
225
216 if (!graphMenu.isEmpty()) {
226 if (!graphMenu.isEmpty()) {
217 graphMenu.exec(mapToGlobal(pos));
227 graphMenu.exec(mapToGlobal(pos));
218 }
228 }
219 }
229 }
220
230
221 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
231 void VisualizationGraphWidget::processRangeChange()
222 {
232 {
223 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
233 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::processRangeChange")
224 << QThread::currentThread()->objectName();
234 << QThread::currentThread()->objectName();
225
235
226 auto dateTimeRange = SqpDateTime{t1.lower, t1.upper};
236 auto oldRange = impl->m_RefRange;
237 auto newRange = ui->widget->xAxis->range();
227
238
228 auto zoomType = impl->getZoomType(t1, t2);
239 auto dateTimeRange = SqpDateTime{newRange.lower, newRange.upper};
240
241 auto zoomType = impl->getZoomType(newRange, impl->m_RefRange);
229 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
242 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
230 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
243 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
231
244
232 auto variable = it->first;
245 auto variable = it->first;
233 auto currentDateTime = dateTimeRange;
246 auto currentDateTime = dateTimeRange;
234
247
235 auto toleranceFactor = 0.2;
248 auto toleranceFactor = 0.2;
236 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
249 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
237 auto variableDateTimeWithTolerance = currentDateTime;
250 auto variableDateTimeWithTolerance = currentDateTime;
238 variableDateTimeWithTolerance.m_TStart -= tolerance;
251 variableDateTimeWithTolerance.m_TStart -= tolerance;
239 variableDateTimeWithTolerance.m_TEnd += tolerance;
252 variableDateTimeWithTolerance.m_TEnd += tolerance;
240
253
241 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
254 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
242 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
255 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
243 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
256 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
244 // If new range with tol is upper than variable datetime parameters. we need to request new
257 // If new range with tol is upper than variable datetime parameters. we need to request new
245 // data
258 // data
246 if (!variable->contains(variableDateTimeWithTolerance)) {
259 if (!variable->contains(variableDateTimeWithTolerance)) {
247
260
248 auto variableDateTimeWithTolerance = currentDateTime;
261 auto variableDateTimeWithTolerance = currentDateTime;
249 if (!variable->isInside(currentDateTime)) {
262 if (!variable->isInside(currentDateTime)) {
250 auto variableDateTime = variable->dateTime();
263 auto variableDateTime = variable->dateTime();
251 if (variable->contains(variableDateTimeWithTolerance)) {
264 if (variable->contains(variableDateTimeWithTolerance)) {
252 qCDebug(LOG_VisualizationGraphWidget())
265 qCDebug(LOG_VisualizationGraphWidget())
253 << tr("TORM: Detection zoom in that need request:");
266 << tr("TORM: Detection zoom in that need request:");
254 // add 10% tolerance for each side
267 // add 10% tolerance for each side
255 tolerance
268 tolerance
256 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
269 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
257 variableDateTimeWithTolerance.m_TStart -= tolerance;
270 variableDateTimeWithTolerance.m_TStart -= tolerance;
258 variableDateTimeWithTolerance.m_TEnd += tolerance;
271 variableDateTimeWithTolerance.m_TEnd += tolerance;
259 }
272 }
260 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
273 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
261 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
274 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
262
275
263 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
276 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
264 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
277 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
265 // Tolerance have to be added to the right
278 // Tolerance have to be added to the right
266 // add tolerance for right (end) side
279 // add tolerance for right (end) side
267 tolerance
280 tolerance
268 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
281 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
269 variableDateTimeWithTolerance.m_TEnd += tolerance;
282 variableDateTimeWithTolerance.m_TEnd += tolerance;
270 }
283 }
271 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
284 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
272 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
285 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
273 auto diffStartToKeepDelta
286 auto diffStartToKeepDelta
274 = variableDateTime.m_TStart - currentDateTime.m_TStart;
287 = variableDateTime.m_TStart - currentDateTime.m_TStart;
275 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
288 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
276 // Tolerance have to be added to the left
289 // Tolerance have to be added to the left
277 // add tolerance for left (start) side
290 // add tolerance for left (start) side
278 tolerance
291 tolerance
279 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
292 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
280 variableDateTimeWithTolerance.m_TStart -= tolerance;
293 variableDateTimeWithTolerance.m_TStart -= tolerance;
281 }
294 }
282 else {
295 else {
283 qCCritical(LOG_VisualizationGraphWidget())
296 qCCritical(LOG_VisualizationGraphWidget())
284 << tr("Detection anormal zoom detection: ");
297 << tr("Detection anormal zoom detection: ");
285 }
298 }
286 }
299 }
287 else {
300 else {
288 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
301 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
289 // add 10% tolerance for each side
302 // add 10% tolerance for each side
290 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
303 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
291 variableDateTimeWithTolerance.m_TStart -= tolerance;
304 variableDateTimeWithTolerance.m_TStart -= tolerance;
292 variableDateTimeWithTolerance.m_TEnd += tolerance;
305 variableDateTimeWithTolerance.m_TEnd += tolerance;
293 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
306 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
294 }
307 }
295 if (!variable->contains(dateTimeRange)) {
308 if (!variable->contains(dateTimeRange)) {
296 qCDebug(LOG_VisualizationGraphWidget())
309 qCDebug(LOG_VisualizationGraphWidget())
297 << "TORM: Modif on variable datetime detected" << currentDateTime;
310 << "TORM: Modif on variable datetime detected" << currentDateTime;
298 variable->setDateTime(currentDateTime);
311 variable->setDateTime(currentDateTime);
299 }
312 }
300
313
301 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
314 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
302 // CHangement detected, we need to ask controller to request data loading
315 // CHangement detected, we need to ask controller to request data loading
303 emit requestDataLoading(variable, variableDateTimeWithTolerance);
316 emit requestDataLoading(variable, variableDateTimeWithTolerance);
304 }
317 }
305 else {
318 else {
306 qCInfo(LOG_VisualizationGraphWidget())
319 qCInfo(LOG_VisualizationGraphWidget())
307 << tr("TORM: Detection zoom in that doesn't need request: ");
320 << tr("TORM: Detection zoom in that doesn't need request: ");
308 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
321 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
309 }
322 }
310 }
323 }
311
324
312 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
325 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
313 auto oldDateTime = SqpDateTime{t2.lower, t2.upper};
326 auto oldDateTime = SqpDateTime{oldRange.lower, oldRange.upper};
314 qCDebug(LOG_VisualizationGraphWidget())
327 qCDebug(LOG_VisualizationGraphWidget())
315 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
328 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
316 << QThread::currentThread()->objectName();
329 << QThread::currentThread()->objectName();
317 emit synchronize(dateTimeRange, oldDateTime, zoomType);
330 emit synchronize(dateTimeRange, oldDateTime, zoomType);
318 }
331 }
332
333 impl->m_RefRange = newRange;
319 }
334 }
320
335
321 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
336 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
322 {
337 {
338 impl->m_MouseWheelTimer.start(MOUSE_WHEEL_TIMEOUT);
339
323 auto zoomOrientations = QFlags<Qt::Orientation>{};
340 auto zoomOrientations = QFlags<Qt::Orientation>{};
324
341
325 // Lambda that enables a zoom orientation if the key modifier related to this orientation
342 // Lambda that enables a zoom orientation if the key modifier related to this orientation
326 // has
343 // has
327 // been pressed
344 // been pressed
328 auto enableOrientation
345 auto enableOrientation
329 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
346 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
330 auto orientationEnabled = event->modifiers().testFlag(modifier);
347 auto orientationEnabled = event->modifiers().testFlag(modifier);
331 zoomOrientations.setFlag(orientation, orientationEnabled);
348 zoomOrientations.setFlag(orientation, orientationEnabled);
332 };
349 };
333 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
350 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
334 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
351 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
335
352
336 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
353 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
337 }
354 }
338
355
339 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
356 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
340 {
357 {
358 impl->m_RefRange = ui->widget->xAxis->range();
341 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
359 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
342 }
360 }
343
361
344 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
362 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
345 {
363 {
346 impl->m_IsCalibration = false;
364 impl->m_IsCalibration = false;
365 processRangeChange();
347 }
366 }
348
367
349 void VisualizationGraphWidget::onDataCacheVariableUpdated()
368 void VisualizationGraphWidget::onDataCacheVariableUpdated()
350 {
369 {
351 // NOTE:
370 // NOTE:
352 // We don't want to call the method for each component of a variable unitarily, but for
371 // We don't want to call the method for each component of a variable unitarily, but for
353 // all
372 // all
354 // its components at once (eg its three components in the case of a vector).
373 // its components at once (eg its three components in the case of a vector).
355
374
356 // The unordered_multimap does not do this easily, so the question is whether to:
375 // The unordered_multimap does not do this easily, so the question is whether to:
357 // - use an ordered_multimap and the algos of std to group the values by key
376 // - use an ordered_multimap and the algos of std to group the values by key
358 // - use a map (unique keys) and store as values directly the list of components
377 // - use a map (unique keys) and store as values directly the list of components
359
378
360 auto grapheRange = ui->widget->xAxis->range();
379 auto grapheRange = ui->widget->xAxis->range();
361 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
380 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
362
381
363 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
382 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
364 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
383 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
365 auto variable = it->first;
384 auto variable = it->first;
366 qCDebug(LOG_VisualizationGraphWidget())
385 qCDebug(LOG_VisualizationGraphWidget())
367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
386 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
368 << variable->dateTime();
387 << variable->dateTime();
369 qCDebug(LOG_VisualizationGraphWidget())
388 qCDebug(LOG_VisualizationGraphWidget())
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
389 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
371 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
390 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
372
391
373 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
392 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
374 variable->dataSeries(), variable->dateTime());
393 variable->dataSeries(), variable->dateTime());
375 }
394 }
376 }
395 }
377 }
396 }
378
397
379 VisualizationGraphWidgetZoomType
398 VisualizationGraphWidgetZoomType
380 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
399 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
381 const QCPRange &t2)
400 const QCPRange &t2)
382 {
401 {
383 // t1.lower <= t2.lower && t2.upper <= t1.upper
402 // t1.lower <= t2.lower && t2.upper <= t1.upper
384 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
403 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
385 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
404 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
386 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
405 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
387 }
406 }
388 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
407 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
389 zoomType = VisualizationGraphWidgetZoomType::PanRight;
408 zoomType = VisualizationGraphWidgetZoomType::PanRight;
390 }
409 }
391 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
410 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
392 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
411 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
393 }
412 }
394 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
413 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
395 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
414 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
396 }
415 }
397 else {
416 else {
398 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
417 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
399 }
418 }
400 return zoomType;
419 return zoomType;
401 }
420 }
General Comments 0
You need to be logged in to leave comments. Login now