diff --git a/gui/include/Visualization/VisualizationSelectionZoneItem.h b/gui/include/Visualization/VisualizationSelectionZoneItem.h index 9e1c3d2..2bc3c93 100644 --- a/gui/include/Visualization/VisualizationSelectionZoneItem.h +++ b/gui/include/Visualization/VisualizationSelectionZoneItem.h @@ -27,11 +27,18 @@ public: Qt::CursorShape curshorShapeForPosition(const QPoint &position) const; void setHovered(bool value); + void setAssociatedEditedZones(const QVector &associatedZones); + protected: void mousePressEvent(QMouseEvent *event, const QVariant &details) override; void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override; void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override; + void resizeLeft(double pixelDiff); + void resizeRight(double pixelDiff); + void move(double pixelDiff); + + private: class VisualizationSelectionZoneItemPrivate; spimpl::unique_impl_ptr impl; diff --git a/gui/src/Visualization/VisualizationGraphWidget.cpp b/gui/src/Visualization/VisualizationGraphWidget.cpp index 7e4a8de..9586821 100644 --- a/gui/src/Visualization/VisualizationGraphWidget.cpp +++ b/gui/src/Visualization/VisualizationGraphWidget.cpp @@ -90,6 +90,8 @@ struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { VisualizationSelectionZoneItem *m_HoveredZone = nullptr; QVector m_SelectionZones; + bool m_HasMovedMouse = false; //Indicates if the mouse moved in a releaseMouse even + void startDrawingRect(const QPoint &pos, QCustomPlot &plot) { removeDrawingRect(plot); @@ -710,6 +712,7 @@ void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept setCursor(Qt::ArrowCursor); } + impl->m_HasMovedMouse = true; VisualizationDragWidget::mouseMoveEvent(event); } @@ -775,20 +778,13 @@ void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept // Allows zone edition only in selection zone mode without drag&drop impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick); - // Selection + // Selection / Deselection if (isSelectionZoneMode) { auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER); auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot()); if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) { - if (!isMultiSelectionClick) { - parentVisualizationWidget()->selectionZoneManager().select( - {selectionZoneItemUnderCursor}); - } - else { - parentVisualizationWidget()->selectionZoneManager().setSelected( - selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected() - || event->button() == Qt::RightButton); - } + selectionZoneItemUnderCursor->setAssociatedEditedZones( + parentVisualizationWidget()->selectionZoneManager().selectedItems()); } else if (!isMultiSelectionClick && event->button() == Qt::LeftButton) { parentVisualizationWidget()->selectionZoneManager().clearSelection(); @@ -798,6 +794,8 @@ void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept } } + + impl->m_HasMovedMouse = false; VisualizationDragWidget::mousePressEvent(event); } @@ -829,6 +827,28 @@ void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept impl->endDrawingZone(this); impl->m_IsCalibration = false; + + // Selection / Deselection + auto isSelectionZoneMode + = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones; + if (isSelectionZoneMode) { + auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER); + auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot()); + if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) { + if (!isMultiSelectionClick && !impl->m_HasMovedMouse) { + parentVisualizationWidget()->selectionZoneManager().select( + {selectionZoneItemUnderCursor}); + } + else if (!impl->m_HasMovedMouse) { + parentVisualizationWidget()->selectionZoneManager().setSelected( + selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected() + || event->button() == Qt::RightButton); + } + } + else { + // No selection change + } + } } void VisualizationGraphWidget::onDataCacheVariableUpdated() diff --git a/gui/src/Visualization/VisualizationSelectionZoneItem.cpp b/gui/src/Visualization/VisualizationSelectionZoneItem.cpp index 08b5829..443823c 100644 --- a/gui/src/Visualization/VisualizationSelectionZoneItem.cpp +++ b/gui/src/Visualization/VisualizationSelectionZoneItem.cpp @@ -20,6 +20,8 @@ struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate { enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move }; EditionMode m_CurrentEditionMode; + QVector m_AssociatedEditedZones; + VisualizationSelectionZoneItemPrivate(QCustomPlot *plot) : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition) { @@ -46,6 +48,12 @@ struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate { return VisualizationSelectionZoneItemPrivate::EditionMode::Move; } + + double pixelSizeToAxisXSize(double pixels) + { + auto axis = m_Plot->axisRect()->axis(QCPAxis::atBottom); + return axis->pixelToCoord(pixels) - axis->pixelToCoord(0); + } }; VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot) @@ -220,6 +228,13 @@ void VisualizationSelectionZoneItem::setHovered(bool value) } } +void VisualizationSelectionZoneItem::setAssociatedEditedZones( + const QVector &associatedZones) +{ + impl->m_AssociatedEditedZones = associatedZones; + impl->m_AssociatedEditedZones.removeAll(this); +} + void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details) { if (isEditionEnabled() && event->button() == Qt::LeftButton) { @@ -227,6 +242,10 @@ void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const Q impl->m_MovedOrinalT1 = impl->m_T1; impl->m_MovedOrinalT2 = impl->m_T2; + for (auto associatedZone : impl->m_AssociatedEditedZones) { + associatedZone->impl->m_MovedOrinalT1 = associatedZone->impl->m_T1; + associatedZone->impl->m_MovedOrinalT2 = associatedZone->impl->m_T2; + } } else { impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition; @@ -238,21 +257,39 @@ void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QP { if (isEditionEnabled()) { auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom); - auto diff = axis->pixelToCoord(event->pos().x()) - axis->pixelToCoord(startPos.x()); + auto pixelDiff = event->pos().x() - startPos.x(); + auto diff = impl->pixelSizeToAxisXSize(pixelDiff); switch (impl->m_CurrentEditionMode) { case VisualizationSelectionZoneItemPrivate::EditionMode::Move: setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff); + for (auto associatedZone : impl->m_AssociatedEditedZones) { + associatedZone->move(pixelDiff); + } break; case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft: setStart(impl->m_MovedOrinalT1 + diff); + for (auto associatedZone : impl->m_AssociatedEditedZones) { + impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2 + ? associatedZone->resizeLeft(pixelDiff) + : associatedZone->resizeRight(pixelDiff); + } break; case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: setEnd(impl->m_MovedOrinalT2 + diff); + for (auto associatedZone : impl->m_AssociatedEditedZones) { + impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2 + ? associatedZone->resizeRight(pixelDiff) + : associatedZone->resizeLeft(pixelDiff); + } break; default: break; } + + for (auto associatedZone : impl->m_AssociatedEditedZones) { + associatedZone->parentPlot()->replot(); + } } else { event->ignore(); @@ -267,4 +304,34 @@ void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const else { event->ignore(); } + + impl->m_AssociatedEditedZones.clear(); +} + +void VisualizationSelectionZoneItem::resizeLeft(double pixelDiff) +{ + auto diff = impl->pixelSizeToAxisXSize(pixelDiff); + if (impl->m_MovedOrinalT1 <= impl->m_MovedOrinalT2) { + setStart(impl->m_MovedOrinalT1 + diff); + } + else { + setEnd(impl->m_MovedOrinalT2 + diff); + } +} + +void VisualizationSelectionZoneItem::resizeRight(double pixelDiff) +{ + auto diff = impl->pixelSizeToAxisXSize(pixelDiff); + if (impl->m_MovedOrinalT1 > impl->m_MovedOrinalT2) { + setStart(impl->m_MovedOrinalT1 + diff); + } + else { + setEnd(impl->m_MovedOrinalT2 + diff); + } +} + +void VisualizationSelectionZoneItem::move(double pixelDiff) +{ + auto diff = impl->pixelSizeToAxisXSize(pixelDiff); + setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff); }