@@ -86,6 +86,9 public: | |||||
86 | /// Undo the last zoom done with a zoom box |
|
86 | /// Undo the last zoom done with a zoom box | |
87 | void undoZoom(); |
|
87 | void undoZoom(); | |
88 |
|
88 | |||
|
89 | void zoom(double factor, int center, Qt::Orientation orientation); | |||
|
90 | void move(double factor, Qt::Orientation orientation); | |||
|
91 | ||||
89 | // IVisualizationWidget interface |
|
92 | // IVisualizationWidget interface | |
90 | void accept(IVisualizationWidgetVisitor *visitor) override; |
|
93 | void accept(IVisualizationWidgetVisitor *visitor) override; | |
91 | bool canDrop(const Variable &variable) const override; |
|
94 | bool canDrop(const Variable &variable) const override; | |
@@ -123,6 +126,12 protected: | |||||
123 | void closeEvent(QCloseEvent *event) override; |
|
126 | void closeEvent(QCloseEvent *event) override; | |
124 | void enterEvent(QEvent *event) override; |
|
127 | void enterEvent(QEvent *event) override; | |
125 | void leaveEvent(QEvent *event) override; |
|
128 | void leaveEvent(QEvent *event) override; | |
|
129 | void wheelEvent(QWheelEvent * event) override; | |||
|
130 | void mouseMoveEvent(QMouseEvent *event) override; | |||
|
131 | void mouseReleaseEvent(QMouseEvent *event) override; | |||
|
132 | void mousePressEvent(QMouseEvent *event) override; | |||
|
133 | void keyReleaseEvent(QKeyEvent * event) override; | |||
|
134 | void keyPressEvent(QKeyEvent * event) override; | |||
126 |
|
135 | |||
127 | QCustomPlot &plot() const noexcept; |
|
136 | QCustomPlot &plot() const noexcept; | |
128 |
|
137 | |||
@@ -131,13 +140,13 private: | |||||
131 |
|
140 | |||
132 | class VisualizationGraphWidgetPrivate; |
|
141 | class VisualizationGraphWidgetPrivate; | |
133 | spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl; |
|
142 | spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl; | |
134 |
|
143 | QPoint _dragLastPos; | ||
135 | private slots: |
|
144 | private slots: | |
136 | /// Slot called when right clicking on the graph (displays a menu) |
|
145 | /// Slot called when right clicking on the graph (displays a menu) | |
137 | void onGraphMenuRequested(const QPoint &pos) noexcept; |
|
146 | void onGraphMenuRequested(const QPoint &pos) noexcept; | |
138 |
|
147 | |||
139 | /// Rescale the X axe to range parameter |
|
148 | /// Rescale the X axe to range parameter | |
140 |
void onRangeChanged(const QCPRange & |
|
149 | void onRangeChanged(const QCPRange &newRange, const QCPRange &oldRange); | |
141 |
|
150 | |||
142 | /// Slot called when a mouse double click was made |
|
151 | /// Slot called when a mouse double click was made | |
143 | void onMouseDoubleClick(QMouseEvent *event) noexcept; |
|
152 | void onMouseDoubleClick(QMouseEvent *event) noexcept; |
@@ -231,16 +231,22 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget | |||||
231 | impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot()); |
|
231 | impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot()); | |
232 | impl->m_VerticalCursor->setOrientation(Qt::Vertical); |
|
232 | impl->m_VerticalCursor->setOrientation(Qt::Vertical); | |
233 |
|
233 | |||
234 | connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress); |
|
234 | // β swhitch to this ASAP, VisualizationGraphWidget should intercept all UI events | |
235 | connect(ui->widget, &QCustomPlot::mouseRelease, this, |
|
235 | this->setFocusPolicy(Qt::WheelFocus); | |
236 | &VisualizationGraphWidget::onMouseRelease); |
|
236 | ui->widget->setAttribute(Qt::WA_TransparentForMouseEvents); | |
237 |
connect(ui->widget, &QCustomPlot::mouse |
|
237 | // connect(ui->widget, &QCustomPlot::mousePress, this, | |
238 | connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel); |
|
238 | // &VisualizationGraphWidget::onMousePress); connect(ui->widget, &QCustomPlot::mouseRelease, | |
239 | connect(ui->widget, &QCustomPlot::mouseDoubleClick, this, |
|
239 | // this, | |
240 |
&VisualizationGraphWidget::onMouse |
|
240 | // &VisualizationGraphWidget::onMouseRelease); | |
241 | connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>( |
|
241 | // connect(ui->widget, &QCustomPlot::mouseMove, this, | |
242 | &QCPAxis::rangeChanged), |
|
242 | // &VisualizationGraphWidget::onMouseMove); connect(ui->widget, &QCustomPlot::mouseWheel, | |
243 |
this, &VisualizationGraphWidget::on |
|
243 | // this, &VisualizationGraphWidget::onMouseWheel); connect(ui->widget, | |
|
244 | // &QCustomPlot::mouseDoubleClick, this, | |||
|
245 | // &VisualizationGraphWidget::onMouseDoubleClick); | |||
|
246 | // connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange | |||
|
247 | // &)>( | |||
|
248 | // &QCPAxis::rangeChanged), | |||
|
249 | // this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection); | |||
244 |
|
250 | |||
245 | // Activates menu when right clicking on the graph |
|
251 | // Activates menu when right clicking on the graph | |
246 | ui->widget->setContextMenuPolicy(Qt::CustomContextMenu); |
|
252 | ui->widget->setContextMenuPolicy(Qt::CustomContextMenu); | |
@@ -248,11 +254,12 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget | |||||
248 | &VisualizationGraphWidget::onGraphMenuRequested); |
|
254 | &VisualizationGraphWidget::onGraphMenuRequested); | |
249 |
|
255 | |||
250 | //@TODO implement this :) |
|
256 | //@TODO implement this :) | |
251 |
// connect(this, &VisualizationGraphWidget::requestDataLoading, |
|
257 | // connect(this, &VisualizationGraphWidget::requestDataLoading, | |
252 | // &VariableController::onRequestDataLoading); |
|
258 | // &sqpApp->variableController(), | |
|
259 | // &VariableController::onRequestDataLoading); | |||
253 |
|
260 | |||
254 | // connect(&sqpApp->variableController(), &VariableController2::updateVarDisplaying, this, |
|
261 | // connect(&sqpApp->variableController(), &VariableController2::updateVarDisplaying, this, | |
255 | // &VisualizationGraphWidget::onUpdateVarDisplaying); |
|
262 | // &VisualizationGraphWidget::onUpdateVarDisplaying); | |
256 |
|
263 | |||
257 | // Necessary for all platform since Qt::AA_EnableHighDpiScaling is enable. |
|
264 | // Necessary for all platform since Qt::AA_EnableHighDpiScaling is enable. | |
258 | plot().setPlottingHint(QCP::phFastPolylines, true); |
|
265 | plot().setPlottingHint(QCP::phFastPolylines, true); | |
@@ -308,8 +315,8 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, D | |||||
308 | } |
|
315 | } | |
309 | //@TODO this is bad! when variable is moved to another graph it still fires |
|
316 | //@TODO this is bad! when variable is moved to another graph it still fires | |
310 | // even if this has been deleted |
|
317 | // even if this has been deleted | |
311 | connect(variable.get(),&Variable::updated,this, &VisualizationGraphWidget::variableUpdated); |
|
318 | connect(variable.get(), &Variable::updated, this, &VisualizationGraphWidget::variableUpdated); | |
312 | this->onUpdateVarDisplaying(variable,range);//My bullshit |
|
319 | this->onUpdateVarDisplaying(variable, range); // My bullshit | |
313 | emit variableAdded(variable); |
|
320 | emit variableAdded(variable); | |
314 | } |
|
321 | } | |
315 |
|
322 | |||
@@ -334,7 +341,7 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable | |||||
334 | } |
|
341 | } | |
335 |
|
342 | |||
336 | // Updates graph |
|
343 | // Updates graph | |
337 | ui->widget->replot(); |
|
344 | ui->widget->replot(QCustomPlot::rpQueuedReplot); | |
338 | } |
|
345 | } | |
339 |
|
346 | |||
340 | std::vector<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const |
|
347 | std::vector<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const | |
@@ -342,7 +349,7 std::vector<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() co | |||||
342 | auto variables = std::vector<std::shared_ptr<Variable> >{}; |
|
349 | auto variables = std::vector<std::shared_ptr<Variable> >{}; | |
343 | for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap); |
|
350 | for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap); | |
344 | it != std::cend(impl->m_VariableToPlotMultiMap); ++it) { |
|
351 | it != std::cend(impl->m_VariableToPlotMultiMap); ++it) { | |
345 |
variables.push_back |
|
352 | variables.push_back(it->first); | |
346 | } |
|
353 | } | |
347 |
|
354 | |||
348 | return variables; |
|
355 | return variables; | |
@@ -371,7 +378,7 void VisualizationGraphWidget::setGraphRange(const DateTimeRange &range, bool ca | |||||
371 | } |
|
378 | } | |
372 |
|
379 | |||
373 | ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd); |
|
380 | ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd); | |
374 | ui->widget->replot(); |
|
381 | ui->widget->replot(QCustomPlot::rpQueuedReplot); | |
375 |
|
382 | |||
376 | if (calibration) { |
|
383 | if (calibration) { | |
377 | impl->m_IsCalibration = false; |
|
384 | impl->m_IsCalibration = false; | |
@@ -405,8 +412,8 void VisualizationGraphWidget::addSelectionZones(const QVector<DateTimeRange> &r | |||||
405 | plot().replot(QCustomPlot::rpQueuedReplot); |
|
412 | plot().replot(QCustomPlot::rpQueuedReplot); | |
406 | } |
|
413 | } | |
407 |
|
414 | |||
408 | VisualizationSelectionZoneItem *VisualizationGraphWidget::addSelectionZone(const QString &name, |
|
415 | VisualizationSelectionZoneItem * | |
409 | const DateTimeRange &range) |
|
416 | VisualizationGraphWidget::addSelectionZone(const QString &name, const DateTimeRange &range) | |
410 | { |
|
417 | { | |
411 | // note: ownership is transfered to QCustomPlot |
|
418 | // note: ownership is transfered to QCustomPlot | |
412 | auto zone = new VisualizationSelectionZoneItem(&plot()); |
|
419 | auto zone = new VisualizationSelectionZoneItem(&plot()); | |
@@ -445,6 +452,46 void VisualizationGraphWidget::undoZoom() | |||||
445 | plot().replot(QCustomPlot::rpQueuedReplot); |
|
452 | plot().replot(QCustomPlot::rpQueuedReplot); | |
446 | } |
|
453 | } | |
447 |
|
454 | |||
|
455 | void VisualizationGraphWidget::zoom(double factor, int center, Qt::Orientation orientation) | |||
|
456 | ||||
|
457 | { | |||
|
458 | auto oldRange = ui->widget->xAxis->range(); | |||
|
459 | QCPAxis *axis = ui->widget->axisRect()->rangeZoomAxis(orientation); | |||
|
460 | axis->scaleRange(factor, axis->pixelToCoord(center)); | |||
|
461 | if (orientation == Qt::Horizontal) | |||
|
462 | onRangeChanged(axis->range(), oldRange); | |||
|
463 | ui->widget->replot(QCustomPlot::rpQueuedReplot); | |||
|
464 | } | |||
|
465 | ||||
|
466 | void VisualizationGraphWidget::move(double factor, Qt::Orientation orientation) | |||
|
467 | { | |||
|
468 | auto oldRange = ui->widget->xAxis->range(); | |||
|
469 | QCPAxis *axis = ui->widget->axisRect()->rangeDragAxis(orientation); | |||
|
470 | if (ui->widget->xAxis->scaleType() == QCPAxis::stLinear) { | |||
|
471 | double rg = (axis->range().upper - axis->range().lower) * (factor / 10); | |||
|
472 | axis->setRange(axis->range().lower + (rg), axis->range().upper + (rg)); | |||
|
473 | } | |||
|
474 | else if (ui->widget->xAxis->scaleType() == QCPAxis::stLogarithmic) { | |||
|
475 | int start = 0, stop = 0; | |||
|
476 | double diff = 0.; | |||
|
477 | if (factor > 0.0) { | |||
|
478 | stop = this->width() * factor / 10; | |||
|
479 | start = 2 * this->width() * factor / 10; | |||
|
480 | } | |||
|
481 | if (factor < 0.0) { | |||
|
482 | factor *= -1.0; | |||
|
483 | start = this->width() * factor / 10; | |||
|
484 | stop = 2 * this->width() * factor / 10; | |||
|
485 | } | |||
|
486 | diff = axis->pixelToCoord(start) / axis->pixelToCoord(stop); | |||
|
487 | axis->setRange(ui->widget->axisRect()->rangeDragAxis(orientation)->range().lower * diff, | |||
|
488 | ui->widget->axisRect()->rangeDragAxis(orientation)->range().upper * diff); | |||
|
489 | } | |||
|
490 | if (orientation == Qt::Horizontal) | |||
|
491 | onRangeChanged(axis->range(), oldRange); | |||
|
492 | ui->widget->replot(QCustomPlot::rpQueuedReplot); | |||
|
493 | } | |||
|
494 | ||||
448 | void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor) |
|
495 | void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor) | |
449 | { |
|
496 | { | |
450 | if (visitor) { |
|
497 | if (visitor) { | |
@@ -636,6 +683,147 void VisualizationGraphWidget::leaveEvent(QEvent *event) | |||||
636 | } |
|
683 | } | |
637 | } |
|
684 | } | |
638 |
|
685 | |||
|
686 | void VisualizationGraphWidget::wheelEvent(QWheelEvent *event) | |||
|
687 | { | |||
|
688 | double factor; | |||
|
689 | double wheelSteps = event->delta() / 120.0; // a single step delta is +/-120 usually | |||
|
690 | if (event->modifiers() == Qt::ControlModifier) { | |||
|
691 | if (event->orientation() == Qt::Vertical) // mRangeZoom.testFlag(Qt::Vertical)) | |||
|
692 | { | |||
|
693 | setCursor(Qt::SizeVerCursor); | |||
|
694 | factor = pow(ui->widget->axisRect()->rangeZoomFactor(Qt::Vertical), wheelSteps); | |||
|
695 | zoom(factor, event->pos().y(), Qt::Vertical); | |||
|
696 | } | |||
|
697 | } | |||
|
698 | else if (event->modifiers() == Qt::ShiftModifier) { | |||
|
699 | if (event->orientation() == Qt::Vertical) // mRangeZoom.testFlag(Qt::Vertical)) | |||
|
700 | { | |||
|
701 | setCursor(Qt::SizeHorCursor); | |||
|
702 | factor = pow(ui->widget->axisRect()->rangeZoomFactor(Qt::Horizontal), wheelSteps); | |||
|
703 | zoom(factor, event->pos().x(), Qt::Horizontal); | |||
|
704 | } | |||
|
705 | } | |||
|
706 | else { | |||
|
707 | move(wheelSteps, Qt::Horizontal); | |||
|
708 | } | |||
|
709 | QWidget::wheelEvent(event); | |||
|
710 | } | |||
|
711 | ||||
|
712 | inline QCPRange _pixDistanceToRange(double pos1, double pos2, QCPAxis *axis) | |||
|
713 | { | |||
|
714 | if (axis->scaleType() == QCPAxis::stLinear) | |||
|
715 | { | |||
|
716 | auto diff = axis->pixelToCoord(pos1) - axis->pixelToCoord(pos2); | |||
|
717 | return QCPRange{axis->range().lower + diff, axis->range().upper + diff}; | |||
|
718 | } | |||
|
719 | else | |||
|
720 | { | |||
|
721 | auto diff = axis->pixelToCoord(pos1) / axis->pixelToCoord(pos2); | |||
|
722 | return QCPRange{axis->range().lower * diff, axis->range().upper * diff}; | |||
|
723 | } | |||
|
724 | } | |||
|
725 | ||||
|
726 | void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent *event) | |||
|
727 | { | |||
|
728 | if (event->buttons() & Qt::LeftButton) { | |||
|
729 | auto currentPos = event->pos(); | |||
|
730 | auto xAxis = ui->widget->axisRect()->rangeDragAxis(Qt::Horizontal); | |||
|
731 | auto yAxis = ui->widget->axisRect()->rangeDragAxis(Qt::Vertical); | |||
|
732 | auto oldXRange = xAxis->range(); | |||
|
733 | xAxis->setRange(_pixDistanceToRange(_dragLastPos.x(), currentPos.x(), xAxis)); | |||
|
734 | yAxis->setRange(_pixDistanceToRange(_dragLastPos.y(), currentPos.y(), yAxis)); | |||
|
735 | onRangeChanged(oldXRange, xAxis->range()); | |||
|
736 | ui->widget->replot(QCustomPlot::rpQueuedReplot); | |||
|
737 | _dragLastPos = currentPos; | |||
|
738 | } | |||
|
739 | QWidget::mouseMoveEvent(event); | |||
|
740 | } | |||
|
741 | ||||
|
742 | void VisualizationGraphWidget::mouseReleaseEvent(QMouseEvent *event) | |||
|
743 | { | |||
|
744 | setCursor(Qt::ArrowCursor); | |||
|
745 | QWidget::mouseReleaseEvent(event); | |||
|
746 | } | |||
|
747 | ||||
|
748 | void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event) | |||
|
749 | { | |||
|
750 | if (event->button() == Qt::LeftButton) { | |||
|
751 | if (event->modifiers() == Qt::ControlModifier) { | |||
|
752 | } | |||
|
753 | else { | |||
|
754 | setCursor(Qt::ClosedHandCursor); | |||
|
755 | this->_dragLastPos= event->pos(); | |||
|
756 | } | |||
|
757 | } | |||
|
758 | QWidget::mousePressEvent(event); | |||
|
759 | } | |||
|
760 | ||||
|
761 | void VisualizationGraphWidget::keyReleaseEvent(QKeyEvent *event) | |||
|
762 | { | |||
|
763 | switch (event->key()) { | |||
|
764 | case Qt::Key_Control: | |||
|
765 | event->accept(); | |||
|
766 | break; | |||
|
767 | case Qt::Key_Shift: | |||
|
768 | event->accept(); | |||
|
769 | break; | |||
|
770 | default: | |||
|
771 | QWidget::keyReleaseEvent(event); | |||
|
772 | break; | |||
|
773 | } | |||
|
774 | setCursor(Qt::ArrowCursor); | |||
|
775 | } | |||
|
776 | ||||
|
777 | void VisualizationGraphWidget::keyPressEvent(QKeyEvent *event) | |||
|
778 | { | |||
|
779 | switch (event->key()) { | |||
|
780 | case Qt::Key_Control: | |||
|
781 | setCursor(Qt::CrossCursor); | |||
|
782 | break; | |||
|
783 | case Qt::Key_Shift: | |||
|
784 | break; | |||
|
785 | case Qt::Key_M: | |||
|
786 | ui->widget->rescaleAxes(); | |||
|
787 | ui->widget->replot(QCustomPlot::rpQueuedReplot); | |||
|
788 | break; | |||
|
789 | case Qt::Key_Left: | |||
|
790 | if (event->modifiers() != Qt::ControlModifier) { | |||
|
791 | move(-0.1, Qt::Horizontal); | |||
|
792 | } | |||
|
793 | else { | |||
|
794 | zoom(2, this->width() / 2, Qt::Horizontal); | |||
|
795 | } | |||
|
796 | break; | |||
|
797 | case Qt::Key_Right: | |||
|
798 | if (event->modifiers() != Qt::ControlModifier) { | |||
|
799 | move(0.1, Qt::Horizontal); | |||
|
800 | } | |||
|
801 | else { | |||
|
802 | zoom(0.5, this->width() / 2, Qt::Horizontal); | |||
|
803 | } | |||
|
804 | break; | |||
|
805 | case Qt::Key_Up: | |||
|
806 | if (event->modifiers() != Qt::ControlModifier) { | |||
|
807 | move(0.1, Qt::Vertical); | |||
|
808 | } | |||
|
809 | else { | |||
|
810 | zoom(0.5, this->height() / 2, Qt::Vertical); | |||
|
811 | } | |||
|
812 | break; | |||
|
813 | case Qt::Key_Down: | |||
|
814 | if (event->modifiers() != Qt::ControlModifier) { | |||
|
815 | move(-0.1, Qt::Vertical); | |||
|
816 | } | |||
|
817 | else { | |||
|
818 | zoom(2, this->height() / 2, Qt::Vertical); | |||
|
819 | } | |||
|
820 | break; | |||
|
821 | default: | |||
|
822 | QWidget::keyPressEvent(event); | |||
|
823 | break; | |||
|
824 | } | |||
|
825 | } | |||
|
826 | ||||
639 | QCustomPlot &VisualizationGraphWidget::plot() const noexcept |
|
827 | QCustomPlot &VisualizationGraphWidget::plot() const noexcept | |
640 | { |
|
828 | { | |
641 | return *ui->widget; |
|
829 | return *ui->widget; | |
@@ -651,7 +839,7 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept | |||||
651 | it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) { |
|
839 | it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) { | |
652 | // 'Remove variable' action |
|
840 | // 'Remove variable' action | |
653 | graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()), |
|
841 | graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()), | |
654 |
[ |
|
842 | [this, var = it->first]() { removeVariable(var); }); | |
655 | } |
|
843 | } | |
656 |
|
844 | |||
657 | if (!impl->m_ZoomStack.isEmpty()) { |
|
845 | if (!impl->m_ZoomStack.isEmpty()) { | |
@@ -733,10 +921,10 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept | |||||
733 | } |
|
921 | } | |
734 | } |
|
922 | } | |
735 |
|
923 | |||
736 |
void VisualizationGraphWidget::onRangeChanged(const QCPRange & |
|
924 | void VisualizationGraphWidget::onRangeChanged(const QCPRange &newRange, const QCPRange &oldRange) | |
737 | { |
|
925 | { | |
738 |
auto graphRange = DateTimeRange{ |
|
926 | auto graphRange = DateTimeRange{newRange.lower, newRange.upper}; | |
739 |
auto oldGraphRange = DateTimeRange{ |
|
927 | auto oldGraphRange = DateTimeRange{oldRange.lower, oldRange.upper}; | |
740 |
|
928 | |||
741 | if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) { |
|
929 | if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) { | |
742 | for (auto it = impl->m_VariableToPlotMultiMap.begin(), |
|
930 | for (auto it = impl->m_VariableToPlotMultiMap.begin(), | |
@@ -746,24 +934,24 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange | |||||
746 | } |
|
934 | } | |
747 | } |
|
935 | } | |
748 |
|
936 | |||
749 | if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) |
|
937 | // if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) | |
750 | { |
|
938 | // { | |
751 | emit synchronize(graphRange, oldGraphRange); |
|
939 | // emit synchronize(graphRange, oldGraphRange); | |
752 | } |
|
940 | // } | |
753 |
|
941 | |||
754 | auto pos = mapFromGlobal(QCursor::pos()); |
|
942 | // auto pos = mapFromGlobal(QCursor::pos()); | |
755 | auto axisPos = impl->posToAxisPos(pos, plot()); |
|
943 | // auto axisPos = impl->posToAxisPos(pos, plot()); | |
756 | if (auto parentZone = parentZoneWidget()) { |
|
944 | // if (auto parentZone = parentZoneWidget()) { | |
757 | if (impl->pointIsInAxisRect(axisPos, plot())) { |
|
945 | // if (impl->pointIsInAxisRect(axisPos, plot())) { | |
758 | parentZone->notifyMouseMoveInGraph(pos, axisPos, this); |
|
946 | // parentZone->notifyMouseMoveInGraph(pos, axisPos, this); | |
759 | } |
|
947 | // } | |
760 | else { |
|
948 | // else { | |
761 | parentZone->notifyMouseLeaveGraph(this); |
|
949 | // parentZone->notifyMouseLeaveGraph(this); | |
762 | } |
|
950 | // } | |
763 | } |
|
951 | // } | |
764 |
|
952 | |||
765 | // Quits calibration |
|
953 | // Quits calibration | |
766 | impl->m_IsCalibration = false; |
|
954 | // impl->m_IsCalibration = false; | |
767 | } |
|
955 | } | |
768 |
|
956 | |||
769 | void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept |
|
957 | void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept | |
@@ -860,7 +1048,7 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept | |||||
860 | plot().setNotAntialiasedElements(QCP::aeAll); |
|
1048 | plot().setNotAntialiasedElements(QCP::aeAll); | |
861 | } |
|
1049 | } | |
862 |
|
1050 | |||
863 | //plot().replot(QCustomPlot::rpQueuedReplot); |
|
1051 | // plot().replot(QCustomPlot::rpQueuedReplot); | |
864 | } |
|
1052 | } | |
865 | } |
|
1053 | } | |
866 | } |
|
1054 | } | |
@@ -887,9 +1075,10 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept | |||||
887 | } |
|
1075 | } | |
888 |
|
1076 | |||
889 | // Allows mouse panning only in default mode |
|
1077 | // Allows mouse panning only in default mode | |
890 | plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode() |
|
1078 | // plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode() | |
891 |
== |
|
1079 | // == | |
892 |
|
|
1080 | // SqpApplication::PlotsInteractionMode::None | |
|
1081 | // && !isDragDropClick); | |||
893 |
|
1082 | |||
894 | // Allows zone edition only in selection zone mode without drag&drop |
|
1083 | // Allows zone edition only in selection zone mode without drag&drop | |
895 | impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick); |
|
1084 | impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick); | |
@@ -1035,11 +1224,9 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> v | |||||
1035 |
|
1224 | |||
1036 | void VisualizationGraphWidget::variableUpdated(QUuid id) |
|
1225 | void VisualizationGraphWidget::variableUpdated(QUuid id) | |
1037 | { |
|
1226 | { | |
1038 |
for(auto& |
|
1227 | for (auto &[var, plotables] : impl->m_VariableToPlotMultiMap) { | |
1039 | { |
|
1228 | if (var->ID() == id) { | |
1040 | if(var->ID()==id) |
|
1229 | impl->updateData(plotables, var, this->graphRange()); | |
1041 | { |
|
|||
1042 | impl->updateData(plotables,var,this->graphRange()); |
|
|||
1043 | } |
|
1230 | } | |
1044 | } |
|
1231 | } | |
1045 | } |
|
1232 | } |
@@ -20,7 +20,7 QPoint center(T* widget) | |||||
20 | HAS_METHOD(viewport) |
|
20 | HAS_METHOD(viewport) | |
21 |
|
21 | |||
22 | template <typename T> |
|
22 | template <typename T> | |
23 |
|
|
23 | static inline constexpr bool is_QWidgetOrDerived = std::is_base_of<QWidget,T>::value; | |
24 |
|
24 | |||
25 | template <typename T> using viewport_type = decltype(std::declval<T>().viewport()); |
|
25 | template <typename T> using viewport_type = decltype(std::declval<T>().viewport()); | |
26 |
|
26 | |||
@@ -31,9 +31,16 void mouseMove(T* widget, QPoint pos, Qt::MouseButton mouseModifier) | |||||
31 | { |
|
31 | { | |
32 | QCursor::setPos(widget->mapToGlobal(pos)); |
|
32 | QCursor::setPos(widget->mapToGlobal(pos)); | |
33 | QMouseEvent event(QEvent::MouseMove, pos, Qt::NoButton, mouseModifier, Qt::NoModifier); |
|
33 | QMouseEvent event(QEvent::MouseMove, pos, Qt::NoButton, mouseModifier, Qt::NoModifier); | |
34 | if constexpr(has_viewport<T> && is_QWidgetOrDerived<viewport_type<T>>::value ) |
|
34 | if constexpr(has_viewport<T>) | |
35 | { |
|
35 | { | |
36 | qApp->sendEvent(widget->viewport(), &event); |
|
36 | if constexpr(is_QWidgetOrDerived<viewport_type<T>>) | |
|
37 | { | |||
|
38 | qApp->sendEvent(widget->viewport(), &event); | |||
|
39 | } | |||
|
40 | else | |||
|
41 | { | |||
|
42 | qApp->sendEvent(widget, &event); | |||
|
43 | } | |||
37 | } |
|
44 | } | |
38 | else |
|
45 | else | |
39 | { |
|
46 | { | |
@@ -46,9 +53,16 void mouseMove(T* widget, QPoint pos, Qt::MouseButton mouseModifier) | |||||
46 | template <typename T> |
|
53 | template <typename T> | |
47 | void setMouseTracking(T* widget) |
|
54 | void setMouseTracking(T* widget) | |
48 | { |
|
55 | { | |
49 | if constexpr(has_viewport<T> && is_QWidgetOrDerived<viewport_type<T>>::value) |
|
56 | if constexpr(has_viewport<T>) | |
50 | { |
|
57 | { | |
51 | widget->viewport()->setMouseTracking(true); |
|
58 | if constexpr(is_QWidgetOrDerived<viewport_type<T>>) | |
|
59 | { | |||
|
60 | widget->viewport()->setMouseTracking(true); | |||
|
61 | } | |||
|
62 | else | |||
|
63 | { | |||
|
64 | widget->setMouseTracking(true); | |||
|
65 | } | |||
52 | } |
|
66 | } | |
53 | else |
|
67 | else | |
54 | { |
|
68 | { |
@@ -30,7 +30,7 ALIAS_TEMPLATE_FUNCTION(isReady, static_cast<SqpApplication *>(qApp)->variableCo | |||||
30 | QCoreApplication::processEvents();\ |
|
30 | QCoreApplication::processEvents();\ | |
31 | w.addVariable(var, range);\ |
|
31 | w.addVariable(var, range);\ | |
32 | GET_CHILD_WIDGET_FOR_GUI_TESTS(w, plot, QCustomPlot, "widget");\ |
|
32 | GET_CHILD_WIDGET_FOR_GUI_TESTS(w, plot, QCustomPlot, "widget");\ | |
33 |
auto cent = center( |
|
33 | auto cent = center(&w);\ | |
34 |
|
34 | |||
35 |
|
35 | |||
36 | class A_SimpleGraph : public QObject { |
|
36 | class A_SimpleGraph : public QObject { | |
@@ -44,23 +44,20 private slots: | |||||
44 | A_SIMPLE_GRAPH_FIXTURE |
|
44 | A_SIMPLE_GRAPH_FIXTURE | |
45 |
|
45 | |||
46 | for (auto i = 0; i < 10; i++) { |
|
46 | for (auto i = 0; i < 10; i++) { | |
47 |
QTest::mousePress( |
|
47 | QTest::mousePress(&w, Qt::LeftButton, Qt::NoModifier, cent, 500); | |
48 |
mouseMove( |
|
48 | mouseMove(&w, {cent.x() + 200, cent.y()}, Qt::LeftButton); | |
49 |
QTest::mouseRelease( |
|
49 | QTest::mouseRelease(&w, Qt::LeftButton); | |
50 | while (!isReady(var)) |
|
50 | while (!isReady(var)) | |
51 | QCoreApplication::processEvents(); |
|
51 | QCoreApplication::processEvents(); | |
52 | /* |
|
|||
53 | * Just for visual inspection while running tests |
|
|||
54 | */ |
|
|||
55 | plot->rescaleAxes(); |
|
|||
56 | plot->replot(); |
|
|||
57 | QCoreApplication::processEvents(); |
|
|||
58 | } |
|
52 | } | |
59 | while (!isReady(var)) |
|
53 | while (!isReady(var)) | |
60 | QCoreApplication::processEvents(); |
|
54 | QCoreApplication::processEvents(); | |
61 | auto r = var->range(); |
|
55 | auto r = var->range(); | |
|
56 | /* | |||
|
57 | * Scrolling to the left implies going back in time | |||
|
58 | * Scroll only implies keeping the same delta T -> shit only transformation | |||
|
59 | */ | |||
62 | QVERIFY(r.m_TEnd < range.m_TEnd); |
|
60 | QVERIFY(r.m_TEnd < range.m_TEnd); | |
63 | // this fails :( |
|
|||
64 | QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(),range.delta(),1)); |
|
61 | QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(),range.delta(),1)); | |
65 | } |
|
62 | } | |
66 | }; |
|
63 | }; |
General Comments 0
You need to be logged in to leave comments.
Login now