Skip to content

Commit

Permalink
[feature][selfsnap] add snapping to currently digitized feature for c…
Browse files Browse the repository at this point in the history
…apture tool
  • Loading branch information
olivierdalang committed May 21, 2020
1 parent d48c178 commit 66ebe34
Show file tree
Hide file tree
Showing 15 changed files with 495 additions and 5 deletions.
1 change: 1 addition & 0 deletions images/images.qrc
Expand Up @@ -700,6 +700,7 @@
<file>themes/default/mIconSnappingMiddle.svg</file>
<file>themes/default/mIconSnappingOnScale.svg</file>
<file>themes/default/mIconSnappingVertex.svg</file>
<file>themes/default/mIconSnappingSelf.svg</file>
<file>themes/default/mIconSnappingSegment.svg</file>
<file>themes/default/mIconTopologicalEditing.svg</file>
<file>themes/default/mIconSnappingIntersection.svg</file>
Expand Down
141 changes: 141 additions & 0 deletions images/themes/default/mIconSnappingSelf.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions python/core/auto_generated/qgscadutils.sip.in
Expand Up @@ -53,6 +53,8 @@ The QgsCadUtils class provides routines for CAD editing.

QgsPointXY finalMapPoint;

QgsPointLocator::Match snapMatch;

QgsPointLocator::Match edgeMatch;

double softLockCommonAngle;
Expand Down
14 changes: 14 additions & 0 deletions python/core/auto_generated/qgssnappingconfig.sip.in
Expand Up @@ -343,6 +343,20 @@ Returns if the snapping on intersection is enabled
void setIntersectionSnapping( bool enabled );
%Docstring
Sets if the snapping on intersection is enabled
%End

bool selfSnapping() const;
%Docstring
Returns if self snapping (snapping to the currently digitised feature) is enabled

.. versionadded:: 3.14
%End

void setSelfSnapping( bool enabled );
%Docstring
Sets if self snapping (snapping to the currently digitised feature) is enabled

.. versionadded:: 3.14
%End

SIP_PYDICT individualLayerSettings() const;
Expand Down
36 changes: 36 additions & 0 deletions python/core/auto_generated/qgssnappingutils.sip.in
Expand Up @@ -166,6 +166,42 @@ Set if invisible features must be snapped or not.
.. versionadded:: 3.2
%End

void addExtraSnapLayer( QgsVectorLayer *vl );
%Docstring
Supply an extra snapping layer (typically a memory layer).
This is can be used by map tools to provide additionnal
snappings points.

.. seealso:: :py:func:`removeExtraSnapLayer`

.. seealso:: :py:func:`getExtraSnapLayers`

.. versionadded:: 3.14
%End

void removeExtraSnapLayer( QgsVectorLayer *vl );
%Docstring
Removes an extra snapping layer

.. seealso:: :py:func:`addExtraSnapLayer`

.. seealso:: :py:func:`getExtraSnapLayers`

.. versionadded:: 3.14
%End

QSet<QgsVectorLayer *> getExtraSnapLayers();
%Docstring
Returns the list of extra snapping layers

.. seealso:: :py:func:`addExtraSnapLayer`

.. seealso:: :py:func:`removeExtraSnapLayer`

.. versionadded:: 3.14
%End


public slots:

void setConfig( const QgsSnappingConfig &snappingConfig );
Expand Down
27 changes: 27 additions & 0 deletions src/app/qgssnappingwidget.cpp
Expand Up @@ -287,6 +287,14 @@ QgsSnappingWidget::QgsSnappingWidget( QgsProject *project, QgsMapCanvas *canvas,
tracingMenu->addAction( widgetAction );
mEnableTracingAction->setMenu( tracingMenu );

// self-snapping button
mSelfSnappingAction = new QAction( tr( "Self-snapping" ), this );
mSelfSnappingAction->setCheckable( true );
mSelfSnappingAction->setIcon( QIcon( QgsApplication::getThemeIcon( "/mIconSnappingSelf.svg" ) ) );
mSelfSnappingAction->setToolTip( tr( "Enable Self-snapping" ) );
mSelfSnappingAction->setObjectName( QStringLiteral( "SelfSnappingAction" ) );
connect( mSelfSnappingAction, &QAction::toggled, this, &QgsSnappingWidget::enableSelfSnapping );

// layout
if ( mDisplayMode == ToolBar )
{
Expand Down Expand Up @@ -316,6 +324,7 @@ QgsSnappingWidget::QgsSnappingWidget( QgsProject *project, QgsMapCanvas *canvas,
mAvoidIntersectionsModeAction = tb->addWidget( mAvoidIntersectionsModeButton );
tb->addAction( mIntersectionSnappingAction );
tb->addAction( mEnableTracingAction );
tb->addAction( mSelfSnappingAction );
}
else
{
Expand Down Expand Up @@ -350,6 +359,12 @@ QgsSnappingWidget::QgsSnappingWidget( QgsProject *project, QgsMapCanvas *canvas,
interButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
layout->addWidget( interButton );

QToolButton *selfsnapButton = new QToolButton();
selfsnapButton->addAction( mSelfSnappingAction );
selfsnapButton->setDefaultAction( mSelfSnappingAction );
selfsnapButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
layout->addWidget( selfsnapButton );

layout->setContentsMargins( 0, 0, 0, 0 );
layout->setAlignment( Qt::AlignRight );
layout->setSpacing( mDisplayMode == Widget ? 3 : 0 );
Expand Down Expand Up @@ -488,6 +503,11 @@ void QgsSnappingWidget::projectSnapSettingsChanged()
mIntersectionSnappingAction->setChecked( config.intersectionSnapping() );
}

if ( config.selfSnapping() != mSelfSnappingAction->isChecked() )
{
mSelfSnappingAction->setChecked( config.selfSnapping() );
}

toggleSnappingWidgets( config.enabled() );

}
Expand Down Expand Up @@ -552,6 +572,7 @@ void QgsSnappingWidget::toggleSnappingWidgets( bool enabled )
mAdvancedConfigWidget->setEnabled( enabled );
}
mIntersectionSnappingAction->setEnabled( enabled );
mSelfSnappingAction->setEnabled( enabled );
mEnableTracingAction->setEnabled( enabled );
}

Expand Down Expand Up @@ -593,6 +614,12 @@ void QgsSnappingWidget::enableIntersectionSnapping( bool enabled )
mProject->setSnappingConfig( mConfig );
}

void QgsSnappingWidget::enableSelfSnapping( bool enabled )
{
mConfig.setSelfSnapping( enabled );
mProject->setSnappingConfig( mConfig );
}

void QgsSnappingWidget::onSnappingTreeLayersChanged()
{
mLayerTreeView->expandAll();
Expand Down
3 changes: 3 additions & 0 deletions src/app/qgssnappingwidget.h
Expand Up @@ -114,6 +114,8 @@ class APP_EXPORT QgsSnappingWidget : public QWidget

void enableIntersectionSnapping( bool enabled );

void enableSelfSnapping( bool enabled );

void modeButtonTriggered( QAction *action );
void avoidIntersectionsModeButtonTriggered( QAction *action );
void typeButtonTriggered( QAction *action );
Expand Down Expand Up @@ -172,6 +174,7 @@ class APP_EXPORT QgsSnappingWidget : public QWidget
QAction *mIntersectionSnappingAction = nullptr;
QAction *mEnableTracingAction = nullptr;
QgsDoubleSpinBox *mTracingOffsetSpinBox = nullptr;
QAction *mSelfSnappingAction = nullptr;
QTreeView *mLayerTreeView = nullptr;
QWidget *mAdvancedConfigWidget = nullptr;
QgsFloatingWidget *mAdvancedConfigContainer = nullptr;
Expand Down
16 changes: 16 additions & 0 deletions src/core/qgssnappingconfig.cpp
Expand Up @@ -179,6 +179,7 @@ bool QgsSnappingConfig::operator==( const QgsSnappingConfig &other ) const
&& mTolerance == other.mTolerance
&& mUnits == other.mUnits
&& mIntersectionSnapping == other.mIntersectionSnapping
&& mSelfSnapping == other.mSelfSnapping
&& mIndividualLayerSettings == other.mIndividualLayerSettings
&& mScaleDependencyMode == other.mScaleDependencyMode
&& mMinimumScale == other.mMinimumScale
Expand Down Expand Up @@ -218,6 +219,7 @@ void QgsSnappingConfig::reset()
mUnits = units;
}
mIntersectionSnapping = false;
mSelfSnapping = false;

// set advanced config
if ( mProject )
Expand Down Expand Up @@ -343,6 +345,16 @@ void QgsSnappingConfig::setIntersectionSnapping( bool enabled )
mIntersectionSnapping = enabled;
}

bool QgsSnappingConfig::selfSnapping() const
{
return mSelfSnapping;
}

void QgsSnappingConfig::setSelfSnapping( bool enabled )
{
mSelfSnapping = enabled;
}

QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings> QgsSnappingConfig::individualLayerSettings() const
{
return mIndividualLayerSettings;
Expand Down Expand Up @@ -459,6 +471,9 @@ void QgsSnappingConfig::readProject( const QDomDocument &doc )
if ( snapSettingsElem.hasAttribute( QStringLiteral( "intersection-snapping" ) ) )
mIntersectionSnapping = snapSettingsElem.attribute( QStringLiteral( "intersection-snapping" ) ) == QLatin1String( "1" );

if ( snapSettingsElem.hasAttribute( QStringLiteral( "self-snapping" ) ) )
mSelfSnapping = snapSettingsElem.attribute( QStringLiteral( "self-snapping" ) ) == QLatin1String( "1" );

// do not clear the settings as they must be automatically synchronized with current layers
QDomNodeList nodes = snapSettingsElem.elementsByTagName( QStringLiteral( "individual-layer-settings" ) );
if ( nodes.count() )
Expand Down Expand Up @@ -504,6 +519,7 @@ void QgsSnappingConfig::writeProject( QDomDocument &doc )
snapSettingsElem.setAttribute( QStringLiteral( "tolerance" ), mTolerance );
snapSettingsElem.setAttribute( QStringLiteral( "unit" ), static_cast<int>( mUnits ) );
snapSettingsElem.setAttribute( QStringLiteral( "intersection-snapping" ), QString::number( mIntersectionSnapping ) );
snapSettingsElem.setAttribute( QStringLiteral( "self-snapping" ), QString::number( mSelfSnapping ) );
snapSettingsElem.setAttribute( QStringLiteral( "scaleDependencyMode" ), QString::number( mScaleDependencyMode ) );
snapSettingsElem.setAttribute( QStringLiteral( "minScale" ), mMinimumScale );
snapSettingsElem.setAttribute( QStringLiteral( "maxScale" ), mMaximumScale );
Expand Down
15 changes: 15 additions & 0 deletions src/core/qgssnappingconfig.h
Expand Up @@ -335,6 +335,20 @@ class CORE_EXPORT QgsSnappingConfig
//! Sets if the snapping on intersection is enabled
void setIntersectionSnapping( bool enabled );

/**
* Returns if self snapping (snapping to the currently digitised feature) is enabled
*
* \since QGIS 3.14
*/
bool selfSnapping() const;

/**
* Sets if self snapping (snapping to the currently digitised feature) is enabled
*
* \since QGIS 3.14
*/
void setSelfSnapping( bool enabled );

//! Returns individual snapping settings for all layers
#ifndef SIP_RUN
QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings> individualLayerSettings() const;
Expand Down Expand Up @@ -458,6 +472,7 @@ class CORE_EXPORT QgsSnappingConfig
double mMaximumScale = 0.0;
QgsTolerance::UnitType mUnits = QgsTolerance::ProjectUnits;
bool mIntersectionSnapping = false;
bool mSelfSnapping = false;

QHash<QgsVectorLayer *, IndividualLayerSettings> mIndividualLayerSettings;

Expand Down

0 comments on commit 66ebe34

Please sign in to comment.