Use a tri state button to configure snapping limit : disable, global and per layer.

This commit is contained in:
obrix 2020-03-30 17:32:24 +02:00
parent b3e96ff26a
commit 03c522a957
7 changed files with 136 additions and 54 deletions

View File

@ -51,6 +51,13 @@ This is a container for configuration of the snapping of the project
typedef QFlags<QgsSnappingConfig::SnappingTypes> SnappingTypeFlag;
enum ScaleDependencyMode
{
Disabled,
ScaleDependentGlobal,
ScaleDependentPerLayer
};
static const QString snappingTypeFlagToString( SnappingTypeFlag type );
%Docstring
Convenient method to returns the translated name of the enum type
@ -154,42 +161,59 @@ define the type of snapping
double tolerance() const;
%Docstring
!
Returns the tolerance
.. versionadded:: 3.12
%End
void setTolerance( double tolerance );
%Docstring
Sets the tolerance
.. versionadded:: 3.12
%End
QgsTolerance::UnitType units() const;
%Docstring
Returns the type of units
.. versionadded:: 3.12
%End
void setUnits( QgsTolerance::UnitType units );
%Docstring
Sets the type of units
.. versionadded:: 3.12
%End
double minScale() const;
%Docstring
Returns min scale on which snapping is limited
.. versionadded:: 3.14
%End
void setMinScale( double p_minScale );
%Docstring
Sets the min scale value on which snapping is used, 0.0 disable scale limit
.. versionadded:: 3.14
%End
double maxScale() const;
%Docstring
Returns max scale on which snapping is limite
Returns max scale on which snapping is limited
.. versionadded:: 3.14
%End
void setMaxScale( double p_maxScale );
%Docstring
Sets the max scale value on which snapping is used, 0.0 disable scale limit
.. versionadded:: 3.14
%End
bool operator!= ( const QgsSnappingConfig::IndividualLayerSettings &other ) const;
@ -273,31 +297,43 @@ Sets the tolerance
double minScale() const;
%Docstring
Returns the min scale
.. versionadded:: 3.14
%End
void setMinScale( double pMinScale );
%Docstring
Sets the min scale on which snapping is enabled, 0.0 disable scale limit
.. versionadded:: 3.14
%End
double maxScale() const;
%Docstring
Returns the max scale
.. versionadded:: 3.14
%End
void setMaxScale( double pMaxScale );
%Docstring
Set the max scale on which snapping is enabled, 0.0 disable scale limit
.. versionadded:: 3.14
%End
bool limitToScale() const;
void setScaleDependencyMode( ScaleDependencyMode mode );
%Docstring
Returns limit to scale
Set the scale dependency mode
.. versionadded:: 3.14
%End
void setLimitToScale( bool pLimitSnapping );
ScaleDependencyMode scaleDependencyMode() const;
%Docstring
Set limit to scale, true means snapping will be limited to the [minScale, maxScale] range
Returns the scale dependency mode
.. versionadded:: 3.14
%End
QgsTolerance::UnitType units() const;

View File

@ -238,7 +238,7 @@ QgsSnappingLayerTreeModel::QgsSnappingLayerTreeModel( QgsProject *project, QgsMa
, mProject( project )
, mCanvas( canvas )
, mIndividualLayerSettings( project->snappingConfig().individualLayerSettings() )
, mEnableMinMaxColumn( project->snappingConfig().limitToScale() )
, mEnableMinMaxColumn( project->snappingConfig().scaleDependencyMode() == QgsSnappingConfig::ScaleDependentPerLayer )
{
connect( project, &QgsProject::snappingConfigChanged, this, &QgsSnappingLayerTreeModel::onSnappingSettingsChanged );
@ -369,7 +369,7 @@ void QgsSnappingLayerTreeModel::onSnappingSettingsChanged()
}
}
mEnableMinMaxColumn = mProject->snappingConfig().limitToScale();
mEnableMinMaxColumn = ( mProject->snappingConfig().scaleDependencyMode() == QgsSnappingConfig::ScaleDependentPerLayer );
hasRowchanged( mLayerTreeModel->rootGroup(), oldSettings, wasMinMaxEnabled != mEnableMinMaxColumn );
}

View File

@ -186,11 +186,23 @@ QgsSnappingWidget::QgsSnappingWidget( QgsProject *project, QgsMapCanvas *canvas,
connect( mMaxScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsSnappingWidget::changeMaxScale );
mLimitToScale = new QAction( tr( "Toggle scale dependent snapping" ), this );
mLimitToScale->setCheckable( true );
mLimitToScale->setIcon( QIcon( QgsApplication::getThemeIcon( "/mIconSnappingOnScale.svg" ) ) );
mLimitToScale->setObjectName( QStringLiteral( "EnableSnappingLimitOnScaleAction" ) );
connect( mLimitToScale, &QAction::toggled, this, &QgsSnappingWidget::changeLimitToScale );
mSnappingScaleModeButton = new QToolButton();
mSnappingScaleModeButton->setToolTip( tr( "Snapping scale mode" ) );
mSnappingScaleModeButton->setPopupMode( QToolButton::InstantPopup );
QMenu *scaleModeMenu = new QMenu( tr( "Set snapping scale mode" ), this );
mDefaultSnappingScaleAct = new QAction( QIcon( QgsApplication::getThemeIcon( "/mIconSnappingOnScale.svg" ) ), tr( "Disabled" ), scaleModeMenu );
mDefaultSnappingScaleAct->setToolTip( tr( "Scale dependency disabled" ) );
mGlobalSnappingScaleAct = new QAction( QIcon( QgsApplication::getThemeIcon( "/mIconSnappingOnScale.svg" ) ), tr( "Global" ), scaleModeMenu );
mGlobalSnappingScaleAct->setToolTip( tr( "Scale dependency global" ) );
mPerLayerSnappingScaleAct = new QAction( QIcon( QgsApplication::getThemeIcon( "/mIconSnappingOnScale.svg" ) ), tr( "Per layer" ), scaleModeMenu );
mPerLayerSnappingScaleAct->setToolTip( tr( "Scale dependency per layer" ) );
scaleModeMenu->addAction( mDefaultSnappingScaleAct );
scaleModeMenu->addAction( mGlobalSnappingScaleAct );
scaleModeMenu->addAction( mPerLayerSnappingScaleAct );
mSnappingScaleModeButton->setMenu( scaleModeMenu );
mSnappingScaleModeButton->setObjectName( QStringLiteral( "SnappingScaleModeButton" ) );
mSnappingScaleModeButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
connect( mSnappingScaleModeButton, &QToolButton::triggered, this, &QgsSnappingWidget::snappingScaleModeTriggered );
// units
mUnitsComboBox = new QComboBox();
@ -299,10 +311,8 @@ QgsSnappingWidget::QgsSnappingWidget( QgsProject *project, QgsMapCanvas *canvas,
layout->addWidget( mTypeButton );
layout->addWidget( mToleranceSpinBox );
layout->addWidget( mUnitsComboBox );
QToolButton *limitToScaleButton = new QToolButton();
limitToScaleButton->addAction( mLimitToScale );
limitToScaleButton->setDefaultAction( mLimitToScale );
layout->addWidget( limitToScaleButton );
mSnappingScaleModeButton->setDefaultAction( mDefaultSnappingScaleAct );
layout->addWidget( mSnappingScaleModeButton );
layout->addWidget( mMinScaleWidget );
layout->addWidget( mMaxScaleWidget );
@ -437,7 +447,18 @@ void QgsSnappingWidget::projectSnapSettingsChanged()
mMaxScaleWidget->setScale( config.maxScale() );
}
mLimitToScale->setChecked( config.limitToScale() );
if ( config.scaleDependencyMode() == QgsSnappingConfig::Disabled )
{
mSnappingScaleModeButton->setDefaultAction( mDefaultSnappingScaleAct );
}
else if ( config.scaleDependencyMode() == QgsSnappingConfig::ScaleDependentGlobal )
{
mSnappingScaleModeButton->setDefaultAction( mGlobalSnappingScaleAct );
}
else if ( config.scaleDependencyMode() == QgsSnappingConfig::ScaleDependentPerLayer )
{
mSnappingScaleModeButton->setDefaultAction( mPerLayerSnappingScaleAct );
}
if ( config.intersectionSnapping() != mIntersectionSnappingAction->isChecked() )
{
@ -468,9 +489,9 @@ void QgsSnappingWidget::toggleSnappingWidgets( bool enabled )
mModeButton->setEnabled( enabled );
mTypeButton->setEnabled( enabled );
mToleranceSpinBox->setEnabled( enabled );
mLimitToScale->setEnabled( enabled );
mMinScaleWidget->setEnabled( enabled && mConfig.limitToScale() );
mMaxScaleWidget->setEnabled( enabled && mConfig.limitToScale() );
mSnappingScaleModeButton->setEnabled( enabled );
mMinScaleWidget->setEnabled( enabled && mConfig.scaleDependencyMode() == QgsSnappingConfig::ScaleDependentGlobal );
mMaxScaleWidget->setEnabled( enabled && mConfig.scaleDependencyMode() == QgsSnappingConfig::ScaleDependentGlobal );
mUnitsComboBox->setEnabled( enabled );
if ( mEditAdvancedConfigAction )
@ -504,14 +525,6 @@ void QgsSnappingWidget::changeMaxScale( double pMaxScale )
mProject->setSnappingConfig( mConfig );
}
void QgsSnappingWidget::changeLimitToScale( bool enabled )
{
mConfig.setLimitToScale( enabled );
mMinScaleWidget->setEnabled( mConfig.limitToScale() );
mMaxScaleWidget->setEnabled( mConfig.limitToScale() );
mProject->setSnappingConfig( mConfig );
}
void QgsSnappingWidget::changeUnit( int idx )
{
QgsTolerance::UnitType unit = static_cast<QgsTolerance::UnitType>( mUnitsComboBox->itemData( idx ).toInt() );
@ -597,6 +610,29 @@ void QgsSnappingWidget::typeButtonTriggered( QAction *action )
mProject->setSnappingConfig( mConfig );
}
void QgsSnappingWidget::snappingScaleModeTriggered( QAction *action )
{
mSnappingScaleModeButton->setDefaultAction( action );
QgsSnappingConfig::ScaleDependencyMode mode;
if ( action == mDefaultSnappingScaleAct )
{
mode = QgsSnappingConfig::Disabled;
}
else if ( action == mGlobalSnappingScaleAct )
{
mode = QgsSnappingConfig::ScaleDependentGlobal;
}
else if ( action == mPerLayerSnappingScaleAct )
{
mode = QgsSnappingConfig::ScaleDependentPerLayer;
}
mMinScaleWidget->setEnabled( mode == QgsSnappingConfig::ScaleDependentGlobal );
mMaxScaleWidget->setEnabled( mode == QgsSnappingConfig::ScaleDependentGlobal );
mConfig.setScaleDependencyMode( mode );
mProject->setSnappingConfig( mConfig );
}
void QgsSnappingWidget::updateToleranceDecimals()
{
if ( mConfig.units() == QgsTolerance::Pixels )
@ -638,9 +674,9 @@ void QgsSnappingWidget::modeChanged()
{
mAdvancedConfigWidget->setVisible( advanced );
}
mSnappingScaleModeButton->setVisible( advanced );
mMinScaleWidget->setVisible( advanced );
mMaxScaleWidget->setVisible( advanced );
mLimitToScale->setVisible( advanced );
}
}

View File

@ -106,8 +106,6 @@ class APP_EXPORT QgsSnappingWidget : public QWidget
void changeMaxScale( double pMaxScale );
void changeLimitToScale( bool enabled );
void changeUnit( int idx );
void enableTopologicalEditing( bool enabled );
@ -116,6 +114,7 @@ class APP_EXPORT QgsSnappingWidget : public QWidget
void modeButtonTriggered( QAction *action );
void typeButtonTriggered( QAction *action );
void snappingScaleModeTriggered( QAction *action );
//! number of decimals of the tolerance spin box depends on map units
void updateToleranceDecimals();
@ -152,11 +151,13 @@ class APP_EXPORT QgsSnappingWidget : public QWidget
QAction *mCentroidAction = nullptr;
QAction *mMiddleAction = nullptr;
QDoubleSpinBox *mToleranceSpinBox = nullptr;
QAction *mLimitToScale = nullptr;
QgsScaleWidget *mMinScaleWidget = nullptr;
QgsScaleWidget *mMaxScaleWidget = nullptr;
QAction *mToleranceAction = nullptr; // hide widget does not work on toolbar, action needed
QAction *mLimitToScaleAction = nullptr;
QToolButton *mSnappingScaleModeButton = nullptr;
QAction *mDefaultSnappingScaleAct = nullptr;
QAction *mGlobalSnappingScaleAct = nullptr;
QAction *mPerLayerSnappingScaleAct = nullptr;
QComboBox *mUnitsComboBox = nullptr;
QAction *mUnitAction = nullptr; // hide widget does not work on toolbar, action needed
QAction *mTopologicalEditingAction = nullptr;

View File

@ -180,7 +180,7 @@ bool QgsSnappingConfig::operator==( const QgsSnappingConfig &other ) const
&& mUnits == other.mUnits
&& mIntersectionSnapping == other.mIntersectionSnapping
&& mIndividualLayerSettings == other.mIndividualLayerSettings
&& mLimitToScale == other.mLimitToScale
&& mScaleDependencyMode == other.mScaleDependencyMode
&& mMinScale == other.mMinScale
&& mMaxScale == other.mMaxScale;
}
@ -205,7 +205,7 @@ void QgsSnappingConfig::reset()
mMode = mode;
mType = type;
mTolerance = tolerance;
mLimitToScale = false;
mScaleDependencyMode = Disabled;
mMinScale = 0.0;
mMaxScale = 0.0;
// do not allow unit to be "layer" if not in advanced configuration
@ -378,7 +378,7 @@ bool QgsSnappingConfig::operator!=( const QgsSnappingConfig &other ) const
|| mTolerance != other.mTolerance
|| mUnits != other.mUnits
|| mIndividualLayerSettings != other.mIndividualLayerSettings
|| mLimitToScale != other.mLimitToScale
|| mScaleDependencyMode != other.mScaleDependencyMode
|| mMinScale != other.mMinScale
|| mMaxScale != other.mMaxScale;
}
@ -444,8 +444,8 @@ void QgsSnappingConfig::readProject( const QDomDocument &doc )
if ( snapSettingsElem.hasAttribute( QStringLiteral( "tolerance" ) ) )
mTolerance = snapSettingsElem.attribute( QStringLiteral( "tolerance" ) ).toDouble();
if ( snapSettingsElem.hasAttribute( QStringLiteral( "limitToScale" ) ) )
mLimitToScale = snapSettingsElem.attribute( QStringLiteral( "limitToScale" ) ) == QLatin1String( "1" );
if ( snapSettingsElem.hasAttribute( QStringLiteral( "scaleDependencyMode" ) ) )
mScaleDependencyMode = static_cast<QgsSnappingConfig::ScaleDependencyMode>( snapSettingsElem.attribute( QStringLiteral( "scaleDependencyMode" ) ).toInt() );
if ( snapSettingsElem.hasAttribute( QStringLiteral( "minScale" ) ) )
mMinScale = snapSettingsElem.attribute( QStringLiteral( "minScale" ) ).toDouble();
@ -504,7 +504,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( "limitToScale" ), QString::number( mLimitToScale ) );
snapSettingsElem.setAttribute( QStringLiteral( "scaleDependencyMode" ), QString::number( mScaleDependencyMode ) );
snapSettingsElem.setAttribute( QStringLiteral( "minScale" ), mMinScale );
snapSettingsElem.setAttribute( QStringLiteral( "maxScale" ), mMaxScale );
@ -668,16 +668,17 @@ void QgsSnappingConfig::setMaxScale( double pMaxScale )
mMaxScale = pMaxScale;
}
bool QgsSnappingConfig::limitToScale() const
void QgsSnappingConfig::setScaleDependencyMode( QgsSnappingConfig::ScaleDependencyMode mode )
{
return mLimitToScale;
mScaleDependencyMode = mode;
}
void QgsSnappingConfig::setLimitToScale( bool pLimitSnapping )
QgsSnappingConfig::ScaleDependencyMode QgsSnappingConfig::scaleDependencyMode() const
{
mLimitToScale = pLimitSnapping;
return mScaleDependencyMode;
}

View File

@ -80,6 +80,13 @@ class CORE_EXPORT QgsSnappingConfig
Q_DECLARE_FLAGS( SnappingTypeFlag, SnappingTypes )
Q_FLAG( SnappingTypeFlag )
enum ScaleDependencyMode
{
Disabled = 0,
ScaleDependentGlobal,
ScaleDependentPerLayer
};
/**
* Convenient method to returns the translated name of the enum type
* QgsSnappingConfig::SnappingTypeFlag
@ -172,7 +179,8 @@ class CORE_EXPORT QgsSnappingConfig
*/
void setTypeFlag( QgsSnappingConfig::SnappingTypeFlag type );
/**!
/**
* !
* Returns the tolerance
* \since QGIS 3.12
*/
@ -314,16 +322,16 @@ class CORE_EXPORT QgsSnappingConfig
void setMaxScale( double pMaxScale );
/**
* Returns limit to scale
* Set the scale dependency mode
* \since QGIS 3.14
*/
bool limitToScale() const;
void setScaleDependencyMode( ScaleDependencyMode mode );
/**
* Set limit to scale, true means snapping will be limited to the [minScale, maxScale] range
* Returns the scale dependency mode
* \since QGIS 3.14
*/
void setLimitToScale( bool pLimitSnapping );
ScaleDependencyMode scaleDependencyMode() const;
//! Returns the type of units
QgsTolerance::UnitType units() const;
@ -455,7 +463,7 @@ class CORE_EXPORT QgsSnappingConfig
SnappingMode mMode = ActiveLayer;
SnappingTypeFlag mType = VertexFlag;
double mTolerance = 0.0;
bool mLimitToScale = false;
ScaleDependencyMode mScaleDependencyMode = Disabled;
double mMinScale = 0.0;
double mMaxScale = 0.0;
QgsTolerance::UnitType mUnits = QgsTolerance::ProjectUnits;

View File

@ -297,17 +297,17 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPointXY &pointMap,
bool inRangeGlobal = ( mSnappingConfig.minScale() <= 0.0 || mMapSettings.scale() >= mSnappingConfig.minScale() )
&& ( mSnappingConfig.maxScale() <= 0.0 || mMapSettings.scale() <= mSnappingConfig.maxScale() );
for ( const LayerConfig &layerConfig : qgis::as_const( mLayers ))
for ( const LayerConfig &layerConfig : qgis::as_const( mLayers ) )
{
QgsSnappingConfig::IndividualLayerSettings layerSettings = mSnappingConfig.individualLayerSettings( layerConfig.layer );
//Default value for layer config means it is not set ( appears NULL ) layerSpecificRange <- false
bool layerSpecificRange = layerSettings.minScale() > 0.0 || layerSettings.maxScale() > 0.0;
bool inRangeLayer = ( layerSettings.minScale() < 0.0 || mMapSettings.scale() >= layerSettings.minScale() ) && ( layerSettings.maxScale() < 0.0 || mMapSettings.scale() <= layerSettings.maxScale() );
bool inRangeLayer = ( layerSettings.minScale() <= 0.0 || mMapSettings.scale() >= layerSettings.minScale() ) && ( layerSettings.maxScale() <= 0.0 || mMapSettings.scale() <= layerSettings.maxScale() );
//If limit to scale is disabled, snapping activated on all layer
//If no per layer config is set use the global one, otherwise use the layer config
if ( !mSnappingConfig.limitToScale() || ( ( !layerSpecificRange && inRangeGlobal ) || ( layerSpecificRange && inRangeLayer ) ) )
if ( mSnappingConfig.scaleDependencyMode() == QgsSnappingConfig::Disabled
|| ( mSnappingConfig.scaleDependencyMode() == QgsSnappingConfig::ScaleDependentGlobal && inRangeGlobal )
|| ( mSnappingConfig.scaleDependencyMode() == QgsSnappingConfig::ScaleDependentPerLayer && inRangeLayer ) )
{
double tolerance = QgsTolerance::toleranceInProjectUnits( layerConfig.tolerance, layerConfig.layer, mMapSettings, layerConfig.unit );
layers << qMakePair( layerConfig.layer, _areaOfInterest( pointMap, tolerance ) );