##// END OF EJS Templates
Add synchronization that keep delta
perrinel -
r444:c857efd82181
parent child
Show More
@@ -1,66 +1,78
1 1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 9 #include <memory>
10 10
11 11 #include <Common/spimpl.h>
12 12
13 13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 14
15 15 class QCPRange;
16 16 class SqpDateTime;
17 17 class Variable;
18 18
19 /**
20 * Possible types of zoom operation
21 */
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
23
19 24 namespace Ui {
20 25 class VisualizationGraphWidget;
21 26 } // namespace Ui
22 27
23 28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
24 29 Q_OBJECT
25 30
26 31 public:
27 32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
28 33 virtual ~VisualizationGraphWidget();
29 34
35 void enableSynchronize(bool enable);
36
30 37 void addVariable(std::shared_ptr<Variable> variable);
31 38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
32 39 /// Removes a variable from the graph
33 40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
34 41
35 /// Rescale the X axe to range parameter
36 42 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
43 SqpDateTime graphRange();
44 void setGraphRange(const SqpDateTime &range);
37 45
38 46 // IVisualizationWidget interface
39 47 void accept(IVisualizationWidgetVisitor *visitor) override;
40 48 bool canDrop(const Variable &variable) const override;
41 49 bool contains(const Variable &variable) const override;
42 50 QString name() const override;
43 51
52
44 53 signals:
45 54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
55 void synchronize(const SqpDateTime &dateTime, const SqpDateTime &oldDateTime,
56 VisualizationGraphWidgetZoomType zoomType);
46 57
47 58
48 59 private:
49 60 Ui::VisualizationGraphWidget *ui;
50 61
51 62 class VisualizationGraphWidgetPrivate;
52 63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
53 64
54 65 private slots:
55 66 /// Slot called when right clicking on the graph (displays a menu)
56 67 void onGraphMenuRequested(const QPoint &pos) noexcept;
57 68
58 void onRangeChanged(const QCPRange &t1);
69 /// Rescale the X axe to range parameter
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
59 71
60 72 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
61 73 void onMouseWheel(QWheelEvent *event) noexcept;
62 74
63 75 void onDataCacheVariableUpdated();
64 76 };
65 77
66 78 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,307 +1,362
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphHelper.h"
4 4 #include "ui_VisualizationGraphWidget.h"
5 5
6 6 #include <Data/ArrayData.h>
7 7 #include <Data/IDataSeries.h>
8 8 #include <SqpApplication.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <unordered_map>
13 13
14 14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15 15
16 16 namespace {
17 17
18 18 /// Key pressed to enable zoom on horizontal axis
19 19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20 20
21 21 /// Key pressed to enable zoom on vertical axis
22 22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23 23
24 24 } // namespace
25 25
26 26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27 27
28 explicit VisualizationGraphWidgetPrivate() : m_DoSynchronize(true) {}
29
28 30 // 1 variable -> n qcpplot
29 31 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
32
33 bool m_DoSynchronize;
30 34 };
31 35
32 36 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
33 37 : QWidget{parent},
34 38 ui{new Ui::VisualizationGraphWidget},
35 39 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
36 40 {
37 41 ui->setupUi(this);
38 42
39 43 ui->graphNameLabel->setText(name);
40 44
41 45 // 'Close' options : widget is deleted when closed
42 46 setAttribute(Qt::WA_DeleteOnClose);
43 47 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
44 48 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
45 49
46 50 // Set qcpplot properties :
47 51 // - Drag (on x-axis) and zoom are enabled
48 52 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
49 53 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
50 54 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
51 55 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
52 connect(ui->widget->xAxis,
53 static_cast<void (QCPAxis::*)(const QCPRange &)>(&QCPAxis::rangeChanged), this,
54 &VisualizationGraphWidget::onRangeChanged);
56 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
57 &QCPAxis::rangeChanged),
58 this, &VisualizationGraphWidget::onRangeChanged);
55 59
56 60 // Activates menu when right clicking on the graph
57 61 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
58 62 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
59 63 &VisualizationGraphWidget::onGraphMenuRequested);
60 64
61 65 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
62 66 &VariableController::onRequestDataLoading);
63 67 }
64 68
65 69
66 70 VisualizationGraphWidget::~VisualizationGraphWidget()
67 71 {
68 72 delete ui;
69 73 }
70 74
75 void VisualizationGraphWidget::enableSynchronize(bool enable)
76 {
77 impl->m_DoSynchronize = enable;
78 }
79
71 80 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
72 81 {
73 82 // Uses delegate to create the qcpplot components according to the variable
74 83 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
75 84
76 85 for (auto createdPlottable : qAsConst(createdPlottables)) {
77 86 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
78 87 }
79 88
80 89 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
81 90 }
82 91 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
83 92 {
84 93
85 94 // when adding a variable, we need to set its time range to the current graph range
86 95 auto grapheRange = ui->widget->xAxis->range();
87 96 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
88 97 variable->setDateTime(dateTime);
89 98
90 99 auto variableDateTimeWithTolerance = dateTime;
91 100
92 101 // add 10% tolerance for each side
93 102 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
94 103 variableDateTimeWithTolerance.m_TStart -= tolerance;
95 104 variableDateTimeWithTolerance.m_TEnd += tolerance;
96 105
97 106 // Uses delegate to create the qcpplot components according to the variable
98 107 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
99 108
100 109 for (auto createdPlottable : qAsConst(createdPlottables)) {
101 110 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
102 111 }
103 112
104 113 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
105 114
106 115 // CHangement detected, we need to ask controller to request data loading
107 116 emit requestDataLoading(variable, variableDateTimeWithTolerance);
108 117 }
109 118
110 119 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
111 120 {
112 121 // Each component associated to the variable :
113 122 // - is removed from qcpplot (which deletes it)
114 123 // - is no longer referenced in the map
115 124 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
116 125 for (auto it = componentsIt.first; it != componentsIt.second;) {
117 126 ui->widget->removePlottable(it->second);
118 127 it = impl->m_VariableToPlotMultiMap.erase(it);
119 128 }
120 129
121 130 // Updates graph
122 131 ui->widget->replot();
123 132 }
124 133
125 134 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
126 135 const SqpDateTime &range)
127 136 {
128 137 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
129 138 // for (auto it = componentsIt.first; it != componentsIt.second;) {
130 139 // }
131 140 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
141 ui->widget->replot();
142 }
143
144 SqpDateTime VisualizationGraphWidget::graphRange()
145 {
146 auto grapheRange = ui->widget->xAxis->range();
147 return SqpDateTime{grapheRange.lower, grapheRange.upper};
148 }
149
150 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
151 {
152 qCDebug(LOG_VisualizationGraphWidget())
153 << tr("VisualizationGraphWidget::setGraphRange START");
154 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
155 ui->widget->replot();
156 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
132 157 }
133 158
134 159 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
135 160 {
136 161 if (visitor) {
137 162 visitor->visit(this);
138 163 }
139 164 else {
140 165 qCCritical(LOG_VisualizationGraphWidget())
141 166 << tr("Can't visit widget : the visitor is null");
142 167 }
143 168 }
144 169
145 170 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
146 171 {
147 172 /// @todo : for the moment, a graph can always accomodate a variable
148 173 Q_UNUSED(variable);
149 174 return true;
150 175 }
151 176
152 177 bool VisualizationGraphWidget::contains(const Variable &variable) const
153 178 {
154 179 // Finds the variable among the keys of the map
155 180 auto variablePtr = &variable;
156 181 auto findVariable
157 182 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
158 183
159 184 auto end = impl->m_VariableToPlotMultiMap.cend();
160 185 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
161 186 return it != end;
162 187 }
163 188
164 189 QString VisualizationGraphWidget::name() const
165 190 {
166 191 return ui->graphNameLabel->text();
167 192 }
168 193
169 194 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
170 195 {
171 196 QMenu graphMenu{};
172 197
173 198 // Iterates on variables (unique keys)
174 199 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
175 200 end = impl->m_VariableToPlotMultiMap.cend();
176 201 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
177 202 // 'Remove variable' action
178 203 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
179 204 [ this, var = it->first ]() { removeVariable(var); });
180 205 }
181 206
182 207 if (!graphMenu.isEmpty()) {
183 208 graphMenu.exec(mapToGlobal(pos));
184 209 }
185 210 }
186 211
187 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1)
212 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
188 213 {
189 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
190 << QThread::currentThread()->objectName();
214 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
215 << QThread::currentThread()->objectName();
216
217 auto dateTimeRange = SqpDateTime{t1.lower, t1.upper};
191 218
219 auto zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
192 220 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
193 221 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
194 222
195 223 auto variable = it->first;
196 auto dateTime = SqpDateTime{t1.lower, t1.upper};
197 auto dateTimeRange = dateTime;
224 auto currentDateTime = dateTimeRange;
198 225
199 226 auto toleranceFactor = 0.2;
200 auto tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
201 auto variableDateTimeWithTolerance = dateTime;
227 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
228 auto variableDateTimeWithTolerance = currentDateTime;
202 229 variableDateTimeWithTolerance.m_TStart -= tolerance;
203 230 variableDateTimeWithTolerance.m_TEnd += tolerance;
204 231
205 qCDebug(LOG_VisualizationGraphWidget()) << "v" << dateTime;
206 qCDebug(LOG_VisualizationGraphWidget()) << "vtol" << variableDateTimeWithTolerance;
232 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
233 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
234 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
207 235 // If new range with tol is upper than variable datetime parameters. we need to request new
208 236 // data
209 237 if (!variable->contains(variableDateTimeWithTolerance)) {
210 238
211 auto variableDateTimeWithTolerance = dateTime;
212 if (!variable->isInside(dateTime)) {
239 auto variableDateTimeWithTolerance = currentDateTime;
240 if (!variable->isInside(currentDateTime)) {
213 241 auto variableDateTime = variable->dateTime();
214 if (variableDateTime.m_TStart < dateTime.m_TStart) {
215 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
242 if (variable->contains(variableDateTimeWithTolerance)) {
243 qCInfo(LOG_VisualizationGraphWidget())
244 << tr("TORM: Detection zoom in that need request:");
245 // add 10% tolerance for each side
246 tolerance
247 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
248 variableDateTimeWithTolerance.m_TStart -= tolerance;
249 variableDateTimeWithTolerance.m_TEnd += tolerance;
250 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
251 }
252 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
253 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
216 254
217 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
218 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
255 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
256 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
219 257 // Tolerance have to be added to the right
220 258 // add tolerance for right (end) side
221 tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
259 tolerance
260 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
222 261 variableDateTimeWithTolerance.m_TEnd += tolerance;
262 zoomType = VisualizationGraphWidgetZoomType::PanRight;
223 263 }
224 else if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
225 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
226 auto diffStartToKeepDelta = variableDateTime.m_TStart - dateTime.m_TStart;
227 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
264 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
265 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
266 auto diffStartToKeepDelta
267 = variableDateTime.m_TStart - currentDateTime.m_TStart;
268 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
228 269 // Tolerance have to be added to the left
229 270 // add tolerance for left (start) side
230 tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
271 tolerance
272 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
231 273 variableDateTimeWithTolerance.m_TStart -= tolerance;
274 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
232 275 }
233 276 else {
234 qCDebug(LOG_VisualizationGraphWidget())
277 qCInfo(LOG_VisualizationGraphWidget())
235 278 << tr("Detection anormal zoom detection: ");
279 zoomType = VisualizationGraphWidgetZoomType::Unknown;
236 280 }
237 281 }
238 282 else {
239 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom out: ");
283 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
240 284 // add 10% tolerance for each side
241 tolerance = 0.2 * (dateTime.m_TEnd - dateTime.m_TStart);
285 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
242 286 variableDateTimeWithTolerance.m_TStart -= tolerance;
243 287 variableDateTimeWithTolerance.m_TEnd += tolerance;
288 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
244 289 }
245 290 if (!variable->contains(dateTimeRange)) {
246 qCDebug(LOG_VisualizationGraphWidget())
247 << "TORM: Modif on variable datetime detected" << dateTime;
248 variable->setDateTime(dateTime);
291 qCInfo(LOG_VisualizationGraphWidget())
292 << "TORM: Modif on variable datetime detected" << currentDateTime;
293 variable->setDateTime(currentDateTime);
249 294 }
250 295
251 qCDebug(LOG_VisualizationGraphWidget()) << tr("Request data detection: ");
296 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
252 297 // CHangement detected, we need to ask controller to request data loading
253 298 emit requestDataLoading(variable, variableDateTimeWithTolerance);
254 299 }
255 300 else {
256 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom in: ");
301 qCInfo(LOG_VisualizationGraphWidget())
302 << tr("TORM: Detection zoom in that doesn't need request: ");
303 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
257 304 }
258 305 }
306
307 if (impl->m_DoSynchronize) {
308 auto oldDateTime = SqpDateTime{t2.lower, t2.upper};
309 qCDebug(LOG_VisualizationGraphWidget())
310 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
311 << QThread::currentThread()->objectName();
312 emit synchronize(dateTimeRange, oldDateTime, zoomType);
313 }
259 314 }
260 315
261 316 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
262 317 {
263 318 auto zoomOrientations = QFlags<Qt::Orientation>{};
264 319
265 320 // Lambda that enables a zoom orientation if the key modifier related to this orientation
266 321 // has
267 322 // been pressed
268 323 auto enableOrientation
269 324 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
270 325 auto orientationEnabled = event->modifiers().testFlag(modifier);
271 326 zoomOrientations.setFlag(orientation, orientationEnabled);
272 327 };
273 328 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
274 329 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
275 330
276 331 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
277 332 }
278 333
279 334 void VisualizationGraphWidget::onDataCacheVariableUpdated()
280 335 {
281 336 // NOTE:
282 337 // We don't want to call the method for each component of a variable unitarily, but for
283 338 // all
284 339 // its components at once (eg its three components in the case of a vector).
285 340
286 341 // The unordered_multimap does not do this easily, so the question is whether to:
287 342 // - use an ordered_multimap and the algos of std to group the values by key
288 343 // - use a map (unique keys) and store as values directly the list of components
289 344
290 345 auto grapheRange = ui->widget->xAxis->range();
291 346 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
292 347
293 348 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
294 349 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
295 350 auto variable = it->first;
296 351 qCDebug(LOG_VisualizationGraphWidget())
297 352 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
298 353 << variable->dateTime();
299 354 qCDebug(LOG_VisualizationGraphWidget())
300 355 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
301 356 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
302 357
303 358 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
304 359 variable->dataSeries(), variable->dateTime());
305 360 }
306 361 }
307 362 }
@@ -1,111 +1,180
1 1 #include "Visualization/VisualizationZoneWidget.h"
2
3 #include "Data/SqpDateTime.h"
4
2 5 #include "Visualization/IVisualizationWidgetVisitor.h"
6 #include "Visualization/VisualizationGraphWidget.h"
3 7 #include "ui_VisualizationZoneWidget.h"
4 8
5 #include "Visualization/VisualizationGraphWidget.h"
6 9
7 10 #include <SqpApplication.h>
8 11
9 12 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
10 13
11 14 namespace {
12 15
13 16 /// Minimum height for graph added in zones (in pixels)
14 17 const auto GRAPH_MINIMUM_HEIGHT = 300;
15 18
16 19 /// Generates a default name for a new graph, according to the number of graphs already displayed in
17 20 /// the zone
18 21 QString defaultGraphName(const QLayout &layout)
19 22 {
20 23 auto count = 0;
21 24 for (auto i = 0; i < layout.count(); ++i) {
22 25 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
23 26 count++;
24 27 }
25 28 }
26 29
27 30 return QObject::tr("Graph %1").arg(count + 1);
28 31 }
29 32
30 33 } // namespace
31 34
32 35 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
33 36 : QWidget{parent}, ui{new Ui::VisualizationZoneWidget}
34 37 {
35 38 ui->setupUi(this);
36 39
37 40 ui->zoneNameLabel->setText(name);
38 41
39 42 // 'Close' options : widget is deleted when closed
40 43 setAttribute(Qt::WA_DeleteOnClose);
41 44 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
42 45 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
43 46 }
44 47
45 48 VisualizationZoneWidget::~VisualizationZoneWidget()
46 49 {
47 50 delete ui;
48 51 }
49 52
50 53 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
51 54 {
52 55 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
53 56 }
54 57
55 58 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
56 59 {
57 60 auto graphWidget = new VisualizationGraphWidget{
58 61 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
59 62
63
60 64 // Set graph properties
61 65 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
62 66 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
63 67
64 68 this->addGraph(graphWidget);
65 69
66 70 graphWidget->addVariable(variable);
67 71
72 // Lambda to synchronize zone widget
73 auto synchronizeZoneWidget = [this, graphWidget](const SqpDateTime &dateTime,
74 const SqpDateTime &oldDateTime,
75 VisualizationGraphWidgetZoomType zoomType) {
76 auto frameLayout = ui->visualizationZoneFrame->layout();
77 for (auto i = 0; i < frameLayout->count(); ++i) {
78 auto graphChild
79 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
80 if (graphChild && (graphChild != graphWidget)) {
81
82 auto dateTimeThatKeepDelta = dateTime;
83 auto graphChildRange = graphChild->graphRange();
84 switch (zoomType) {
85 case VisualizationGraphWidgetZoomType::ZoomIn: {
86 auto deltaLeft = dateTime.m_TStart - oldDateTime.m_TStart;
87 auto deltaRight = oldDateTime.m_TEnd - dateTime.m_TEnd;
88 graphChildRange.m_TStart += deltaLeft;
89 graphChildRange.m_TEnd -= deltaRight;
90 dateTimeThatKeepDelta = graphChildRange;
91 break;
92 }
93
94 case VisualizationGraphWidgetZoomType::ZoomOut: {
95 auto deltaLeft = oldDateTime.m_TStart - dateTime.m_TStart;
96 auto deltaRight = dateTime.m_TEnd - oldDateTime.m_TEnd;
97 graphChildRange.m_TStart -= deltaLeft;
98 graphChildRange.m_TEnd += deltaRight;
99 dateTimeThatKeepDelta = graphChildRange;
100 break;
101 }
102 case VisualizationGraphWidgetZoomType::PanRight: {
103 auto deltaRight = dateTime.m_TEnd - oldDateTime.m_TEnd;
104 graphChildRange.m_TStart += deltaRight;
105 graphChildRange.m_TEnd += deltaRight;
106 dateTimeThatKeepDelta = graphChildRange;
107 break;
108 }
109 case VisualizationGraphWidgetZoomType::PanLeft: {
110 auto deltaLeft = oldDateTime.m_TStart - dateTime.m_TStart;
111 graphChildRange.m_TStart -= deltaLeft;
112 graphChildRange.m_TEnd -= deltaLeft;
113 dateTimeThatKeepDelta = graphChildRange;
114 break;
115 }
116 case VisualizationGraphWidgetZoomType::Unknown: {
117 qCCritical(LOG_VisualizationZoneWidget())
118 << tr("Impossible to synchronize: zoom type unknown");
119 break;
120 }
121 default:
122 qCCritical(LOG_VisualizationZoneWidget())
123 << tr("Impossible to synchronize: zoom type not take into account");
124 // No action
125 break;
126 }
127 graphChild->enableSynchronize(false);
128 graphChild->setGraphRange(dateTimeThatKeepDelta);
129 graphChild->enableSynchronize(true);
130 }
131 }
132 };
133
134 // connection for synchronization
135 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
136
68 137 return graphWidget;
69 138 }
70 139
71 140 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
72 141 {
73 142 if (visitor) {
74 143 visitor->visitEnter(this);
75 144
76 145 // Apply visitor to graph children
77 146 auto layout = ui->visualizationZoneFrame->layout();
78 147 for (auto i = 0; i < layout->count(); ++i) {
79 148 if (auto item = layout->itemAt(i)) {
80 149 // Widgets different from graphs are not visited (no action)
81 150 if (auto visualizationGraphWidget
82 151 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
83 152 visualizationGraphWidget->accept(visitor);
84 153 }
85 154 }
86 155 }
87 156
88 157 visitor->visitLeave(this);
89 158 }
90 159 else {
91 160 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
92 161 }
93 162 }
94 163
95 164 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
96 165 {
97 166 // A tab can always accomodate a variable
98 167 Q_UNUSED(variable);
99 168 return true;
100 169 }
101 170
102 171 bool VisualizationZoneWidget::contains(const Variable &variable) const
103 172 {
104 173 Q_UNUSED(variable);
105 174 return false;
106 175 }
107 176
108 177 QString VisualizationZoneWidget::name() const
109 178 {
110 179 return ui->zoneNameLabel->text();
111 180 }
General Comments 0
You need to be logged in to leave comments. Login now