From 8384b41be65391542c5a2073c25af5b45be338d0 Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Mon, 29 Jul 2024 10:25:20 +0700 Subject: [PATCH] Address review and add test --- .../qgsadvanceddigitizingdockwidget.sip.in | 12 +--- .../qgsadvanceddigitizingtools.sip.in | 38 ++++++++--- .../qgsadvanceddigitizingtoolsregistry.sip.in | 3 + .../qgsadvanceddigitizingdockwidget.sip.in | 12 +--- .../qgsadvanceddigitizingtools.sip.in | 38 ++++++++--- .../qgsadvanceddigitizingtoolsregistry.sip.in | 3 + src/gui/qgsadvanceddigitizingcanvasitem.cpp | 7 +- src/gui/qgsadvanceddigitizingdockwidget.cpp | 54 +++++++++------ src/gui/qgsadvanceddigitizingdockwidget.h | 9 +-- src/gui/qgsadvanceddigitizingtools.cpp | 67 ++++++++++++------- src/gui/qgsadvanceddigitizingtools.h | 35 +++++----- .../qgsadvanceddigitizingtoolsregistry.cpp | 2 + src/gui/qgsadvanceddigitizingtoolsregistry.h | 3 + src/gui/qgsmaptooladvanceddigitizing.cpp | 15 +++-- tests/src/gui/CMakeLists.txt | 1 + 15 files changed, 184 insertions(+), 115 deletions(-) diff --git a/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in b/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in index d465295e75f9..fccd3de72a2d 100644 --- a/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in +++ b/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in @@ -236,25 +236,19 @@ align to segment for between line constraint. If between line constraints are used, this will determine the angle to be locked depending on the snapped segment. %End - bool processCanvasPressEvent( QgsMapMouseEvent *event ); + void processCanvasPressEvent( QgsMapMouseEvent *event ); %Docstring Processes the canvas press ``event``. - -:return: Returns ``True`` if the event has been 'eaten' and should not propagate further. %End - bool processCanvasMoveEvent( QgsMapMouseEvent *event ); + void processCanvasMoveEvent( QgsMapMouseEvent *event ); %Docstring Processes the canvas move ``event``. - -:return: Returns ``True`` if the event has been 'eaten' and should not propagate further. %End - bool processCanvasReleaseEvent( QgsMapMouseEvent *event ); + void processCanvasReleaseEvent( QgsMapMouseEvent *event ); %Docstring Processes the canvas release ``event``. - -:return: Returns ``True`` if the event has been 'eaten' and should not propagate further. %End void setTool( QgsAdvancedDigitizingTool *tool ); diff --git a/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtools.sip.in b/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtools.sip.in index c3511108cb71..b587dae0133b 100644 --- a/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtools.sip.in +++ b/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtools.sip.in @@ -11,7 +11,7 @@ -class QgsAdvancedDigitizingTool : QWidget +class QgsAdvancedDigitizingTool : QObject { %Docstring(signature="appended") An abstract class for advanced digitizing tools. @@ -42,27 +42,45 @@ Returns the map canvas associated with the tool. Returns the advanced digitizing widget associated with the tool. %End + virtual QWidget *createWidget(); +%Docstring +Returns a widget to control the tool. + +.. note:: + + The caller gets the ownership. +%End + virtual void paint( QPainter *painter ); %Docstring Paints tool content onto the advanced digitizing canvas item. %End - virtual bool canvasPressEvent( QgsMapMouseEvent *event ); + virtual void canvasPressEvent( QgsMapMouseEvent *event ); %Docstring -Handles canvas press event. If ``True`` is returned, the tool will have -blocked the event for propagating. +Handles canvas press event. + +.. note:: + + To stop propagation, set the event's accepted property to ``False``. %End - virtual bool canvasMoveEvent( QgsMapMouseEvent *event ); + virtual void canvasMoveEvent( QgsMapMouseEvent *event ); %Docstring -Handles canvas press move. If ``True`` is returned, the tool will have -blocked the event for propagating. +Handles canvas press move. + +.. note:: + + To stop propagation, set the event's accepted property to ``False``. %End - virtual bool canvasReleaseEvent( QgsMapMouseEvent *event ); + virtual void canvasReleaseEvent( QgsMapMouseEvent *event ); %Docstring -Handles canvas release event. If ``True`` is returned, the tool will have -blocked the event for propagating. +Handles canvas release event. + +.. note:: + + To stop propagation, set the event's accepted property to ``False``. %End signals: diff --git a/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in b/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in index fb48ea403aaa..3f9d6284c8e4 100644 --- a/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in +++ b/python/PyQt6/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in @@ -63,6 +63,9 @@ class QgsAdvancedDigitizingToolsRegistry %Docstring(signature="appended") Registry of available advanced digitizing tools. +:py:class:`QgsAdvancedDigitizingToolsRegistry` is not usually directly created, but rather accessed through +:py:func:`QgsGui.advancedDigitizingToolsRegistry()`. + .. versionadded:: 3.40 %End diff --git a/python/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in b/python/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in index fc9a4d70c705..962a3a03f8a1 100644 --- a/python/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in +++ b/python/gui/auto_generated/qgsadvanceddigitizingdockwidget.sip.in @@ -236,25 +236,19 @@ align to segment for between line constraint. If between line constraints are used, this will determine the angle to be locked depending on the snapped segment. %End - bool processCanvasPressEvent( QgsMapMouseEvent *event ); + void processCanvasPressEvent( QgsMapMouseEvent *event ); %Docstring Processes the canvas press ``event``. - -:return: Returns ``True`` if the event has been 'eaten' and should not propagate further. %End - bool processCanvasMoveEvent( QgsMapMouseEvent *event ); + void processCanvasMoveEvent( QgsMapMouseEvent *event ); %Docstring Processes the canvas move ``event``. - -:return: Returns ``True`` if the event has been 'eaten' and should not propagate further. %End - bool processCanvasReleaseEvent( QgsMapMouseEvent *event ); + void processCanvasReleaseEvent( QgsMapMouseEvent *event ); %Docstring Processes the canvas release ``event``. - -:return: Returns ``True`` if the event has been 'eaten' and should not propagate further. %End void setTool( QgsAdvancedDigitizingTool *tool ); diff --git a/python/gui/auto_generated/qgsadvanceddigitizingtools.sip.in b/python/gui/auto_generated/qgsadvanceddigitizingtools.sip.in index c3511108cb71..b587dae0133b 100644 --- a/python/gui/auto_generated/qgsadvanceddigitizingtools.sip.in +++ b/python/gui/auto_generated/qgsadvanceddigitizingtools.sip.in @@ -11,7 +11,7 @@ -class QgsAdvancedDigitizingTool : QWidget +class QgsAdvancedDigitizingTool : QObject { %Docstring(signature="appended") An abstract class for advanced digitizing tools. @@ -42,27 +42,45 @@ Returns the map canvas associated with the tool. Returns the advanced digitizing widget associated with the tool. %End + virtual QWidget *createWidget(); +%Docstring +Returns a widget to control the tool. + +.. note:: + + The caller gets the ownership. +%End + virtual void paint( QPainter *painter ); %Docstring Paints tool content onto the advanced digitizing canvas item. %End - virtual bool canvasPressEvent( QgsMapMouseEvent *event ); + virtual void canvasPressEvent( QgsMapMouseEvent *event ); %Docstring -Handles canvas press event. If ``True`` is returned, the tool will have -blocked the event for propagating. +Handles canvas press event. + +.. note:: + + To stop propagation, set the event's accepted property to ``False``. %End - virtual bool canvasMoveEvent( QgsMapMouseEvent *event ); + virtual void canvasMoveEvent( QgsMapMouseEvent *event ); %Docstring -Handles canvas press move. If ``True`` is returned, the tool will have -blocked the event for propagating. +Handles canvas press move. + +.. note:: + + To stop propagation, set the event's accepted property to ``False``. %End - virtual bool canvasReleaseEvent( QgsMapMouseEvent *event ); + virtual void canvasReleaseEvent( QgsMapMouseEvent *event ); %Docstring -Handles canvas release event. If ``True`` is returned, the tool will have -blocked the event for propagating. +Handles canvas release event. + +.. note:: + + To stop propagation, set the event's accepted property to ``False``. %End signals: diff --git a/python/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in b/python/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in index fb48ea403aaa..3f9d6284c8e4 100644 --- a/python/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in +++ b/python/gui/auto_generated/qgsadvanceddigitizingtoolsregistry.sip.in @@ -63,6 +63,9 @@ class QgsAdvancedDigitizingToolsRegistry %Docstring(signature="appended") Registry of available advanced digitizing tools. +:py:class:`QgsAdvancedDigitizingToolsRegistry` is not usually directly created, but rather accessed through +:py:func:`QgsGui.advancedDigitizingToolsRegistry()`. + .. versionadded:: 3.40 %End diff --git a/src/gui/qgsadvanceddigitizingcanvasitem.cpp b/src/gui/qgsadvanceddigitizingcanvasitem.cpp index 571601be1613..fe67e6c7ab47 100644 --- a/src/gui/qgsadvanceddigitizingcanvasitem.cpp +++ b/src/gui/qgsadvanceddigitizingcanvasitem.cpp @@ -59,10 +59,11 @@ void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter ) } } - // Draw current intersection tool - if ( mAdvancedDigitizingDockWidget->tool() ) + // Draw current tool + if ( QgsAdvancedDigitizingTool *tool = mAdvancedDigitizingDockWidget->tool() ) { - mAdvancedDigitizingDockWidget->tool()->paint( painter ); + // if a tool is active in the dock, then delegate to that tool to handle decorating the canvas instead of using the default decorations + tool->paint( painter ); return; } diff --git a/src/gui/qgsadvanceddigitizingdockwidget.cpp b/src/gui/qgsadvanceddigitizingdockwidget.cpp index 52cebd0450e1..383c0e2d31f7 100644 --- a/src/gui/qgsadvanceddigitizingdockwidget.cpp +++ b/src/gui/qgsadvanceddigitizingdockwidget.cpp @@ -242,17 +242,20 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas * // Tools QMenu *toolsMenu = new QMenu( this ); - const QStringList toolMetadataNames = QgsGui::instance()->advancedDigitizingToolsRegistry()->toolMetadataNames(); - for ( const QString &name : toolMetadataNames ) + connect( toolsMenu, &QMenu::aboutToShow, this, [ = ]() { - QgsAdvancedDigitizingToolAbstractMetadata *toolMetadata = QgsGui::instance()->advancedDigitizingToolsRegistry()->toolMetadata( name ); - QAction *toolAction = new QAction( toolMetadata->icon(), toolMetadata->visibleName(), this ); - connect( toolAction, &QAction::triggered, this, [ = ]() + const QStringList toolMetadataNames = QgsGui::instance()->advancedDigitizingToolsRegistry()->toolMetadataNames(); + for ( const QString &name : toolMetadataNames ) { - setTool( toolMetadata->createTool( mMapCanvas, this ) ); - } ); - toolsMenu->addAction( toolAction ); - } + QgsAdvancedDigitizingToolAbstractMetadata *toolMetadata = QgsGui::instance()->advancedDigitizingToolsRegistry()->toolMetadata( name ); + QAction *toolAction = new QAction( toolMetadata->icon(), toolMetadata->visibleName(), this ); + connect( toolAction, &QAction::triggered, this, [ = ]() + { + setTool( toolMetadata->createTool( mMapCanvas, this ) ); + } ); + toolsMenu->addAction( toolAction ); + } + } ); qobject_cast< QToolButton *>( mToolbar->widgetForAction( mToolsAction ) )->setPopupMode( QToolButton::InstantPopup ); mToolsAction->setMenu( toolsMenu ); @@ -684,12 +687,15 @@ void QgsAdvancedDigitizingDockWidget::setTool( QgsAdvancedDigitizingTool *tool ) mCurrentTool = nullptr; } - qDebug() << mCurrentTool; mCurrentTool = tool; if ( mCurrentTool ) { - mUserInputWidget->addUserInputWidget( mCurrentTool.data() ); + if ( QWidget *toolWidget = mCurrentTool->createWidget() ) + { + toolWidget->setParent( mUserInputWidget ); + mUserInputWidget->addUserInputWidget( toolWidget ); + } connect( mCurrentTool.data(), &QgsAdvancedDigitizingTool::paintRequested, this, &QgsAdvancedDigitizingDockWidget::updateCadPaintItem ); } } @@ -1547,17 +1553,20 @@ QList QgsAdvancedDigitizingDockWidget::snapSegmentToAllLayers( const return segment; } -bool QgsAdvancedDigitizingDockWidget::processCanvasPressEvent( QgsMapMouseEvent *event ) +void QgsAdvancedDigitizingDockWidget::processCanvasPressEvent( QgsMapMouseEvent *event ) { if ( mCurrentTool ) { mCurrentTool->canvasPressEvent( event ); } - return constructionMode(); + if ( constructionMode() ) + { + event->setAccepted( false ); + } } -bool QgsAdvancedDigitizingDockWidget::processCanvasMoveEvent( QgsMapMouseEvent *event ) +void QgsAdvancedDigitizingDockWidget::processCanvasMoveEvent( QgsMapMouseEvent *event ) { // perpendicular/parallel constraint // do a soft lock when snapping to a segment @@ -1569,22 +1578,22 @@ bool QgsAdvancedDigitizingDockWidget::processCanvasMoveEvent( QgsMapMouseEvent * } updateCadPaintItem(); - - return false; } -bool QgsAdvancedDigitizingDockWidget::processCanvasReleaseEvent( QgsMapMouseEvent *event ) +void QgsAdvancedDigitizingDockWidget::processCanvasReleaseEvent( QgsMapMouseEvent *event ) { if ( alignToSegment( event ) ) { - return true; + event->setAccepted( false ); + return; } if ( mCurrentTool ) { - if ( mCurrentTool->canvasReleaseEvent( event ) ) + mCurrentTool->canvasReleaseEvent( event ); + if ( !event->isAccepted() ) { - return true; + return; } else { @@ -1608,7 +1617,10 @@ bool QgsAdvancedDigitizingDockWidget::processCanvasReleaseEvent( QgsMapMouseEven addPoint( event->mapPoint() ); releaseLocks( false ); - return constructionMode(); + if ( constructionMode() ) + { + event->setAccepted( false ); + } } bool QgsAdvancedDigitizingDockWidget::alignToSegment( QgsMapMouseEvent *e, CadConstraint::LockMode lockMode ) diff --git a/src/gui/qgsadvanceddigitizingdockwidget.h b/src/gui/qgsadvanceddigitizingdockwidget.h index 44d327fc4c8b..73871a705a8b 100644 --- a/src/gui/qgsadvanceddigitizingdockwidget.h +++ b/src/gui/qgsadvanceddigitizingdockwidget.h @@ -278,21 +278,18 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private /** * Processes the canvas press \a event. - * \returns Returns TRUE if the event has been 'eaten' and should not propagate further. */ - bool processCanvasPressEvent( QgsMapMouseEvent *event ); + void processCanvasPressEvent( QgsMapMouseEvent *event ); /** * Processes the canvas move \a event. - * \returns Returns TRUE if the event has been 'eaten' and should not propagate further. */ - bool processCanvasMoveEvent( QgsMapMouseEvent *event ); + void processCanvasMoveEvent( QgsMapMouseEvent *event ); /** * Processes the canvas release \a event. - * \returns Returns TRUE if the event has been 'eaten' and should not propagate further. */ - bool processCanvasReleaseEvent( QgsMapMouseEvent *event ); + void processCanvasReleaseEvent( QgsMapMouseEvent *event ); /** * Sets an advanced digitizing tool which will take over digitizing until the tool is close. diff --git a/src/gui/qgsadvanceddigitizingtools.cpp b/src/gui/qgsadvanceddigitizingtools.cpp index 23abb12ab125..b85e4d16cce6 100644 --- a/src/gui/qgsadvanceddigitizingtools.cpp +++ b/src/gui/qgsadvanceddigitizingtools.cpp @@ -23,7 +23,7 @@ #include "qgsmapcanvas.h" QgsAdvancedDigitizingTool::QgsAdvancedDigitizingTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ) - : QWidget( canvas->viewport() ) + : QObject( canvas ? canvas->viewport() : nullptr ) , mMapCanvas( canvas ) , mCadDockWidget( cadDockWidget ) { @@ -32,72 +32,78 @@ QgsAdvancedDigitizingTool::QgsAdvancedDigitizingTool( QgsMapCanvas *canvas, QgsA QgsAdvancedDigitizingCirclesIntersectionTool::QgsAdvancedDigitizingCirclesIntersectionTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ) : QgsAdvancedDigitizingTool( canvas, cadDockWidget ) { - QGridLayout *layout = new QGridLayout( this ); +} + +QWidget *QgsAdvancedDigitizingCirclesIntersectionTool::createWidget() +{ + QWidget *toolWidget = new QWidget(); + + QGridLayout *layout = new QGridLayout( toolWidget ); layout->setContentsMargins( 0, 0, 0, 0 ); - setLayout( layout ); + toolWidget->setLayout( layout ); - QLabel *label = new QLabel( QStringLiteral( "Circle #1" ), this ); + QLabel *label = new QLabel( QStringLiteral( "Circle #1" ), toolWidget ); layout->addWidget( label, 0, 0, 1, 3 ); - mCircle1Digitize = new QToolButton( this ); + mCircle1Digitize = new QToolButton( toolWidget ); mCircle1Digitize->setCheckable( true ); mCircle1Digitize->setChecked( false ); mCircle1Digitize->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapIdentification.svg" ) ) ); layout->addWidget( mCircle1Digitize, 1, 2, 2, 1 ); - label = new QLabel( QStringLiteral( "X" ), this ); + label = new QLabel( QStringLiteral( "X" ), toolWidget ); layout->addWidget( label, 1, 0 ); - mCircle1X = new QgsDoubleSpinBox( this ); + mCircle1X = new QgsDoubleSpinBox( toolWidget ); mCircle1X->setMinimum( std::numeric_limits::min() ); mCircle1X->setMaximum( std::numeric_limits::max() ); layout->addWidget( mCircle1X, 1, 1 ); - label = new QLabel( QStringLiteral( "Y" ), this ); + label = new QLabel( QStringLiteral( "Y" ), toolWidget ); layout->addWidget( label, 2, 0 ); - mCircle1Y = new QgsDoubleSpinBox( this ); + mCircle1Y = new QgsDoubleSpinBox( toolWidget ); mCircle1Y->setMinimum( std::numeric_limits::min() ); mCircle1Y->setMaximum( std::numeric_limits::max() ); layout->addWidget( mCircle1Y, 2, 1 ); - label = new QLabel( QStringLiteral( "Distance" ), this ); + label = new QLabel( QStringLiteral( "Distance" ), toolWidget ); layout->addWidget( label, 3, 0 ); - mCircle1Distance = new QgsDoubleSpinBox( this ); + mCircle1Distance = new QgsDoubleSpinBox( toolWidget ); mCircle1Distance->setMinimum( 0 ); mCircle1Distance->setMaximum( std::numeric_limits::max() ); layout->addWidget( mCircle1Distance, 3, 1 ); - label = new QLabel( QStringLiteral( "Circle #2" ), this ); + label = new QLabel( QStringLiteral( "Circle #2" ), toolWidget ); layout->addWidget( label, 4, 0, 1, 3 ); - mCircle2Digitize = new QToolButton( this ); + mCircle2Digitize = new QToolButton( toolWidget ); mCircle2Digitize->setCheckable( true ); mCircle2Digitize->setChecked( false ); mCircle2Digitize->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapIdentification.svg" ) ) ); layout->addWidget( mCircle2Digitize, 5, 2, 2, 1 ); - label = new QLabel( QStringLiteral( "X" ), this ); + label = new QLabel( QStringLiteral( "X" ), toolWidget ); layout->addWidget( label, 5, 0 ); - mCircle2X = new QgsDoubleSpinBox( this ); + mCircle2X = new QgsDoubleSpinBox( toolWidget ); mCircle2X->setMinimum( std::numeric_limits::min() ); mCircle2X->setMaximum( std::numeric_limits::max() ); layout->addWidget( mCircle2X, 5, 1 ); - label = new QLabel( QStringLiteral( "Y" ), this ); + label = new QLabel( QStringLiteral( "Y" ), toolWidget ); layout->addWidget( label, 6, 0 ); - mCircle2Y = new QgsDoubleSpinBox( this ); + mCircle2Y = new QgsDoubleSpinBox( toolWidget ); mCircle2Y->setMinimum( std::numeric_limits::min() ); mCircle2Y->setMaximum( std::numeric_limits::max() ); layout->addWidget( mCircle2Y, 6, 1 ); - label = new QLabel( QStringLiteral( "Distance" ), this ); + label = new QLabel( QStringLiteral( "Distance" ), toolWidget ); layout->addWidget( label, 7, 0 ); - mCircle2Distance = new QgsDoubleSpinBox( this ); + mCircle2Distance = new QgsDoubleSpinBox( toolWidget ); mCircle2Distance->setMinimum( 0 ); mCircle2Distance->setMaximum( std::numeric_limits::max() ); layout->addWidget( mCircle2Distance, 7, 1 ); @@ -108,6 +114,9 @@ QgsAdvancedDigitizingCirclesIntersectionTool::QgsAdvancedDigitizingCirclesInters connect( mCircle2X, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double ) { processParameters(); } ); connect( mCircle2Y, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double ) { processParameters(); } ); connect( mCircle2Distance, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double ) { processParameters(); } ); + + mToolWidget = toolWidget; + return toolWidget; } void QgsAdvancedDigitizingCirclesIntersectionTool::processParameters() @@ -120,7 +129,7 @@ void QgsAdvancedDigitizingCirclesIntersectionTool::processParameters() emit paintRequested(); } -bool QgsAdvancedDigitizingCirclesIntersectionTool::canvasMoveEvent( QgsMapMouseEvent *event ) +void QgsAdvancedDigitizingCirclesIntersectionTool::canvasMoveEvent( QgsMapMouseEvent *event ) { if ( mCircle1Digitize->isChecked() ) { @@ -138,35 +147,41 @@ bool QgsAdvancedDigitizingCirclesIntersectionTool::canvasMoveEvent( QgsMapMouseE mP1Closest = QgsGeometryUtils::distance2D( QgsPoint( mP1 ), QgsPoint( event->mapPoint() ) ) < QgsGeometryUtils::distance2D( QgsPoint( mP2 ), QgsPoint( event->mapPoint() ) ); } - return true; + event->setAccepted( false ); } -bool QgsAdvancedDigitizingCirclesIntersectionTool::canvasReleaseEvent( QgsMapMouseEvent *event ) +void QgsAdvancedDigitizingCirclesIntersectionTool::canvasReleaseEvent( QgsMapMouseEvent *event ) { if ( mCircle1Digitize->isChecked() ) { mCircle1X->setValue( event->mapPoint().x() ); mCircle1Y->setValue( event->mapPoint().y() ); mCircle1Digitize->setChecked( false ); - return true; + event->setAccepted( false ); + return; } else if ( mCircle2Digitize->isChecked() ) { mCircle2X->setValue( event->mapPoint().x() ); mCircle2Y->setValue( event->mapPoint().y() ); mCircle2Digitize->setChecked( false ); - return true; + event->setAccepted( false ); + return; } if ( !mP1.isEmpty() ) { mP1Closest = QgsGeometryUtils::distance2D( QgsPoint( mP1 ), QgsPoint( event->mapPoint() ) ) < QgsGeometryUtils::distance2D( QgsPoint( mP2 ), QgsPoint( event->mapPoint() ) ); event->setMapPoint( mP1Closest ? mP1 : mP2 ); + if ( mToolWidget ) + { + mToolWidget->deleteLater(); + } deleteLater(); - return false; + return; } - return true; + event->setAccepted( false ); } void QgsAdvancedDigitizingCirclesIntersectionTool::drawCircle( QPainter *painter, double x, double y, double distance ) diff --git a/src/gui/qgsadvanceddigitizingtools.h b/src/gui/qgsadvanceddigitizingtools.h index dd4275a91941..a8669f7a5f80 100644 --- a/src/gui/qgsadvanceddigitizingtools.h +++ b/src/gui/qgsadvanceddigitizingtools.h @@ -35,7 +35,7 @@ class QgsMapCanvas; * \brief An abstract class for advanced digitizing tools. * \since QGIS 3.40 */ -class GUI_EXPORT QgsAdvancedDigitizingTool : public QWidget +class GUI_EXPORT QgsAdvancedDigitizingTool : public QObject { Q_OBJECT @@ -58,39 +58,42 @@ class GUI_EXPORT QgsAdvancedDigitizingTool : public QWidget */ QgsAdvancedDigitizingDockWidget *cadDockWidget() const { return mCadDockWidget.data(); } + /** + * Returns a widget to control the tool. + * \note The caller gets the ownership. + */ + virtual QWidget *createWidget() { return nullptr; } + /** * Paints tool content onto the advanced digitizing canvas item. */ virtual void paint( QPainter *painter ) { Q_UNUSED( painter ) } /** - * Handles canvas press event. If TRUE is returned, the tool will have - * blocked the event for propagating. + * Handles canvas press event. + * \note To stop propagation, set the event's accepted property to FALSE. */ - virtual bool canvasPressEvent( QgsMapMouseEvent *event ) + virtual void canvasPressEvent( QgsMapMouseEvent *event ) { Q_UNUSED( event ) - return true; } /** - * Handles canvas press move. If TRUE is returned, the tool will have - * blocked the event for propagating. + * Handles canvas press move. + * \note To stop propagation, set the event's accepted property to FALSE. */ - virtual bool canvasMoveEvent( QgsMapMouseEvent *event ) + virtual void canvasMoveEvent( QgsMapMouseEvent *event ) { Q_UNUSED( event ) - return true; } /** - * Handles canvas release event. If TRUE is returned, the tool will have - * blocked the event for propagating. + * Handles canvas release event. + * \note To stop propagation, set the event's accepted property to FALSE. */ - virtual bool canvasReleaseEvent( QgsMapMouseEvent *event ) + virtual void canvasReleaseEvent( QgsMapMouseEvent *event ) { Q_UNUSED( event ) - return true; } signals: @@ -127,10 +130,11 @@ class GUI_EXPORT QgsAdvancedDigitizingCirclesIntersectionTool : public QgsAdvanc */ explicit QgsAdvancedDigitizingCirclesIntersectionTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); + QWidget *createWidget() override; void paint( QPainter *painter ) override; - bool canvasMoveEvent( QgsMapMouseEvent *event ) override; - bool canvasReleaseEvent( QgsMapMouseEvent *event ) override; + void canvasMoveEvent( QgsMapMouseEvent *event ) override; + void canvasReleaseEvent( QgsMapMouseEvent *event ) override; private: void processParameters(); @@ -138,6 +142,7 @@ class GUI_EXPORT QgsAdvancedDigitizingCirclesIntersectionTool : public QgsAdvanc void drawCircle( QPainter *painter, double x, double y, double distance ); void drawCandidate( QPainter *painter, double x, double y, bool closest ); + QPointer mToolWidget; QToolButton *mCircle1Digitize = nullptr; QgsDoubleSpinBox *mCircle1X = nullptr; QgsDoubleSpinBox *mCircle1Y = nullptr; diff --git a/src/gui/qgsadvanceddigitizingtoolsregistry.cpp b/src/gui/qgsadvanceddigitizingtoolsregistry.cpp index 77b7992b8c67..6f1b09a75f4b 100644 --- a/src/gui/qgsadvanceddigitizingtoolsregistry.cpp +++ b/src/gui/qgsadvanceddigitizingtoolsregistry.cpp @@ -49,6 +49,7 @@ bool QgsAdvancedDigitizingToolsRegistry::addTool( QgsAdvancedDigitizingToolAbstr return false; mTools[toolMetaData->name()] = toolMetaData; + return true; } @@ -59,6 +60,7 @@ bool QgsAdvancedDigitizingToolsRegistry::removeTool( const QString &name ) return false; delete mTools.take( name ); + return true; } diff --git a/src/gui/qgsadvanceddigitizingtoolsregistry.h b/src/gui/qgsadvanceddigitizingtoolsregistry.h index 3793cda98a58..e320822053d3 100644 --- a/src/gui/qgsadvanceddigitizingtoolsregistry.h +++ b/src/gui/qgsadvanceddigitizingtoolsregistry.h @@ -115,6 +115,9 @@ class GUI_EXPORT QgsAdvancedDigitizingToolMetadata : public QgsAdvancedDigitizin * \ingroup gui * \brief Registry of available advanced digitizing tools. * + * QgsAdvancedDigitizingToolsRegistry is not usually directly created, but rather accessed through + * QgsGui::advancedDigitizingToolsRegistry(). + * * \since QGIS 3.40 */ class GUI_EXPORT QgsAdvancedDigitizingToolsRegistry diff --git a/src/gui/qgsmaptooladvanceddigitizing.cpp b/src/gui/qgsmaptooladvanceddigitizing.cpp index 30e08a0c9d57..94f3d804a2e0 100644 --- a/src/gui/qgsmaptooladvanceddigitizing.cpp +++ b/src/gui/qgsmaptooladvanceddigitizing.cpp @@ -36,9 +36,10 @@ void QgsMapToolAdvancedDigitizing::canvasPressEvent( QgsMapMouseEvent *e ) if ( isAdvancedDigitizingAllowed() && mCadDockWidget->cadEnabled() ) { mCadDockWidget->applyConstraints( e ); // updates event's map point - if ( mCadDockWidget->processCanvasPressEvent( e ) ) + mCadDockWidget->processCanvasPressEvent( e ); + if ( !e->isAccepted() ) { - return; // The dock widget has eaten the event + return; // The dock widget has taken the event } } else if ( isAutoSnapEnabled() ) @@ -66,9 +67,10 @@ void QgsMapToolAdvancedDigitizing::canvasReleaseEvent( QgsMapMouseEvent *e ) else { mCadDockWidget->applyConstraints( e ); // updates event's map point - if ( mCadDockWidget->processCanvasReleaseEvent( e ) ) + mCadDockWidget->processCanvasReleaseEvent( e ); + if ( !e->isAccepted() ) { - return; // The dock widget has eaten the event + return; // The dock widget has taken the event } } } @@ -91,9 +93,10 @@ void QgsMapToolAdvancedDigitizing::canvasMoveEvent( QgsMapMouseEvent *e ) if ( isAdvancedDigitizingAllowed() && mCadDockWidget->cadEnabled() ) { mCadDockWidget->applyConstraints( e ); // updates event's map point - if ( mCadDockWidget->processCanvasMoveEvent( e ) ) + mCadDockWidget->processCanvasMoveEvent( e ); + if ( !e->isAccepted() ) { - return; // The dock widget has eaten the event + return; // The dock widget has taken the event } } else if ( isAutoSnapEnabled() ) diff --git a/tests/src/gui/CMakeLists.txt b/tests/src/gui/CMakeLists.txt index 94edb3c983fe..a1d151f974e0 100644 --- a/tests/src/gui/CMakeLists.txt +++ b/tests/src/gui/CMakeLists.txt @@ -25,6 +25,7 @@ endif() set(TESTS testqgsadvanceddigitizingdockwidget.cpp + testqgsadvanceddigitizingtoolsregistry.cpp testqgsannotationitemguiregistry.cpp testqgsmaptoolzoom.cpp testqgsmaptooledit.cpp