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