[advanced digitizing] Add circles intersection digitizing tool (#57648)

This commit is contained in:
Mathieu Pellerin 2024-07-31 17:05:58 +07:00 committed by GitHub
parent 1c0484f455
commit 6994d1c680
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 1690 additions and 34 deletions

View File

@ -693,6 +693,7 @@
<file>themes/default/mActionPanHighlightFeature.svg</file>
<file>themes/default/mActionPrevious.svg</file>
<file>themes/default/mActionPlay.svg</file>
<file>themes/default/cadtools/circlesintersection.svg</file>
<file>themes/default/cadtools/construction.svg</file>
<file>themes/default/cadtools/delta.svg</file>
<file>themes/default/cadtools/floater.svg</file>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke-linecap="square">
<circle cx="8" cy="16" r="1" stop-color="#000000" stroke="#000" stroke-width=".5"/>
<circle cx="16" cy="9" r="1" stop-color="#000000" stroke="#000" stroke-width=".5"/>
<circle cx="16" cy="9" r="6.5" stop-color="#000000" stroke="#f3e278"/>
<circle cx="8" cy="16" r="7.5" stop-color="#000000" stroke="#f3e278"/>
</g>
<circle cx="8" cy="16" r="1" fill="#f3e278" stop-color="#000000"/>
<circle cx="8" cy="16" r="7.5" fill="none" stop-color="#000000" stroke="#000" stroke-dasharray="1,3" stroke-linecap="square"/>
<circle cx="16" cy="9" r="6.5" fill="none" stop-color="#000000" stroke="#000" stroke-dasharray="0.99999899,2.99999696" stroke-linecap="square"/>
<circle cx="16" cy="9" r="1" fill="#f3e278" stop-color="#000000"/>
<g fill="none" stroke-linecap="square">
<rect x="7.5" y="6.5" width="4" height="4" stop-color="#000000" stroke="#000" stroke-width="2.5"/>
<rect x="7.5" y="6.5" width="4" height="4" stop-color="#000000" stroke="#ffa169" stroke-width="2"/>
<rect x="14.5" y="14.5" width="2" height="2" stop-color="#000000" stroke="#000" stroke-width="1.5"/>
<rect x="14.5" y="14.5" width="2" height="2" stop-color="#000000" stroke="#f3e278"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -138,6 +138,22 @@ is equal to :py:func:`~QgsDoubleSpinBox.minimum`. Typical use is to indicate tha
virtual void stepBy( int steps );
signals:
void returnPressed();
%Docstring
Emitted when the Return or Enter key is used in the line edit.
.. versionadded:: 3.40
%End
void textEdited( const QString &text );
%Docstring
Emitted when the the value has been manually edited via line edit.
.. versionadded:: 3.40
%End
protected:
virtual void changeEvent( QEvent *event );

View File

@ -136,6 +136,22 @@ is equal to :py:func:`~QgsSpinBox.minimum`. Typical use is to indicate that this
virtual void stepBy( int steps );
signals:
void returnPressed();
%Docstring
Emitted when the Return or Enter key is used in the line edit
.. versionadded:: 3.40
%End
void textEdited( const QString &text );
%Docstring
Emitted when the the value has been manually edited via line edit.
.. versionadded:: 3.40
%End
protected:
virtual void changeEvent( QEvent *event );

View File

@ -204,13 +204,15 @@ Removes unit suffix from the constraint text.
};
explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = 0 );
explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = 0, QgsUserInputWidget *userInputWidget = 0 );
%Docstring
Create an advanced digitizing dock widget
:param canvas: The map canvas on which the widget operates
:param parent: The parent
:param userInputWidget: The user input widget on which tools can add widget overlays on top of the map canvas (since QGIS 3.40)
%End
~QgsAdvancedDigitizingDockWidget();
bool canvasKeyPressEventFilter( QKeyEvent *e );
%Docstring
@ -232,6 +234,35 @@ apply the CAD constraints. The will modify the position of the map event in map
%Docstring
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
void processCanvasPressEvent( QgsMapMouseEvent *event );
%Docstring
Processes the canvas press ``event``.
%End
void processCanvasMoveEvent( QgsMapMouseEvent *event );
%Docstring
Processes the canvas move ``event``.
%End
void processCanvasReleaseEvent( QgsMapMouseEvent *event );
%Docstring
Processes the canvas release ``event``.
%End
void setTool( QgsAdvancedDigitizingTool *tool );
%Docstring
Sets an advanced digitizing tool which will take over digitizing until the tool is close.
.. versionadded:: 3.40
%End
QgsAdvancedDigitizingTool *tool() const;
%Docstring
Returns the current advanced digitizing tool. Returns ``None`` if not set.
.. versionadded:: 3.40
%End
void releaseLocks( bool releaseRepeatingLocks = true );
@ -372,6 +403,13 @@ Returns the X value of the X soft lock. The value is NaN is the constraint isn't
double softLockY() const;
%Docstring
Returns the Y value of the Y soft lock. The value is NaN is the constraint isn't magnetized to a line
%End
void toggleConstraintDistance();
%Docstring
Toggles the distance constraint.
.. versionadded:: 3.40
%End
QgsPointLocator::Match mapPointMatch() const;

View File

@ -0,0 +1,104 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtools.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsAdvancedDigitizingTool : QObject
{
%Docstring(signature="appended")
An abstract class for advanced digitizing tools.
.. versionadded:: 3.40
%End
%TypeHeaderCode
#include "qgsadvanceddigitizingtools.h"
%End
public:
explicit QgsAdvancedDigitizingTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget );
%Docstring
The advanced digitizing tool constructor.
:param canvas: The map canvas on which the widget operates
:param cadDockWidget: The cadDockWidget to which the floater belongs
%End
QgsMapCanvas *mapCanvas() const;
%Docstring
Returns the map canvas associated with the tool.
%End
QgsAdvancedDigitizingDockWidget *cadDockWidget() const;
%Docstring
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 void canvasPressEvent( QgsMapMouseEvent *event );
%Docstring
Handles canvas press event.
.. note::
To stop propagation, set the event's accepted property to ``False``.
%End
virtual void canvasMoveEvent( QgsMapMouseEvent *event );
%Docstring
Handles canvas press move.
.. note::
To stop propagation, set the event's accepted property to ``False``.
%End
virtual void canvasReleaseEvent( QgsMapMouseEvent *event );
%Docstring
Handles canvas release event.
.. note::
To stop propagation, set the event's accepted property to ``False``.
%End
signals:
void paintRequested();
%Docstring
Requests a new painting event to the advanced digitizing canvas item.
%End
protected:
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtools.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -0,0 +1,116 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtoolsregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsAdvancedDigitizingToolAbstractMetadata
{
%Docstring(signature="appended")
Stores metadata about one advanced digitizing tool class.
.. versionadded:: 3.40
%End
%TypeHeaderCode
#include "qgsadvanceddigitizingtoolsregistry.h"
%End
public:
QgsAdvancedDigitizingToolAbstractMetadata( const QString &name, const QString &visibleName, const QIcon &icon = QIcon() );
%Docstring
Constructor for QgsAdvancedDigitizingToolAbstractMetadata with the specified tool ``name``.
``visibleName`` should be set to a translated, user visible name identifying the corresponding annotation item.
An optional ``icon`` can be set, which will be used by the advanced digitizing dock widget.
%End
virtual ~QgsAdvancedDigitizingToolAbstractMetadata();
QString name() const;
%Docstring
Returns the tool's unique name
%End
QString visibleName() const;
%Docstring
Returns the tool's translatable user-friendly name
%End
QIcon icon() const;
%Docstring
Returns the tool's icon
%End
virtual QgsAdvancedDigitizingTool *createTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ) /Factory/;
%Docstring
Returns new tool of this type. Return ``None`` on error
%End
protected:
};
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
%TypeHeaderCode
#include "qgsadvanceddigitizingtoolsregistry.h"
%End
public:
QgsAdvancedDigitizingToolsRegistry();
~QgsAdvancedDigitizingToolsRegistry();
void addDefaultTools();
%Docstring
Adds the default tools shipped in QGIS
%End
bool addTool( QgsAdvancedDigitizingToolAbstractMetadata *toolMetaData /Transfer/ );
%Docstring
Adds an advanced digitizing tool (take ownership) and return ``True`` on success
%End
bool removeTool( const QString &name );
%Docstring
Removes the advanced digitizing tool matching the provided ``name`` and return ``True`` on success
%End
QgsAdvancedDigitizingToolAbstractMetadata *toolMetadata( const QString &name );
%Docstring
Returns the advanced digitizing tool matching the provided ``name`` or ``None`` when no match available
%End
const QStringList toolMetadataNames() const;
%Docstring
Returns the list of registered tool names
%End
private:
QgsAdvancedDigitizingToolsRegistry( const QgsAdvancedDigitizingToolsRegistry &rh );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtoolsregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -77,6 +77,13 @@ Returns the global layout item GUI registry, used for registering the GUI behavi
Returns the global annotation item GUI registry, used for registering the GUI behavior of annotation items.
.. versionadded:: 3.22
%End
static QgsAdvancedDigitizingToolsRegistry *advancedDigitizingToolsRegistry() /KeepReference/;
%Docstring
Returns the global advanced digitizing tools registry, used for registering advanced digitizing tools.
.. versionadded:: 3.40
%End
static QgsProcessingGuiRegistry *processingGuiRegistry() /KeepReference/;

View File

@ -6,6 +6,8 @@
%Include auto_generated/qgsadvanceddigitizingcanvasitem.sip
%Include auto_generated/qgsadvanceddigitizingdockwidget.sip
%Include auto_generated/qgsadvanceddigitizingfloater.sip
%Include auto_generated/qgsadvanceddigitizingtools.sip
%Include auto_generated/qgsadvanceddigitizingtoolsregistry.sip
%Include auto_generated/qgsaggregatetoolbutton.sip
%Include auto_generated/qgsalignmentcombobox.sip
%Include auto_generated/qgsapplicationexitblockerinterface.sip

View File

@ -138,6 +138,22 @@ is equal to :py:func:`~QgsDoubleSpinBox.minimum`. Typical use is to indicate tha
virtual void stepBy( int steps );
signals:
void returnPressed();
%Docstring
Emitted when the Return or Enter key is used in the line edit.
.. versionadded:: 3.40
%End
void textEdited( const QString &text );
%Docstring
Emitted when the the value has been manually edited via line edit.
.. versionadded:: 3.40
%End
protected:
virtual void changeEvent( QEvent *event );

View File

@ -136,6 +136,22 @@ is equal to :py:func:`~QgsSpinBox.minimum`. Typical use is to indicate that this
virtual void stepBy( int steps );
signals:
void returnPressed();
%Docstring
Emitted when the Return or Enter key is used in the line edit
.. versionadded:: 3.40
%End
void textEdited( const QString &text );
%Docstring
Emitted when the the value has been manually edited via line edit.
.. versionadded:: 3.40
%End
protected:
virtual void changeEvent( QEvent *event );

View File

@ -204,13 +204,15 @@ Removes unit suffix from the constraint text.
};
explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = 0 );
explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = 0, QgsUserInputWidget *userInputWidget = 0 );
%Docstring
Create an advanced digitizing dock widget
:param canvas: The map canvas on which the widget operates
:param parent: The parent
:param userInputWidget: The user input widget on which tools can add widget overlays on top of the map canvas (since QGIS 3.40)
%End
~QgsAdvancedDigitizingDockWidget();
bool canvasKeyPressEventFilter( QKeyEvent *e );
%Docstring
@ -232,6 +234,35 @@ apply the CAD constraints. The will modify the position of the map event in map
%Docstring
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
void processCanvasPressEvent( QgsMapMouseEvent *event );
%Docstring
Processes the canvas press ``event``.
%End
void processCanvasMoveEvent( QgsMapMouseEvent *event );
%Docstring
Processes the canvas move ``event``.
%End
void processCanvasReleaseEvent( QgsMapMouseEvent *event );
%Docstring
Processes the canvas release ``event``.
%End
void setTool( QgsAdvancedDigitizingTool *tool );
%Docstring
Sets an advanced digitizing tool which will take over digitizing until the tool is close.
.. versionadded:: 3.40
%End
QgsAdvancedDigitizingTool *tool() const;
%Docstring
Returns the current advanced digitizing tool. Returns ``None`` if not set.
.. versionadded:: 3.40
%End
void releaseLocks( bool releaseRepeatingLocks = true );
@ -372,6 +403,13 @@ Returns the X value of the X soft lock. The value is NaN is the constraint isn't
double softLockY() const;
%Docstring
Returns the Y value of the Y soft lock. The value is NaN is the constraint isn't magnetized to a line
%End
void toggleConstraintDistance();
%Docstring
Toggles the distance constraint.
.. versionadded:: 3.40
%End
QgsPointLocator::Match mapPointMatch() const;

View File

@ -0,0 +1,104 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtools.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsAdvancedDigitizingTool : QObject
{
%Docstring(signature="appended")
An abstract class for advanced digitizing tools.
.. versionadded:: 3.40
%End
%TypeHeaderCode
#include "qgsadvanceddigitizingtools.h"
%End
public:
explicit QgsAdvancedDigitizingTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget );
%Docstring
The advanced digitizing tool constructor.
:param canvas: The map canvas on which the widget operates
:param cadDockWidget: The cadDockWidget to which the floater belongs
%End
QgsMapCanvas *mapCanvas() const;
%Docstring
Returns the map canvas associated with the tool.
%End
QgsAdvancedDigitizingDockWidget *cadDockWidget() const;
%Docstring
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 void canvasPressEvent( QgsMapMouseEvent *event );
%Docstring
Handles canvas press event.
.. note::
To stop propagation, set the event's accepted property to ``False``.
%End
virtual void canvasMoveEvent( QgsMapMouseEvent *event );
%Docstring
Handles canvas press move.
.. note::
To stop propagation, set the event's accepted property to ``False``.
%End
virtual void canvasReleaseEvent( QgsMapMouseEvent *event );
%Docstring
Handles canvas release event.
.. note::
To stop propagation, set the event's accepted property to ``False``.
%End
signals:
void paintRequested();
%Docstring
Requests a new painting event to the advanced digitizing canvas item.
%End
protected:
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtools.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -0,0 +1,116 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtoolsregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsAdvancedDigitizingToolAbstractMetadata
{
%Docstring(signature="appended")
Stores metadata about one advanced digitizing tool class.
.. versionadded:: 3.40
%End
%TypeHeaderCode
#include "qgsadvanceddigitizingtoolsregistry.h"
%End
public:
QgsAdvancedDigitizingToolAbstractMetadata( const QString &name, const QString &visibleName, const QIcon &icon = QIcon() );
%Docstring
Constructor for QgsAdvancedDigitizingToolAbstractMetadata with the specified tool ``name``.
``visibleName`` should be set to a translated, user visible name identifying the corresponding annotation item.
An optional ``icon`` can be set, which will be used by the advanced digitizing dock widget.
%End
virtual ~QgsAdvancedDigitizingToolAbstractMetadata();
QString name() const;
%Docstring
Returns the tool's unique name
%End
QString visibleName() const;
%Docstring
Returns the tool's translatable user-friendly name
%End
QIcon icon() const;
%Docstring
Returns the tool's icon
%End
virtual QgsAdvancedDigitizingTool *createTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ) /Factory/;
%Docstring
Returns new tool of this type. Return ``None`` on error
%End
protected:
};
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
%TypeHeaderCode
#include "qgsadvanceddigitizingtoolsregistry.h"
%End
public:
QgsAdvancedDigitizingToolsRegistry();
~QgsAdvancedDigitizingToolsRegistry();
void addDefaultTools();
%Docstring
Adds the default tools shipped in QGIS
%End
bool addTool( QgsAdvancedDigitizingToolAbstractMetadata *toolMetaData /Transfer/ );
%Docstring
Adds an advanced digitizing tool (take ownership) and return ``True`` on success
%End
bool removeTool( const QString &name );
%Docstring
Removes the advanced digitizing tool matching the provided ``name`` and return ``True`` on success
%End
QgsAdvancedDigitizingToolAbstractMetadata *toolMetadata( const QString &name );
%Docstring
Returns the advanced digitizing tool matching the provided ``name`` or ``None`` when no match available
%End
const QStringList toolMetadataNames() const;
%Docstring
Returns the list of registered tool names
%End
private:
QgsAdvancedDigitizingToolsRegistry( const QgsAdvancedDigitizingToolsRegistry &rh );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsadvanceddigitizingtoolsregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -77,6 +77,13 @@ Returns the global layout item GUI registry, used for registering the GUI behavi
Returns the global annotation item GUI registry, used for registering the GUI behavior of annotation items.
.. versionadded:: 3.22
%End
static QgsAdvancedDigitizingToolsRegistry *advancedDigitizingToolsRegistry() /KeepReference/;
%Docstring
Returns the global advanced digitizing tools registry, used for registering advanced digitizing tools.
.. versionadded:: 3.40
%End
static QgsProcessingGuiRegistry *processingGuiRegistry() /KeepReference/;

View File

@ -6,6 +6,8 @@
%Include auto_generated/qgsadvanceddigitizingcanvasitem.sip
%Include auto_generated/qgsadvanceddigitizingdockwidget.sip
%Include auto_generated/qgsadvanceddigitizingfloater.sip
%Include auto_generated/qgsadvanceddigitizingtools.sip
%Include auto_generated/qgsadvanceddigitizingtoolsregistry.sip
%Include auto_generated/qgsaggregatetoolbutton.sip
%Include auto_generated/qgsalignmentcombobox.sip
%Include auto_generated/qgsapplicationexitblockerinterface.sip

View File

@ -1186,7 +1186,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipBadLayers
// Advanced Digitizing dock
startProfile( tr( "Advanced digitize panel" ) );
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this );
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this, mUserInputDockWidget );
mAdvancedDigitizingDockWidget->setWindowTitle( tr( "Advanced Digitizing" ) );
mAdvancedDigitizingDockWidget->setObjectName( QStringLiteral( "AdvancedDigitizingTools" ) );

View File

@ -518,6 +518,8 @@ set(QGIS_GUI_SRCS
qgsadvanceddigitizingcanvasitem.cpp
qgsadvanceddigitizingdockwidget.cpp
qgsadvanceddigitizingfloater.cpp
qgsadvanceddigitizingtools.cpp
qgsadvanceddigitizingtoolsregistry.cpp
qgsaggregatetoolbutton.cpp
qgsalignmentcombobox.cpp
qgsapplicationexitblockerinterface.cpp
@ -790,6 +792,8 @@ set(QGIS_GUI_HDRS
qgsadvanceddigitizingcanvasitem.h
qgsadvanceddigitizingdockwidget.h
qgsadvanceddigitizingfloater.h
qgsadvanceddigitizingtools.h
qgsadvanceddigitizingtoolsregistry.h
qgsaggregatetoolbutton.h
qgsalignmentcombobox.h
qgsapplicationexitblockerinterface.h

View File

@ -40,6 +40,7 @@ QgsDoubleSpinBox::QgsDoubleSpinBox( QWidget *parent )
: QDoubleSpinBox( parent )
{
mLineEdit = new QgsSpinBoxLineEdit();
connect( mLineEdit, &QLineEdit::returnPressed, this, &QgsDoubleSpinBox::returnPressed );
// By default, group separator is off
setLineEdit( mLineEdit );

View File

@ -142,6 +142,20 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
void paintEvent( QPaintEvent *e ) override;
void stepBy( int steps ) override;
signals:
/**
* Emitted when the Return or Enter key is used in the line edit.
* \since QGIS 3.40
*/
void returnPressed();
/**
* Emitted when the the value has been manually edited via line edit.
* \since QGIS 3.40
*/
void textEdited( const QString &text );
protected:
void changeEvent( QEvent *event ) override;
void wheelEvent( QWheelEvent *event ) override;

View File

@ -39,6 +39,8 @@ QgsSpinBox::QgsSpinBox( QWidget *parent )
: QSpinBox( parent )
{
mLineEdit = new QgsSpinBoxLineEdit();
connect( mLineEdit, &QLineEdit::returnPressed, this, &QgsSpinBox::returnPressed );
connect( mLineEdit, &QLineEdit::textEdited, this, &QgsSpinBox::textEdited );
setLineEdit( mLineEdit );
const QSize msz = minimumSizeHint();

View File

@ -141,6 +141,20 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
QValidator::State validate( QString &input, int &pos ) const override;
void stepBy( int steps ) override;
signals:
/**
* Emitted when the Return or Enter key is used in the line edit
* \since QGIS 3.40
*/
void returnPressed();
/**
* Emitted when the the value has been manually edited via line edit.
* \since QGIS 3.40
*/
void textEdited( const QString &text );
protected:
void changeEvent( QEvent *event ) override;

View File

@ -59,6 +59,14 @@ void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter )
}
}
// Draw current tool
if ( QgsAdvancedDigitizingTool *tool = mAdvancedDigitizingDockWidget->tool() )
{
// 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;
}
// Use visible polygon rather than extent to properly handle rotated maps
QPolygonF mapPoly = mMapCanvas->mapSettings().visiblePolygon();
const double canvasWidth = QLineF( mapPoly[0], mapPoly[1] ).length();

View File

@ -22,9 +22,11 @@
#include "qgsadvanceddigitizingdockwidget.h"
#include "qgsadvanceddigitizingfloater.h"
#include "qgsadvanceddigitizingcanvasitem.h"
#include "qgsadvanceddigitizingtoolsregistry.h"
#include "qgsbearingnumericformat.h"
#include "qgscadutils.h"
#include "qgsexpression.h"
#include "qgsgui.h"
#include "qgsmapcanvas.h"
#include "qgsmaptooledit.h"
#include "qgsmaptooladvanceddigitizing.h"
@ -38,6 +40,7 @@
#include "qgsunittypes.h"
#include "qgssettingsentryimpl.h"
#include "qgssettingstree.h"
#include "qgsuserinputwidget.h"
#include <QActionGroup>
@ -48,9 +51,10 @@ const QgsSettingsEntryBool *QgsAdvancedDigitizingDockWidget::settingsCadShowCons
const QgsSettingsEntryBool *QgsAdvancedDigitizingDockWidget::settingsCadSnapToConstructionGuides = new QgsSettingsEntryBool( QStringLiteral( "cad-snap-to-construction-guides" ), QgsSettingsTree::sTreeDigitizing, false, tr( "Determines if points will snap to construction guides." ) ) ;
QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent )
QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent, QgsUserInputWidget *userInputWidget )
: QgsDockWidget( parent )
, mMapCanvas( canvas )
, mUserInputWidget( userInputWidget )
, mSnapIndicator( std::make_unique< QgsSnapIndicator>( canvas ) )
, mCommonAngleConstraint( QgsSettings().value( QStringLiteral( "/Cad/CommonAngle" ), 0.0 ).toDouble() )
{
@ -183,7 +187,6 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *
mCommonAngleActionsMenu->addMenu( snappingPriorityMenu );
}
for ( QList< QPair<double, QString > >::const_iterator it = commonAngles.constBegin(); it != commonAngles.constEnd(); ++it )
{
QAction *action = new QAction( it->second, mCommonAngleActionsMenu );
@ -237,6 +240,26 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *
constructionModeToolButton->setMenu( constructionSettingsMenu );
constructionModeToolButton->setObjectName( QStringLiteral( "ConstructionModeButton" ) );
// Tools
QMenu *toolsMenu = new QMenu( this );
connect( toolsMenu, &QMenu::aboutToShow, this, [ = ]()
{
toolsMenu->clear();
const QStringList toolMetadataNames = QgsGui::instance()->advancedDigitizingToolsRegistry()->toolMetadataNames();
for ( const QString &name : toolMetadataNames )
{
QgsAdvancedDigitizingToolAbstractMetadata *toolMetadata = QgsGui::instance()->advancedDigitizingToolsRegistry()->toolMetadata( name );
QAction *toolAction = new QAction( toolMetadata->icon(), toolMetadata->visibleName(), toolsMenu );
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 );
qobject_cast< QToolButton *>( mToolbar->widgetForAction( mSettingsAction ) )->setPopupMode( QToolButton::InstantPopup );
mSettingsAction->setMenu( mCommonAngleActionsMenu );
mSettingsAction->setCheckable( true );
@ -420,6 +443,14 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *
disable();
}
QgsAdvancedDigitizingDockWidget::~QgsAdvancedDigitizingDockWidget()
{
if ( mCurrentTool )
{
mCurrentTool->deleteLater();
}
}
QString QgsAdvancedDigitizingDockWidget::formatCommonAngleSnapping( double angle )
{
if ( angle == 0 )
@ -536,6 +567,7 @@ void QgsAdvancedDigitizingDockWidget::setCadEnabled( bool enabled )
mInputWidgets->setEnabled( enabled );
mFloaterAction->setEnabled( enabled );
mConstructionAction->setEnabled( enabled );
mToolsAction->setEnabled( enabled );
if ( !enabled )
{
@ -545,6 +577,10 @@ void QgsAdvancedDigitizingDockWidget::setCadEnabled( bool enabled )
// will be reactivated in updateCapacities
mParallelAction->setEnabled( false );
mPerpendicularAction->setEnabled( false );
if ( mCurrentTool )
{
mCurrentTool->deleteLater();
}
}
@ -644,6 +680,32 @@ void QgsAdvancedDigitizingDockWidget::activateCad( bool enabled )
setCadEnabled( enabled );
}
void QgsAdvancedDigitizingDockWidget::setTool( QgsAdvancedDigitizingTool *tool )
{
if ( mCurrentTool )
{
mCurrentTool->deleteLater();
mCurrentTool = nullptr;
}
mCurrentTool = tool;
if ( mCurrentTool )
{
if ( QWidget *toolWidget = mCurrentTool->createWidget() )
{
toolWidget->setParent( mUserInputWidget );
mUserInputWidget->addUserInputWidget( toolWidget );
}
connect( mCurrentTool.data(), &QgsAdvancedDigitizingTool::paintRequested, this, &QgsAdvancedDigitizingDockWidget::updateCadPaintItem );
}
}
QgsAdvancedDigitizingTool *QgsAdvancedDigitizingDockWidget::tool() const
{
return mCurrentTool.data();
}
void QgsAdvancedDigitizingDockWidget::betweenLineConstraintClicked( bool activated )
{
if ( !activated )
@ -1492,6 +1554,76 @@ QList<QgsPointXY> QgsAdvancedDigitizingDockWidget::snapSegmentToAllLayers( const
return segment;
}
void QgsAdvancedDigitizingDockWidget::processCanvasPressEvent( QgsMapMouseEvent *event )
{
if ( mCurrentTool )
{
mCurrentTool->canvasPressEvent( event );
}
if ( constructionMode() )
{
event->setAccepted( false );
}
}
void QgsAdvancedDigitizingDockWidget::processCanvasMoveEvent( QgsMapMouseEvent *event )
{
// perpendicular/parallel constraint
// do a soft lock when snapping to a segment
alignToSegment( event, QgsAdvancedDigitizingDockWidget::CadConstraint::SoftLock );
if ( mCurrentTool )
{
mCurrentTool->canvasMoveEvent( event );
}
updateCadPaintItem();
}
void QgsAdvancedDigitizingDockWidget::processCanvasReleaseEvent( QgsMapMouseEvent *event )
{
if ( alignToSegment( event ) )
{
event->setAccepted( false );
return;
}
if ( mCurrentTool )
{
mCurrentTool->canvasReleaseEvent( event );
if ( !event->isAccepted() )
{
return;
}
else
{
// update the point list
QgsPoint point( event->mapPoint() );
point.setZ( QgsMapToolEdit::defaultZValue() );
point.setM( QgsMapToolEdit::defaultMValue() );
if ( mLockZButton->isChecked() )
{
point.setZ( QLocale().toDouble( mZLineEdit->text() ) );
}
if ( mLockMButton->isChecked() )
{
point.setM( QLocale().toDouble( mMLineEdit->text() ) );
}
updateCurrentPoint( point );
}
}
addPoint( event->mapPoint() );
releaseLocks( false );
if ( constructionMode() )
{
event->setAccepted( false );
}
}
bool QgsAdvancedDigitizingDockWidget::alignToSegment( QgsMapMouseEvent *e, CadConstraint::LockMode lockMode )
{
if ( mBetweenLineConstraint == Qgis::BetweenLineConstraint::NoConstraint )
@ -1621,6 +1753,13 @@ void QgsAdvancedDigitizingDockWidget::setPoints( const QList<QgsPointXY> &points
}
}
void QgsAdvancedDigitizingDockWidget::toggleConstraintDistance()
{
mDistanceConstraint->toggleLocked();
emit lockDistanceChanged( mDistanceConstraint->isLocked() );
emit pointChangedV2( mCadPointList.value( 0 ) );
}
bool QgsAdvancedDigitizingDockWidget::eventFilter( QObject *obj, QEvent *event )
{
if ( !cadEnabled() )
@ -1833,9 +1972,7 @@ bool QgsAdvancedDigitizingDockWidget::filterKeyPress( QKeyEvent *e )
{
if ( mCapacities.testFlag( RelativeCoordinates ) && mCapacities.testFlag( Distance ) )
{
mDistanceConstraint->toggleLocked();
emit lockDistanceChanged( mDistanceConstraint->isLocked() );
emit pointChangedV2( mCadPointList.value( 0 ) );
toggleConstraintDistance();
e->accept();
}
}
@ -2001,7 +2138,6 @@ void QgsAdvancedDigitizingDockWidget::clearLockedSnapVertices( bool force )
mLockedSnapVertices.clear();
}
void QgsAdvancedDigitizingDockWidget::addPoint( const QgsPointXY &point )
{
QgsPoint pt = pointXYToPoint( point );

View File

@ -24,6 +24,7 @@
#include "ui_qgsadvanceddigitizingdockwidgetbase.h"
#include "qgis_gui.h"
#include "qgis_sip.h"
#include "qgsadvanceddigitizingtools.h"
#include "qgsdockwidget.h"
#include "qgsmessagebaritem.h"
#include "qgspointxy.h"
@ -33,10 +34,12 @@
class QgsAdvancedDigitizingCanvasItem;
class QgsAdvancedDigitizingFloater;
class QgsAdvancedDigitizingTool;
class QgsMapCanvas;
class QgsMapTool;
class QgsMapToolAdvancedDigitizing;
class QgsMapMouseEvent;
class QgsUserInputWidget;
/**
* \ingroup gui
@ -248,8 +251,10 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
* Create an advanced digitizing dock widget
* \param canvas The map canvas on which the widget operates
* \param parent The parent
* \param userInputWidget The user input widget on which tools can add widget overlays on top of the map canvas (since QGIS 3.40)
*/
explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = nullptr );
explicit QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent = nullptr, QgsUserInputWidget *userInputWidget = nullptr );
~QgsAdvancedDigitizingDockWidget();
/**
* Filter key events to e.g. toggle construction mode or adapt constraints
@ -271,6 +276,33 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
*/
bool alignToSegment( QgsMapMouseEvent *e, QgsAdvancedDigitizingDockWidget::CadConstraint::LockMode lockMode = QgsAdvancedDigitizingDockWidget::CadConstraint::HardLock );
/**
* Processes the canvas press \a event.
*/
void processCanvasPressEvent( QgsMapMouseEvent *event );
/**
* Processes the canvas move \a event.
*/
void processCanvasMoveEvent( QgsMapMouseEvent *event );
/**
* Processes the canvas release \a event.
*/
void processCanvasReleaseEvent( QgsMapMouseEvent *event );
/**
* Sets an advanced digitizing tool which will take over digitizing until the tool is close.
* \since QGIS 3.40
*/
void setTool( QgsAdvancedDigitizingTool *tool );
/**
* Returns the current advanced digitizing tool. Returns NULLPTR if not set.
* \since QGIS 3.40
*/
QgsAdvancedDigitizingTool *tool() const;
/**
* unlock all constraints
* \param releaseRepeatingLocks set to FALSE to preserve the lock for any constraints set to repeating lock mode
@ -378,6 +410,12 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
//! Returns the Y value of the Y soft lock. The value is NaN is the constraint isn't magnetized to a line
double softLockY() const { return mSoftLockY; }
/**
* Toggles the distance constraint.
* \since QGIS 3.40
*/
void toggleConstraintDistance();
/**
* Returns the point locator match
* \since QGIS 3.4
@ -1059,6 +1097,8 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
void updateConstructionGuidesCrs();
QgsMapCanvas *mMapCanvas = nullptr;
QgsUserInputWidget *mUserInputWidget = nullptr;
QgsAdvancedDigitizingCanvasItem *mCadPaintItem = nullptr;
//! Snapping indicator
std::unique_ptr<QgsSnapIndicator> mSnapIndicator;
@ -1124,6 +1164,9 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
double mSoftLockY;
QQueue< QgsPointLocator::Match > mLockedSnapVertices;
// Advanced digitizing tool
QPointer<QgsAdvancedDigitizingTool> mCurrentTool;
#ifdef SIP_RUN
//! event filter for line edits in the dock UI (angle/distance/x/y line edits)
bool eventFilter( QObject *obj, QEvent *event );

View File

@ -0,0 +1,299 @@
/***************************************************************************
qgsadvanceddigitizingintersectiontools.cpp
----------------------
begin : May 2024
copyright : (C) Mathieu Pellerin
email : mathieu at opengis dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QMouseEvent>
#include <QEnterEvent>
#include <QLocale>
#include "qgsadvanceddigitizingtools.h"
#include "qgsapplication.h"
#include "qgsdoublespinbox.h"
#include "qgsmapcanvas.h"
QgsAdvancedDigitizingTool::QgsAdvancedDigitizingTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
: QObject( canvas ? canvas->viewport() : nullptr )
, mMapCanvas( canvas )
, mCadDockWidget( cadDockWidget )
{
}
QgsAdvancedDigitizingCirclesIntersectionTool::QgsAdvancedDigitizingCirclesIntersectionTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
: QgsAdvancedDigitizingTool( canvas, cadDockWidget )
{
}
QgsAdvancedDigitizingCirclesIntersectionTool::~QgsAdvancedDigitizingCirclesIntersectionTool()
{
if ( mToolWidget )
{
mToolWidget->deleteLater();
}
}
QWidget *QgsAdvancedDigitizingCirclesIntersectionTool::createWidget()
{
QWidget *toolWidget = new QWidget();
QGridLayout *layout = new QGridLayout( toolWidget );
layout->setContentsMargins( 0, 0, 0, 0 );
toolWidget->setLayout( layout );
QLabel *label = new QLabel( QStringLiteral( "Circle #1" ), toolWidget );
layout->addWidget( label, 0, 0, 1, 3 );
mCircle1Digitize = new QToolButton( toolWidget );
mCircle1Digitize->setCheckable( true );
mCircle1Digitize->setChecked( false );
mCircle1Digitize->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapIdentification.svg" ) ) );
connect( mCircle1Digitize, &QAbstractButton::toggled, this, [ = ]( bool checked )
{
if ( checked )
{
mCircle2Digitize->setChecked( false );
}
} );
layout->addWidget( mCircle1Digitize, 1, 2, 2, 1 );
label = new QLabel( QStringLiteral( "X" ), toolWidget );
layout->addWidget( label, 1, 0 );
mCircle1X = new QgsDoubleSpinBox( toolWidget );
mCircle1X->setMinimum( std::numeric_limits<double>::min() );
mCircle1X->setMaximum( std::numeric_limits<double>::max() );
connect( mCircle1X, &QgsDoubleSpinBox::textEdited, this, [ = ]() { mCircle1Digitize->setChecked( false ); } );
layout->addWidget( mCircle1X, 1, 1 );
label = new QLabel( QStringLiteral( "Y" ), toolWidget );
layout->addWidget( label, 2, 0 );
mCircle1Y = new QgsDoubleSpinBox( toolWidget );
mCircle1Y->setMinimum( std::numeric_limits<double>::min() );
mCircle1Y->setMaximum( std::numeric_limits<double>::max() );
connect( mCircle1Y, &QgsDoubleSpinBox::textEdited, this, [ = ]() { mCircle1Digitize->setChecked( false ); } );
layout->addWidget( mCircle1Y, 2, 1 );
label = new QLabel( QStringLiteral( "Distance" ), toolWidget );
layout->addWidget( label, 3, 0 );
mCircle1Distance = new QgsDoubleSpinBox( toolWidget );
mCircle1Distance->setMinimum( 0 );
mCircle1Distance->setMaximum( std::numeric_limits<double>::max() );
connect( mCircle1Distance, &QgsDoubleSpinBox::returnPressed, this, [ = ]() { mCircle2Digitize->setChecked( true ); } );
layout->addWidget( mCircle1Distance, 3, 1 );
label = new QLabel( QStringLiteral( "Circle #2" ), toolWidget );
layout->addWidget( label, 4, 0, 1, 3 );
mCircle2Digitize = new QToolButton( toolWidget );
mCircle2Digitize->setCheckable( true );
mCircle2Digitize->setChecked( false );
mCircle2Digitize->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapIdentification.svg" ) ) );
connect( mCircle2Digitize, &QAbstractButton::toggled, this, [ = ]( bool checked )
{
if ( checked )
{
mCircle1Digitize->setChecked( false );
}
} );
layout->addWidget( mCircle2Digitize, 5, 2, 2, 1 );
label = new QLabel( QStringLiteral( "X" ), toolWidget );
layout->addWidget( label, 5, 0 );
mCircle2X = new QgsDoubleSpinBox( toolWidget );
mCircle2X->setMinimum( std::numeric_limits<double>::min() );
mCircle2X->setMaximum( std::numeric_limits<double>::max() );
connect( mCircle2X, &QgsDoubleSpinBox::textEdited, this, [ = ]() { mCircle2Digitize->setChecked( false ); } );
layout->addWidget( mCircle2X, 5, 1 );
label = new QLabel( QStringLiteral( "Y" ), toolWidget );
layout->addWidget( label, 6, 0 );
mCircle2Y = new QgsDoubleSpinBox( toolWidget );
mCircle2Y->setMinimum( std::numeric_limits<double>::min() );
mCircle2Y->setMaximum( std::numeric_limits<double>::max() );
connect( mCircle2Y, &QgsDoubleSpinBox::textEdited, this, [ = ]() { mCircle2Digitize->setChecked( false ); } );
layout->addWidget( mCircle2Y, 6, 1 );
label = new QLabel( QStringLiteral( "Distance" ), toolWidget );
layout->addWidget( label, 7, 0 );
mCircle2Distance = new QgsDoubleSpinBox( toolWidget );
mCircle2Distance->setMinimum( 0 );
mCircle2Distance->setMaximum( std::numeric_limits<double>::max() );
layout->addWidget( mCircle2Distance, 7, 1 );
connect( mCircle1X, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double ) { processParameters(); } );
connect( mCircle1Y, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double ) { processParameters(); } );
connect( mCircle1Distance, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double ) { processParameters(); } );
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(); } );
bool focusOnCircle2 = false;
if ( mCadDockWidget )
{
if ( mCadDockWidget->constraintDistance()->isLocked() )
{
QgsPoint point = mCadDockWidget->previousPointV2();
if ( !point.isEmpty() )
{
whileBlocking( mCircle1Distance )->setValue( mCadDockWidget->constraintDistance()->value() );
whileBlocking( mCircle1X )->setValue( point.x() );
whileBlocking( mCircle1Y )->setValue( point.y() );
mP1 = point;
focusOnCircle2 = true;
mCadDockWidget->toggleConstraintDistance();
}
}
}
if ( focusOnCircle2 )
{
mCircle2Digitize->setChecked( true );
}
else
{
mCircle1Digitize->setChecked( true );
}
mToolWidget = toolWidget;
return toolWidget;
}
void QgsAdvancedDigitizingCirclesIntersectionTool::processParameters()
{
mP1 = QgsPointXY();
mP2 = QgsPointXY();
QgsGeometryUtils::circleCircleIntersections( QgsPointXY( mCircle1X->value(), mCircle1Y->value() ), mCircle1Distance->value(),
QgsPointXY( mCircle2X->value(), mCircle2Y->value() ), mCircle2Distance->value(),
mP1, mP2 );
emit paintRequested();
}
void QgsAdvancedDigitizingCirclesIntersectionTool::canvasMoveEvent( QgsMapMouseEvent *event )
{
if ( mCircle1Digitize->isChecked() )
{
mCircle1X->setValue( event->mapPoint().x() );
mCircle1Y->setValue( event->mapPoint().y() );
}
else if ( mCircle2Digitize->isChecked() )
{
mCircle2X->setValue( event->mapPoint().x() );
mCircle2Y->setValue( event->mapPoint().y() );
}
if ( !mP1.isEmpty() )
{
mP1Closest = QgsGeometryUtils::distance2D( QgsPoint( mP1 ), QgsPoint( event->mapPoint() ) ) < QgsGeometryUtils::distance2D( QgsPoint( mP2 ), QgsPoint( event->mapPoint() ) );
}
event->setAccepted( false );
}
void QgsAdvancedDigitizingCirclesIntersectionTool::canvasReleaseEvent( QgsMapMouseEvent *event )
{
if ( mCircle1Digitize->isChecked() )
{
mCircle1X->setValue( event->mapPoint().x() );
mCircle1Y->setValue( event->mapPoint().y() );
mCircle1Digitize->setChecked( false );
mCircle1Distance->setFocus();
mCircle1Distance->selectAll();
event->setAccepted( false );
return;
}
else if ( mCircle2Digitize->isChecked() )
{
mCircle2X->setValue( event->mapPoint().x() );
mCircle2Y->setValue( event->mapPoint().y() );
mCircle2Digitize->setChecked( false );
mCircle2Distance->setFocus();
mCircle2Distance->selectAll();
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;
}
event->setAccepted( false );
}
void QgsAdvancedDigitizingCirclesIntersectionTool::drawCircle( QPainter *painter, double x, double y, double distance )
{
painter->setPen( QPen( QColor( 0, 127, 0, 200 ), 2 ) );
painter->setBrush( Qt::NoBrush );
mapCanvas()->getCoordinateTransform()->transformInPlace( x, y );
painter->drawLine( QLineF( x - 3, y - 3, x + 3, y + 3 ) );
painter->drawLine( QLineF( x - 3, y + 3, x + 3, y - 3 ) );
painter->setPen( QPen( QColor( 0, 127, 0, 150 ), 1, Qt::DashLine ) );
distance = distance / mapCanvas()->mapSettings().mapUnitsPerPixel();
painter->drawEllipse( QRectF( x - distance, y - distance, distance * 2, distance * 2 ) );
}
void QgsAdvancedDigitizingCirclesIntersectionTool::drawCandidate( QPainter *painter, double x, double y, bool closest )
{
if ( closest )
{
painter->setPen( QPen( QColor( 127, 0, 0, 222 ), 4 ) );
}
else
{
painter->setPen( QPen( QColor( 0, 127, 0, 222 ), 2 ) );
}
mapCanvas()->getCoordinateTransform()->transformInPlace( x, y );
double size = closest ? 5 : 3;
painter->drawRect( QRectF( x - size, y - size, size * 2, size * 2 ) );
}
void QgsAdvancedDigitizingCirclesIntersectionTool::paint( QPainter *painter )
{
painter->save();
drawCircle( painter, mCircle1X->value(), mCircle1Y->value(), mCircle1Distance->value() );
drawCircle( painter, mCircle2X->value(), mCircle2Y->value(), mCircle2Distance->value() );
if ( !mP1.isEmpty() )
{
if ( mP1Closest )
{
drawCandidate( painter, mP2.x(), mP2.y(), false );
drawCandidate( painter, mP1.x(), mP1.y(), true );
}
else
{
drawCandidate( painter, mP1.x(), mP1.y(), false );
drawCandidate( painter, mP2.x(), mP2.y(), true );
}
}
painter->restore();
}

View File

@ -0,0 +1,164 @@
/***************************************************************************
qgsadvanceddigitizingtools.h
----------------------
begin : May 2024
copyright : (C) Mathieu Pellerin
email : mathieu at opengis dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSADVANCEDDIGITIZINGTOOLS
#define QGSADVANCEDDIGITIZINGTOOLS
#include <QWidget>
#include <QString>
#include "qgsadvanceddigitizingdockwidget.h"
#include "qgis_gui.h"
#include "qgis_sip.h"
#include "qgsmapmouseevent.h"
#include <QPointer>
class QgsAdvancedDigitizingDockWidget;
class QgsDoubleSpinBox;
class QgsMapCanvas;
/**
* \ingroup gui
* \brief An abstract class for advanced digitizing tools.
* \since QGIS 3.40
*/
class GUI_EXPORT QgsAdvancedDigitizingTool : public QObject
{
Q_OBJECT
public:
/**
* The advanced digitizing tool constructor.
* \param canvas The map canvas on which the widget operates
* \param cadDockWidget The cadDockWidget to which the floater belongs
*/
explicit QgsAdvancedDigitizingTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget );
/**
* Returns the map canvas associated with the tool.
*/
QgsMapCanvas *mapCanvas() const { return mMapCanvas; }
/**
* Returns the advanced digitizing widget associated with the tool.
*/
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.
* \note To stop propagation, set the event's accepted property to FALSE.
*/
virtual void canvasPressEvent( QgsMapMouseEvent *event )
{
Q_UNUSED( event )
}
/**
* Handles canvas press move.
* \note To stop propagation, set the event's accepted property to FALSE.
*/
virtual void canvasMoveEvent( QgsMapMouseEvent *event )
{
Q_UNUSED( event )
}
/**
* Handles canvas release event.
* \note To stop propagation, set the event's accepted property to FALSE.
*/
virtual void canvasReleaseEvent( QgsMapMouseEvent *event )
{
Q_UNUSED( event )
}
signals:
/**
* Requests a new painting event to the advanced digitizing canvas item.
*/
void paintRequested();
protected:
QgsMapCanvas *mMapCanvas = nullptr;
QPointer< QgsAdvancedDigitizingDockWidget > mCadDockWidget;
};
#ifndef SIP_RUN
/**
* \ingroup gui
* \brief A advanced digitizing tools to handle the selection of a point at the intersection
* of two circles.
* \since QGIS 3.40
*/
class GUI_EXPORT QgsAdvancedDigitizingCirclesIntersectionTool : public QgsAdvancedDigitizingTool
{
Q_OBJECT
public:
/**
* The advanced digitizing's circles intersection tool constructor.
* \param canvas The map canvas on which the widget operates
* \param cadDockWidget The cadDockWidget to which the floater belongs
*/
explicit QgsAdvancedDigitizingCirclesIntersectionTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget );
~QgsAdvancedDigitizingCirclesIntersectionTool();
QWidget *createWidget() override;
void paint( QPainter *painter ) override;
void canvasMoveEvent( QgsMapMouseEvent *event ) override;
void canvasReleaseEvent( QgsMapMouseEvent *event ) override;
private:
void processParameters();
void drawCircle( QPainter *painter, double x, double y, double distance );
void drawCandidate( QPainter *painter, double x, double y, bool closest );
QPointer<QWidget> mToolWidget;
QToolButton *mCircle1Digitize = nullptr;
QgsDoubleSpinBox *mCircle1X = nullptr;
QgsDoubleSpinBox *mCircle1Y = nullptr;
QgsDoubleSpinBox *mCircle1Distance = nullptr;
QToolButton *mCircle2Digitize = nullptr;
QgsDoubleSpinBox *mCircle2X = nullptr;
QgsDoubleSpinBox *mCircle2Y = nullptr;
QgsDoubleSpinBox *mCircle2Distance = nullptr;
QgsPointXY mP1;
QgsPointXY mP2;
bool mP1Closest = false;
};
#endif
#endif // QGSADVANCEDDIGITIZINGTOOLS

View File

@ -0,0 +1,78 @@
/***************************************************************************
qgsadvanceddigitizingtoolsregistry.cpp
-------------------
begin : July 27 2024
copyright : (C) 2024 by Mathieu Pellerin
email : mathieu at opengis dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsadvanceddigitizingtoolsregistry.h"
#include "qgsadvanceddigitizingtools.h"
#include "qgsapplication.h"
QgsAdvancedDigitizingTool *QgsAdvancedDigitizingToolAbstractMetadata::createTool( QgsMapCanvas *, QgsAdvancedDigitizingDockWidget * )
{
return nullptr;
}
QgsAdvancedDigitizingTool *QgsAdvancedDigitizingToolMetadata::createTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
{
return mToolFunc ? mToolFunc( canvas, cadDockWidget ) : QgsAdvancedDigitizingToolAbstractMetadata::createTool( canvas, cadDockWidget );
}
QgsAdvancedDigitizingToolsRegistry::~QgsAdvancedDigitizingToolsRegistry()
{
qDeleteAll( mTools );
}
void QgsAdvancedDigitizingToolsRegistry::addDefaultTools()
{
addTool( new QgsAdvancedDigitizingToolMetadata( QStringLiteral( "circlesintersection" ),
QObject::tr( "2-Circle Point Intersection" ),
QgsApplication::getThemeIcon( QStringLiteral( "/cadtools/circlesintersection.svg" ) ),
[ = ]( QgsMapCanvas * canvas, QgsAdvancedDigitizingDockWidget * cadDockWidget )->QgsAdvancedDigitizingTool *
{
return new QgsAdvancedDigitizingCirclesIntersectionTool( canvas, cadDockWidget );
} ) );
}
bool QgsAdvancedDigitizingToolsRegistry::addTool( QgsAdvancedDigitizingToolAbstractMetadata *toolMetaData )
{
if ( mTools.contains( toolMetaData->name() ) )
return false;
mTools[toolMetaData->name()] = toolMetaData;
return true;
}
bool QgsAdvancedDigitizingToolsRegistry::removeTool( const QString &name )
{
if ( !mTools.contains( name ) )
return false;
delete mTools.take( name );
return true;
}
QgsAdvancedDigitizingToolAbstractMetadata *QgsAdvancedDigitizingToolsRegistry::toolMetadata( const QString &name )
{
if ( !mTools.contains( name ) )
return nullptr;
return mTools[name];
}
const QStringList QgsAdvancedDigitizingToolsRegistry::toolMetadataNames() const
{
return mTools.keys();
}

View File

@ -0,0 +1,156 @@
/***************************************************************************
qgsadvanceddigitizingtoolsregistry.cpp
-------------------
begin : July 27 2024
copyright : (C) 2024 by Mathieu Pellerin
email : mathieu at opengis dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSADVANCEDDIGITIZINGTOOLSREGSITRY_H
#define QGSADVANCEDDIGITIZINGTOOLSREGSITRY_H
#include "qgis_sip.h"
#include "qgis_gui.h"
#include <QIcon>
#include <QMap>
class QgsAdvancedDigitizingDockWidget;
class QgsAdvancedDigitizingTool;
class QgsMapCanvas;
/**
* \ingroup gui
* \brief Stores metadata about one advanced digitizing tool class.
* \since QGIS 3.40
*/
class GUI_EXPORT QgsAdvancedDigitizingToolAbstractMetadata
{
public:
/**
* Constructor for QgsAdvancedDigitizingToolAbstractMetadata with the specified tool \a name.
*
* \a visibleName should be set to a translated, user visible name identifying the corresponding annotation item.
*
* An optional \a icon can be set, which will be used by the advanced digitizing dock widget.
*/
QgsAdvancedDigitizingToolAbstractMetadata( const QString &name, const QString &visibleName, const QIcon &icon = QIcon() )
: mName( name )
, mVisibleName( visibleName )
, mIcon( icon )
{}
virtual ~QgsAdvancedDigitizingToolAbstractMetadata() = default;
//! Returns the tool's unique name
QString name() const { return mName; }
//! Returns the tool's translatable user-friendly name
QString visibleName() const { return mVisibleName; }
//! Returns the tool's icon
QIcon icon() const { return mIcon; }
//! Returns new tool of this type. Return NULLPTR on error
virtual QgsAdvancedDigitizingTool *createTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ) SIP_FACTORY;
protected:
QString mName;
QString mVisibleName;
QIcon mIcon;
};
#ifndef SIP_RUN
typedef std::function<QgsAdvancedDigitizingTool *( QgsMapCanvas *, QgsAdvancedDigitizingDockWidget * )> QgsAdvancedDigitizingToolFunc SIP_SKIP;
/**
* \ingroup gui
* \brief Convenience metadata class that uses static functions to handle advanced digitizing tool creation
* \note not available in Python bindings
* \since QGIS 3.40
*/
class GUI_EXPORT QgsAdvancedDigitizingToolMetadata : public QgsAdvancedDigitizingToolAbstractMetadata
{
public:
/**
* Constructor for QgsAdvancedDigitizingToolAbstractMetadata with the specified tool \a name.
*
* \a visibleName should be set to a translated, user visible name identifying the corresponding annotation item.
*
* An optional \a icon can be set, which will be used by the advanced digitizing dock widget.
*
* A tool creation function can be declared through the \a toolFunction parameter.
*/
QgsAdvancedDigitizingToolMetadata( const QString &name, const QString &visibleName, const QIcon &icon = QIcon(),
const QgsAdvancedDigitizingToolFunc &toolFunction = nullptr )
: QgsAdvancedDigitizingToolAbstractMetadata( name, visibleName, icon )
, mToolFunc( toolFunction )
{}
//! Returns the tool creation function
QgsAdvancedDigitizingToolFunc toolFunction() const { return mToolFunc; }
//! Sets the tool creation \a function.
void setToolFunction( const QgsAdvancedDigitizingToolFunc &function ) { mToolFunc = function; }
QgsAdvancedDigitizingTool *createTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ) override;
protected:
QgsAdvancedDigitizingToolFunc mToolFunc = nullptr;
};
#endif
/**
* \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
{
public:
QgsAdvancedDigitizingToolsRegistry() = default;
~QgsAdvancedDigitizingToolsRegistry();
QgsAdvancedDigitizingToolsRegistry( const QgsAdvancedDigitizingToolsRegistry &rh ) = delete;
QgsAdvancedDigitizingToolsRegistry &operator=( const QgsAdvancedDigitizingToolsRegistry &rh ) = delete;
//! Adds the default tools shipped in QGIS
void addDefaultTools();
//! Adds an advanced digitizing tool (take ownership) and return TRUE on success
bool addTool( QgsAdvancedDigitizingToolAbstractMetadata *toolMetaData SIP_TRANSFER );
//! Removes the advanced digitizing tool matching the provided \a name and return TRUE on success
bool removeTool( const QString &name );
//! Returns the advanced digitizing tool matching the provided \a name or NULLPTR when no match available
QgsAdvancedDigitizingToolAbstractMetadata *toolMetadata( const QString &name );
//! Returns the list of registered tool names
const QStringList toolMetadataNames() const;
private:
#ifdef SIP_RUN
QgsAdvancedDigitizingToolsRegistry( const QgsAdvancedDigitizingToolsRegistry &rh );
#endif
QMap<QString, QgsAdvancedDigitizingToolAbstractMetadata *> mTools;
};
#endif // QGSADVANCEDDIGITIZINGTOOLSREGSITRY_H

View File

@ -26,6 +26,7 @@
#include "qgssourceselectproviderregistry.h"
#include "qgslayoutitemguiregistry.h"
#include "qgsannotationitemguiregistry.h"
#include "qgsadvanceddigitizingtoolsregistry.h"
#include "qgscalloutsregistry.h"
#include "callouts/qgscalloutwidget.h"
#ifdef Q_OS_MACX
@ -144,6 +145,11 @@ QgsAnnotationItemGuiRegistry *QgsGui::annotationItemGuiRegistry()
return instance()->mAnnotationItemGuiRegistry;
}
QgsAdvancedDigitizingToolsRegistry *QgsGui::advancedDigitizingToolsRegistry()
{
return instance()->mAdvancedDigitizingToolsRegistry;
}
QgsProcessingGuiRegistry *QgsGui::processingGuiRegistry()
{
return instance()->mProcessingGuiRegistry;
@ -243,6 +249,7 @@ QgsGui::~QgsGui()
delete mProcessingRecentAlgorithmLog;
delete mLayoutItemGuiRegistry;
delete mAnnotationItemGuiRegistry;
delete mAdvancedDigitizingToolsRegistry;
delete mLayerTreeEmbeddedWidgetRegistry;
delete mEditorWidgetRegistry;
delete mMapLayerActionRegistry;
@ -352,6 +359,9 @@ QgsGui::QgsGui()
mAnnotationItemGuiRegistry = new QgsAnnotationItemGuiRegistry();
mAnnotationItemGuiRegistry->addDefaultItems();
mAdvancedDigitizingToolsRegistry = new QgsAdvancedDigitizingToolsRegistry();
mAdvancedDigitizingToolsRegistry->addDefaultTools();
mWidgetStateHelper = new QgsWidgetStateHelper();
mProcessingFavoriteAlgorithmManager = new QgsProcessingFavoriteAlgorithmManager();
mProcessingRecentAlgorithmLog = new QgsProcessingRecentAlgorithmLog();

View File

@ -32,6 +32,7 @@ class QgsSourceSelectProviderRegistry;
class QgsNative;
class QgsLayoutItemGuiRegistry;
class QgsAnnotationItemGuiRegistry;
class QgsAdvancedDigitizingToolsRegistry;
class QgsWidgetStateHelper;
class QgsProcessingGuiRegistry;
class QgsProcessingFavoriteAlgorithmManager;
@ -131,6 +132,13 @@ class GUI_EXPORT QgsGui : public QObject
*/
static QgsAnnotationItemGuiRegistry *annotationItemGuiRegistry() SIP_KEEPREFERENCE;
/**
* Returns the global advanced digitizing tools registry, used for registering advanced digitizing tools.
*
* \since QGIS 3.40
*/
static QgsAdvancedDigitizingToolsRegistry *advancedDigitizingToolsRegistry() SIP_KEEPREFERENCE;
/**
* Returns the global processing gui registry, used for registering the GUI behavior of processing algorithms.
* \since QGIS 3.2
@ -334,6 +342,7 @@ class GUI_EXPORT QgsGui : public QObject
QgsMapLayerActionRegistry *mMapLayerActionRegistry = nullptr;
QgsLayoutItemGuiRegistry *mLayoutItemGuiRegistry = nullptr;
QgsAnnotationItemGuiRegistry *mAnnotationItemGuiRegistry = nullptr;
QgsAdvancedDigitizingToolsRegistry *mAdvancedDigitizingToolsRegistry = nullptr;
QgsProcessingGuiRegistry *mProcessingGuiRegistry = nullptr;
QgsProcessingFavoriteAlgorithmManager *mProcessingFavoriteAlgorithmManager = nullptr;
QgsProcessingRecentAlgorithmLog *mProcessingRecentAlgorithmLog = nullptr;

View File

@ -35,10 +35,12 @@ void QgsMapToolAdvancedDigitizing::canvasPressEvent( QgsMapMouseEvent *e )
{
if ( isAdvancedDigitizingAllowed() && mCadDockWidget->cadEnabled() )
{
mCadDockWidget->applyConstraints( e ); // updates event's map point
if ( mCadDockWidget->constructionMode() )
return; // decided to eat the event and not pass it to the map tool (construction mode)
mCadDockWidget->applyConstraints( e ); // updates event's map point
mCadDockWidget->processCanvasPressEvent( e );
if ( !e->isAccepted() )
{
return; // The dock widget has taken the event
}
}
else if ( isAutoSnapEnabled() )
{
@ -64,20 +66,12 @@ void QgsMapToolAdvancedDigitizing::canvasReleaseEvent( QgsMapMouseEvent *e )
}
else
{
mCadDockWidget->applyConstraints( e ); // updates event's map point
if ( mCadDockWidget->alignToSegment( e ) )
mCadDockWidget->applyConstraints( e ); // updates event's map point
mCadDockWidget->processCanvasReleaseEvent( e );
if ( !e->isAccepted() )
{
// Parallel or perpendicular mode and snapped to segment: do not pass the event to map tool
return;
return; // The dock widget has taken the event
}
mCadDockWidget->addPoint( e->mapPoint() );
mCadDockWidget->releaseLocks( false );
if ( mCadDockWidget->constructionMode() )
return; // decided to eat the event and not pass it to the map tool (construction mode)
}
}
else if ( isAutoSnapEnabled() )
@ -98,12 +92,12 @@ void QgsMapToolAdvancedDigitizing::canvasMoveEvent( QgsMapMouseEvent *e )
{
if ( isAdvancedDigitizingAllowed() && mCadDockWidget->cadEnabled() )
{
mCadDockWidget->applyConstraints( e ); // updates event's map point
// perpendicular/parallel constraint
// do a soft lock when snapping to a segment
mCadDockWidget->alignToSegment( e, QgsAdvancedDigitizingDockWidget::CadConstraint::SoftLock );
mCadDockWidget->updateCadPaintItem();
mCadDockWidget->applyConstraints( e ); // updates event's map point
mCadDockWidget->processCanvasMoveEvent( e );
if ( !e->isAccepted() )
{
return; // The dock widget has taken the event
}
}
else if ( isAutoSnapEnabled() )
{

View File

@ -46,12 +46,13 @@
<addaction name="mConstructionModeAction"/>
<addaction name="mParallelAction"/>
<addaction name="mPerpendicularAction"/>
<addaction name="mConstructionAction"/>
<addaction name="separator"/>
<addaction name="mToolsAction"/>
<addaction name="separator"/>
<addaction name="mSettingsAction"/>
<addaction name="separator"/>
<addaction name="mFloaterAction"/>
<addaction name="separator"/>
<addaction name="mConstructionAction"/>
</widget>
</item>
<item>
@ -605,6 +606,15 @@
<string/>
</property>
</action>
<action name="mToolsAction">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/cadtools/circlesintersection.svg</normaloff>:/images/themes/default/cadtools/circlesintersection.svg</iconset>
</property>
</action>
<action name="mSettingsAction">
<property name="icon">
<iconset resource="../../images/images.qrc">

View File

@ -25,6 +25,7 @@ endif()
set(TESTS
testqgsadvanceddigitizingdockwidget.cpp
testqgsadvanceddigitizingtoolsregistry.cpp
testqgsannotationitemguiregistry.cpp
testqgsmaptoolzoom.cpp
testqgsmaptooledit.cpp

View File

@ -0,0 +1,95 @@
/***************************************************************************
testqgsadvanceddigitizingtoolsregistry.cpp
--------------------
Date : July 2024
Copyright : (C) 2024 Mathieu Pellerin
Email : mathieu at opengis dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgstest.h"
#include "qgsadvanceddigitizingtools.h"
#include "qgsadvanceddigitizingtoolsregistry.h"
#include <QSignalSpy>
class TestQgsAdvancedDigitizingToolsRegistry: public QObject
{
Q_OBJECT
private slots:
void initTestCase(); // will be called before the first testfunction is executed.
void cleanupTestCase(); // will be called after the last testfunction was executed.
void init(); // will be called before each testfunction is executed.
void cleanup(); // will be called after every testfunction.
void guiRegistry();
private:
};
void TestQgsAdvancedDigitizingToolsRegistry::initTestCase()
{
}
void TestQgsAdvancedDigitizingToolsRegistry::cleanupTestCase()
{
}
void TestQgsAdvancedDigitizingToolsRegistry::init()
{
}
void TestQgsAdvancedDigitizingToolsRegistry::cleanup()
{
}
class DummyAdvancedDigitizingTool : public QgsAdvancedDigitizingTool
{
Q_OBJECT
public:
DummyAdvancedDigitizingTool()
: QgsAdvancedDigitizingTool( nullptr, nullptr )
{}
};
void TestQgsAdvancedDigitizingToolsRegistry::guiRegistry()
{
// test QgsAnnotationItemGuiRegistry
QgsAdvancedDigitizingToolsRegistry registry;
// empty registry
QVERIFY( !registry.toolMetadata( QString( "empty" ) ) );
QVERIFY( registry.toolMetadataNames().isEmpty() );
auto createTool = []( QgsMapCanvas *, QgsAdvancedDigitizingDockWidget * )->QgsAdvancedDigitizingTool *
{
return new DummyAdvancedDigitizingTool();
};
QgsAdvancedDigitizingToolMetadata *metadata = new QgsAdvancedDigitizingToolMetadata( QStringLiteral( "dummy" ), QStringLiteral( "My Dummy Tool" ), QIcon(), createTool );
QVERIFY( registry.addTool( metadata ) );
const QString name = registry.toolMetadataNames().value( 0 );
QCOMPARE( name, QStringLiteral( "dummy" ) );
// duplicate name not allowed
metadata = new QgsAdvancedDigitizingToolMetadata( QStringLiteral( "dummy" ), QStringLiteral( "My Dummy Tool" ), QIcon(), createTool );
QVERIFY( !registry.addTool( metadata ) );
QVERIFY( registry.toolMetadata( name ) );
QCOMPARE( registry.toolMetadata( name )->visibleName(), QStringLiteral( "My Dummy Tool" ) );
QgsAdvancedDigitizingTool *tool = registry.toolMetadata( name )->createTool( nullptr, nullptr );
QVERIFY( tool );
registry.removeTool( name );
QVERIFY( registry.toolMetadataNames().isEmpty() );
}
QGSTEST_MAIN( TestQgsAdvancedDigitizingToolsRegistry )
#include "testqgsadvanceddigitizingtoolsregistry.moc"