@@ -70,7 +70,7 public: | |||
|
70 | 70 | /// Sets the y-axis range based on the data of a variable |
|
71 | 71 | void setYRange(std::shared_ptr<Variable> variable); |
|
72 | 72 | DateTimeRange graphRange() const noexcept; |
|
73 |
void setGraphRange(const DateTimeRange &range, bool |
|
|
73 | void setGraphRange(const DateTimeRange &range, bool updateVar = false); | |
|
74 | 74 | void setAutoRangeOnVariableInitialization(bool value); |
|
75 | 75 | |
|
76 | 76 | // Zones |
@@ -86,8 +86,9 public: | |||
|
86 | 86 | /// Undo the last zoom done with a zoom box |
|
87 | 87 | void undoZoom(); |
|
88 | 88 | |
|
89 | void zoom(double factor, int center, Qt::Orientation orientation); | |
|
90 | void move(double factor, Qt::Orientation orientation); | |
|
89 | void zoom(double factor, int center, Qt::Orientation orientation, bool forward=true); | |
|
90 | void move(double factor, Qt::Orientation orientation, bool forward=true); | |
|
91 | void move(double dx, double dy, bool forward=true); | |
|
91 | 92 | |
|
92 | 93 | // IVisualizationWidget interface |
|
93 | 94 | void accept(IVisualizationWidgetVisitor *visitor) override; |
@@ -122,6 +123,11 signals: | |||
|
122 | 123 | /// Signal emitted when the variable has been added to the graph |
|
123 | 124 | void variableAdded(std::shared_ptr<Variable> var); |
|
124 | 125 | |
|
126 | ||
|
127 | void zoom_sig(double factor, int center, Qt::Orientation orientation, bool forward=true); | |
|
128 | void move_sig(double factor, Qt::Orientation orientation, bool forward=true); | |
|
129 | void move_sig(double dx, double dy, bool forward=true); | |
|
130 | ||
|
125 | 131 | protected: |
|
126 | 132 | void closeEvent(QCloseEvent *event) override; |
|
127 | 133 | void enterEvent(QEvent *event) override; |
@@ -142,6 +148,7 private: | |||
|
142 | 148 | class VisualizationGraphWidgetPrivate; |
|
143 | 149 | spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl; |
|
144 | 150 | |
|
151 | void _ugly_sync_(const QPoint& pos,const QPointF& axisPos); | |
|
145 | 152 | private slots: |
|
146 | 153 | /// Slot called when right clicking on the graph (displays a menu) |
|
147 | 154 | void onGraphMenuRequested(const QPoint &pos) noexcept; |
@@ -85,6 +85,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { | |||
|
85 | 85 | bool m_IsCalibration; |
|
86 | 86 | QCustomPlot* m_plot; |
|
87 | 87 | QPoint m_lastMousePos; |
|
88 | QCPRange m_lastXRange; | |
|
89 | QCPRange m_lastYRange; | |
|
88 | 90 | /// Delegate used to attach rendering features to the plot |
|
89 | 91 | std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate; |
|
90 | 92 | |
@@ -102,9 +104,12 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { | |||
|
102 | 104 | |
|
103 | 105 | bool m_VariableAutoRangeOnInit = true; |
|
104 | 106 | |
|
105 |
inline void |
|
|
107 | inline void enterPlotDrag(const QPoint& position) | |
|
106 | 108 | { |
|
107 | m_lastMousePos = position; | |
|
109 | m_lastMousePos = m_plot->mapFromParent(position); | |
|
110 | m_lastXRange = m_plot->xAxis->range(); | |
|
111 | m_lastYRange = m_plot->yAxis->range(); | |
|
112 | ||
|
108 | 113 | } |
|
109 | 114 | |
|
110 | 115 | inline bool isDrawingZoomRect(){return m_DrawingZoomRect!=nullptr;} |
@@ -288,31 +293,98 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { | |||
|
288 | 293 | } |
|
289 | 294 | } |
|
290 | 295 | |
|
291 |
void setRange(const |
|
|
296 | void setRange(const DateTimeRange &newRange) | |
|
292 | 297 | { |
|
293 | auto graphRange = DateTimeRange{newRange.lower, newRange.upper}; | |
|
294 | ||
|
295 | 298 | if (m_Flags.testFlag(GraphFlag::EnableAcquisition)) |
|
296 | 299 | { |
|
297 | 300 | for (auto it = m_VariableToPlotMultiMap.begin(), |
|
298 | 301 | end = m_VariableToPlotMultiMap.end(); |
|
299 | 302 | it != end; it = m_VariableToPlotMultiMap.upper_bound(it->first)) |
|
300 | 303 | { |
|
301 |
sqpApp->variableController().asyncChangeRange(it->first, |
|
|
304 | sqpApp->variableController().asyncChangeRange(it->first, newRange); | |
|
302 | 305 | } |
|
303 | 306 | } |
|
304 | 307 | } |
|
305 | 308 | |
|
306 | void moveGraph(const QPoint& destination) | |
|
309 | void setRange(const QCPRange &newRange) | |
|
310 | { | |
|
311 | auto graphRange = DateTimeRange{newRange.lower, newRange.upper}; | |
|
312 | setRange(graphRange); | |
|
313 | } | |
|
314 | ||
|
315 | std::tuple<double,double> moveGraph(const QPoint& destination) | |
|
316 | { | |
|
317 | auto currentPos = m_plot->mapFromParent(destination); | |
|
318 | auto xAxis = m_plot->axisRect()->rangeDragAxis(Qt::Horizontal); | |
|
319 | auto yAxis = m_plot->axisRect()->rangeDragAxis(Qt::Vertical); | |
|
320 | auto oldXRange = xAxis->range(); | |
|
321 | auto oldYRange = yAxis->range(); | |
|
322 | double dx = xAxis->pixelToCoord(m_lastMousePos.x()) - xAxis->pixelToCoord(currentPos.x()); | |
|
323 | xAxis->setRange(m_lastXRange.lower+dx, m_lastXRange.upper+dx); | |
|
324 | if(yAxis->scaleType() == QCPAxis::stLinear) | |
|
325 | { | |
|
326 | double dy = yAxis->pixelToCoord(m_lastMousePos.y()) - yAxis->pixelToCoord(currentPos.y()); | |
|
327 | yAxis->setRange(m_lastYRange.lower+dy, m_lastYRange.upper+dy); | |
|
328 | } | |
|
329 | else | |
|
330 | { | |
|
331 | double dy = yAxis->pixelToCoord(m_lastMousePos.y()) / yAxis->pixelToCoord(currentPos.y()); | |
|
332 | yAxis->setRange(m_lastYRange.lower*dy, m_lastYRange.upper*dy); | |
|
333 | } | |
|
334 | auto newXRange = xAxis->range(); | |
|
335 | auto newYRange = yAxis->range(); | |
|
336 | setRange(xAxis->range()); | |
|
337 | m_plot->replot(QCustomPlot::rpQueuedReplot); | |
|
338 | //m_lastMousePos = currentPos; | |
|
339 | return {newXRange.lower - oldXRange.lower, newYRange.lower - oldYRange.lower}; | |
|
340 | } | |
|
341 | ||
|
342 | void zoom(double factor, int center, Qt::Orientation orientation) | |
|
343 | { | |
|
344 | QCPAxis *axis = m_plot->axisRect()->rangeZoomAxis(orientation); | |
|
345 | axis->scaleRange(factor, axis->pixelToCoord(center)); | |
|
346 | if (orientation == Qt::Horizontal) | |
|
347 | setRange(axis->range()); | |
|
348 | m_plot->replot(QCustomPlot::rpQueuedReplot); | |
|
349 | } | |
|
350 | ||
|
351 | void move(double dx, double dy) | |
|
307 | 352 | { |
|
308 | auto currentPos = destination; | |
|
309 | 353 | auto xAxis = m_plot->axisRect()->rangeDragAxis(Qt::Horizontal); |
|
310 | 354 | auto yAxis = m_plot->axisRect()->rangeDragAxis(Qt::Vertical); |
|
311 | xAxis->setRange(_pixDistanceToRange(m_lastMousePos.x(), currentPos.x(), xAxis)); | |
|
312 | yAxis->setRange(_pixDistanceToRange(m_lastMousePos.y(), currentPos.y(), yAxis)); | |
|
355 | xAxis->setRange(QCPRange(xAxis->range().lower+dx, xAxis->range().upper+dx)); | |
|
356 | yAxis->setRange(QCPRange(yAxis->range().lower+dy, yAxis->range().upper+dy)); | |
|
313 | 357 | setRange(xAxis->range()); |
|
314 | 358 | m_plot->replot(QCustomPlot::rpQueuedReplot); |
|
315 | m_lastMousePos = destination; | |
|
359 | } | |
|
360 | ||
|
361 | void move(double factor, Qt::Orientation orientation) | |
|
362 | { | |
|
363 | auto oldRange = m_plot->xAxis->range(); | |
|
364 | QCPAxis *axis = m_plot->axisRect()->rangeDragAxis(orientation); | |
|
365 | if (m_plot->xAxis->scaleType() == QCPAxis::stLinear) { | |
|
366 | double rg = (axis->range().upper - axis->range().lower) * (factor / 10); | |
|
367 | axis->setRange(axis->range().lower + (rg), axis->range().upper + (rg)); | |
|
368 | } | |
|
369 | else if (m_plot->xAxis->scaleType() == QCPAxis::stLogarithmic) { | |
|
370 | int start = 0, stop = 0; | |
|
371 | double diff = 0.; | |
|
372 | if (factor > 0.0) { | |
|
373 | stop = m_plot->width() * factor / 10; | |
|
374 | start = 2 * m_plot->width() * factor / 10; | |
|
375 | } | |
|
376 | if (factor < 0.0) { | |
|
377 | factor *= -1.0; | |
|
378 | start = m_plot->width() * factor / 10; | |
|
379 | stop = 2 * m_plot->width() * factor / 10; | |
|
380 | } | |
|
381 | diff = axis->pixelToCoord(start) / axis->pixelToCoord(stop); | |
|
382 | axis->setRange(m_plot->axisRect()->rangeDragAxis(orientation)->range().lower * diff, | |
|
383 | m_plot->axisRect()->rangeDragAxis(orientation)->range().upper * diff); | |
|
384 | } | |
|
385 | if (orientation == Qt::Horizontal) | |
|
386 | setRange(axis->range()); | |
|
387 | m_plot->replot(QCustomPlot::rpQueuedReplot); | |
|
316 | 388 | } |
|
317 | 389 | }; |
|
318 | 390 | |
@@ -448,18 +520,14 DateTimeRange VisualizationGraphWidget::graphRange() const noexcept | |||
|
448 | 520 | return DateTimeRange{graphRange.lower, graphRange.upper}; |
|
449 | 521 | } |
|
450 | 522 | |
|
451 |
void VisualizationGraphWidget::setGraphRange(const DateTimeRange &range, bool |
|
|
523 | void VisualizationGraphWidget::setGraphRange(const DateTimeRange &range, bool updateVar) | |
|
452 | 524 | { |
|
453 | if (calibration) { | |
|
454 | impl->m_IsCalibration = true; | |
|
455 | } | |
|
456 | 525 | |
|
526 | if(updateVar) | |
|
527 | impl->setRange(range); | |
|
457 | 528 | impl->m_plot->xAxis->setRange(range.m_TStart, range.m_TEnd); |
|
458 | 529 | impl->m_plot->replot(QCustomPlot::rpQueuedReplot); |
|
459 | 530 | |
|
460 | if (calibration) { | |
|
461 | impl->m_IsCalibration = false; | |
|
462 | } | |
|
463 | 531 | } |
|
464 | 532 | |
|
465 | 533 | void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value) |
@@ -529,43 +597,25 void VisualizationGraphWidget::undoZoom() | |||
|
529 | 597 | plot().replot(QCustomPlot::rpQueuedReplot); |
|
530 | 598 | } |
|
531 | 599 | |
|
532 | void VisualizationGraphWidget::zoom(double factor, int center, Qt::Orientation orientation) | |
|
600 | void VisualizationGraphWidget::zoom(double factor, int center, Qt::Orientation orientation, bool forward) | |
|
601 | { | |
|
602 | impl->zoom(factor, center, orientation); | |
|
603 | if(forward && orientation==Qt::Horizontal) | |
|
604 | emit this->zoom_sig(factor, center, orientation, false); | |
|
605 | } | |
|
533 | 606 | |
|
607 | void VisualizationGraphWidget::move(double factor, Qt::Orientation orientation, bool forward) | |
|
534 | 608 | { |
|
535 | QCPAxis *axis = impl->m_plot->axisRect()->rangeZoomAxis(orientation); | |
|
536 | axis->scaleRange(factor, axis->pixelToCoord(center)); | |
|
537 | if (orientation == Qt::Horizontal) | |
|
538 | impl->setRange(axis->range()); | |
|
539 | impl->m_plot->replot(QCustomPlot::rpQueuedReplot); | |
|
609 | impl->move(factor, orientation); | |
|
610 | if(forward) | |
|
611 | emit this->move_sig(factor, orientation, false); | |
|
540 | 612 | } |
|
541 | 613 | |
|
542 |
void VisualizationGraphWidget::move(double |
|
|
614 | void VisualizationGraphWidget::move(double dx, double dy, bool forward) | |
|
543 | 615 | { |
|
544 | auto oldRange = impl->m_plot->xAxis->range(); | |
|
545 | QCPAxis *axis = impl->m_plot->axisRect()->rangeDragAxis(orientation); | |
|
546 | if (impl->m_plot->xAxis->scaleType() == QCPAxis::stLinear) { | |
|
547 | double rg = (axis->range().upper - axis->range().lower) * (factor / 10); | |
|
548 | axis->setRange(axis->range().lower + (rg), axis->range().upper + (rg)); | |
|
549 | } | |
|
550 | else if (impl->m_plot->xAxis->scaleType() == QCPAxis::stLogarithmic) { | |
|
551 | int start = 0, stop = 0; | |
|
552 | double diff = 0.; | |
|
553 | if (factor > 0.0) { | |
|
554 | stop = this->width() * factor / 10; | |
|
555 | start = 2 * this->width() * factor / 10; | |
|
556 | } | |
|
557 | if (factor < 0.0) { | |
|
558 | factor *= -1.0; | |
|
559 | start = this->width() * factor / 10; | |
|
560 | stop = 2 * this->width() * factor / 10; | |
|
561 | } | |
|
562 | diff = axis->pixelToCoord(start) / axis->pixelToCoord(stop); | |
|
563 | axis->setRange(impl->m_plot->axisRect()->rangeDragAxis(orientation)->range().lower * diff, | |
|
564 | impl->m_plot->axisRect()->rangeDragAxis(orientation)->range().upper * diff); | |
|
565 | } | |
|
566 | if (orientation == Qt::Horizontal) | |
|
567 | impl->setRange(axis->range()); | |
|
568 | impl->m_plot->replot(QCustomPlot::rpQueuedReplot); | |
|
616 | impl->move(dx, dy); | |
|
617 | if(forward) | |
|
618 | emit this->move_sig(dx, dy, false); | |
|
569 | 619 | } |
|
570 | 620 | |
|
571 | 621 | void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor) |
@@ -782,7 +832,7 void VisualizationGraphWidget::wheelEvent(QWheelEvent *event) | |||
|
782 | 832 | else { |
|
783 | 833 | move(wheelSteps, Qt::Horizontal); |
|
784 | 834 | } |
|
785 | QWidget::wheelEvent(event); | |
|
835 | //QWidget::wheelEvent(event); | |
|
786 | 836 | } |
|
787 | 837 | |
|
788 | 838 | |
@@ -799,16 +849,14 void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent *event) | |||
|
799 | 849 | } |
|
800 | 850 | else if (event->buttons() == Qt::LeftButton) |
|
801 | 851 | { |
|
802 |
|
|
|
852 | if(sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) | |
|
803 | 853 | { |
|
804 | case SqpApplication::PlotsInteractionMode::None: | |
|
805 | impl->moveGraph(event->pos()); | |
|
806 | break; | |
|
807 |
|
|
|
808 | ||
|
809 | break; | |
|
810 | default: | |
|
811 | break; | |
|
854 | auto [dx,dy] = impl->moveGraph(event->pos()); | |
|
855 | emit this->move_sig(dx,0., false); // don't sync Y transformations | |
|
856 | } | |
|
857 | else if(sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) | |
|
858 | { | |
|
859 | ||
|
812 | 860 | } |
|
813 | 861 | } |
|
814 | 862 | else |
@@ -872,7 +920,7 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event) | |||
|
872 | 920 | break; |
|
873 | 921 | default: |
|
874 | 922 | setCursor(Qt::ClosedHandCursor); |
|
875 |
impl-> |
|
|
923 | impl->enterPlotDrag(event->pos()); | |
|
876 | 924 | } |
|
877 | 925 | } |
|
878 | 926 | QWidget::mousePressEvent(event); |
@@ -960,7 +1008,7 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept | |||
|
960 | 1008 | |
|
961 | 1009 | // Iterates on variables (unique keys) |
|
962 | 1010 | for (auto it = impl->m_VariableToPlotMultiMap.cbegin(), |
|
963 |
|
|
|
1011 | end = impl->m_VariableToPlotMultiMap.cend(); | |
|
964 | 1012 | it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) { |
|
965 | 1013 | // 'Remove variable' action |
|
966 | 1014 | graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()), |
@@ -172,14 +172,41 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget) | |||
|
172 | 172 | impl->m_Synchronizer->addGraph(*graphWidget); |
|
173 | 173 | |
|
174 | 174 | ui->dragDropContainer->addDragWidget(graphWidget); |
|
175 | ||
|
175 | 176 | } |
|
176 | 177 | |
|
177 | 178 | void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget) |
|
178 | 179 | { |
|
180 | DEPRECATE( | |
|
181 | auto layout = ui->dragDropContainer->layout(); | |
|
182 | for(int i=0;i<layout->count();i++) | |
|
183 | { | |
|
184 | auto graph = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(i)->widget()); | |
|
185 | connect(graphWidget, &VisualizationGraphWidget::zoom_sig, graph, &VisualizationGraphWidget::zoom); | |
|
186 | ||
|
187 | connect(graphWidget, qOverload<double,Qt::Orientation,bool>(&VisualizationGraphWidget::move_sig), | |
|
188 | graph, qOverload<double,Qt::Orientation,bool>(&VisualizationGraphWidget::move)); | |
|
189 | connect(graphWidget, qOverload<double,double,bool>(&VisualizationGraphWidget::move_sig), | |
|
190 | graph, qOverload<double,double,bool>(&VisualizationGraphWidget::move)); | |
|
191 | ||
|
192 | connect(graph, &VisualizationGraphWidget::zoom_sig, graphWidget, &VisualizationGraphWidget::zoom); | |
|
193 | ||
|
194 | connect(graph, qOverload<double,Qt::Orientation,bool>(&VisualizationGraphWidget::move_sig), | |
|
195 | graphWidget, qOverload<double,Qt::Orientation,bool>(&VisualizationGraphWidget::move)); | |
|
196 | connect(graph, qOverload<double,double,bool>(&VisualizationGraphWidget::move_sig), | |
|
197 | graphWidget, qOverload<double,double,bool>(&VisualizationGraphWidget::move)); | |
|
198 | } | |
|
199 | if(auto graph = firstGraph()) | |
|
200 | { | |
|
201 | graphWidget->setGraphRange(graph->graphRange(), true); | |
|
202 | } | |
|
203 | ) | |
|
204 | ||
|
179 | 205 | // Synchronize new graph with others in the zone |
|
180 | 206 | impl->m_Synchronizer->addGraph(*graphWidget); |
|
181 | 207 | |
|
182 | 208 | ui->dragDropContainer->insertDragWidget(index, graphWidget); |
|
209 | ||
|
183 | 210 | } |
|
184 | 211 | |
|
185 | 212 | VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable) |
General Comments 0
You need to be logged in to leave comments.
Login now