27#include <QRegularExpression>
30#include "moc_qgssnappingconfig.cpp"
32using namespace Qt::StringLiterals;
40 , mMinimumScale( minScale )
41 , mMaximumScale( maxScale )
132 return mMinimumScale;
137 mMinimumScale = minScale;
142 return mMaximumScale;
147 mMaximumScale = maxScale;
152 return mValid != other.mValid
153 || mEnabled != other.mEnabled
154 || mType != other.mType
155 || mTolerance != other.mTolerance
156 || mUnits != other.mUnits
157 || mMinimumScale != other.mMinimumScale
158 || mMaximumScale != other.mMaximumScale;
163 return mValid == other.mValid
164 && mEnabled == other.mEnabled
165 && mType == other.mType
166 && mTolerance == other.mTolerance
167 && mUnits == other.mUnits
168 && mMinimumScale == other.mMinimumScale
169 && mMaximumScale == other.mMaximumScale;
181 return mEnabled == other.mEnabled
182 && mMode == other.mMode
183 && mType == other.mType
184 && mTolerance == other.mTolerance
185 && mUnits == other.mUnits
186 && mIntersectionSnapping == other.mIntersectionSnapping
187 && mSelfSnapping == other.mSelfSnapping
188 && mIndividualLayerSettings == other.mIndividualLayerSettings
189 && mScaleDependencyMode == other.mScaleDependencyMode
190 && mMinimumScale == other.mMinimumScale
191 && mMaximumScale == other.mMaximumScale;
220 mIntersectionSnapping =
false;
221 mSelfSnapping =
false;
226 mIndividualLayerSettings = QHash<QgsVectorLayer *, IndividualLayerSettings>();
227 const auto constMapLayers = mProject->mapLayers();
287 return QObject::tr(
"No Snapping" );
289 return QObject::tr(
"Vertex" );
291 return QObject::tr(
"Segment" );
293 return QObject::tr(
"Area" );
295 return QObject::tr(
"Centroid" );
297 return QObject::tr(
"Middle of Segments" );
299 return QObject::tr(
"Line Endpoints" );
374 if ( mUnits ==
units )
383 return mIntersectionSnapping;
388 mIntersectionSnapping =
enabled;
393 return mSelfSnapping;
403 return mIndividualLayerSettings;
408 if ( vl && mIndividualLayerSettings.contains( vl ) )
410 return mIndividualLayerSettings.value( vl );
421 mIndividualLayerSettings.clear();
435 return mEnabled != other.mEnabled
436 || mMode != other.mMode
437 || mType != other.mType
438 || mTolerance != other.mTolerance
439 || mUnits != other.mUnits
440 || mIndividualLayerSettings != other.mIndividualLayerSettings
441 || mScaleDependencyMode != other.mScaleDependencyMode
442 || mMinimumScale != other.mMinimumScale
443 || mMaximumScale != other.mMaximumScale;
448 const QDomElement snapSettingsElem = doc.firstChildElement( u
"qgis"_s ).firstChildElement( u
"snapping-settings"_s );
449 if ( snapSettingsElem.isNull() )
451 readLegacySettings();
455 if ( snapSettingsElem.hasAttribute( u
"enabled"_s ) )
456 mEnabled = snapSettingsElem.attribute( u
"enabled"_s ) ==
"1"_L1;
458 if ( snapSettingsElem.hasAttribute( u
"mode"_s ) )
459 mMode =
static_cast< Qgis::SnappingMode >( snapSettingsElem.attribute( u
"mode"_s ).toInt() );
461 if ( snapSettingsElem.hasAttribute( u
"type"_s ) )
463 const int type = snapSettingsElem.attribute( u
"type"_s ).toInt();
464 const QDomElement versionElem = doc.firstChildElement( u
"qgis"_s );
466 bool before3_14 =
false;
467 if ( versionElem.hasAttribute( u
"version"_s ) )
469 version = versionElem.attribute( u
"version"_s );
470 const thread_local QRegularExpression re( u
"([\\d]+)\\.([\\d]+)"_s );
471 const QRegularExpressionMatch match = re.match( version );
472 if ( match.hasMatch() )
474 if ( ( match.captured( 1 ).toInt() <= 3 ) && ( match.captured( 2 ).toInt() <= 12 ) )
504 if ( snapSettingsElem.hasAttribute( u
"tolerance"_s ) )
505 mTolerance = snapSettingsElem.attribute( u
"tolerance"_s ).toDouble();
507 if ( snapSettingsElem.hasAttribute( u
"scaleDependencyMode"_s ) )
510 if ( snapSettingsElem.hasAttribute( u
"minScale"_s ) )
511 mMinimumScale = snapSettingsElem.attribute( u
"minScale"_s ).toDouble();
513 if ( snapSettingsElem.hasAttribute( u
"maxScale"_s ) )
514 mMaximumScale = snapSettingsElem.attribute( u
"maxScale"_s ).toDouble();
516 if ( snapSettingsElem.hasAttribute( u
"unit"_s ) )
517 mUnits =
static_cast< Qgis::MapToolUnit >( snapSettingsElem.attribute( u
"unit"_s ).toInt() );
519 if ( snapSettingsElem.hasAttribute( u
"intersection-snapping"_s ) )
520 mIntersectionSnapping = snapSettingsElem.attribute( u
"intersection-snapping"_s ) ==
"1"_L1;
522 if ( snapSettingsElem.hasAttribute( u
"self-snapping"_s ) )
523 mSelfSnapping = snapSettingsElem.attribute( u
"self-snapping"_s ) ==
"1"_L1;
526 const QDomNodeList nodes = snapSettingsElem.elementsByTagName( u
"individual-layer-settings"_s );
529 const QDomNode node = nodes.item( 0 );
530 const QDomNodeList settingNodes = node.childNodes();
531 const int layerCount = settingNodes.count();
532 for (
int i = 0; i < layerCount; ++i )
534 const QDomElement settingElement = settingNodes.at( i ).toElement();
535 if ( settingElement.tagName() !=
"layer-setting"_L1 )
537 QgsLogger::warning( QApplication::translate(
"QgsProjectSnappingSettings",
"Cannot read individual settings. Unexpected tag '%1'" ).arg( settingElement.tagName() ) );
541 const QString layerId = settingElement.attribute( u
"id"_s );
542 const bool enabled = settingElement.attribute( u
"enabled"_s ) ==
"1"_L1;
544 const double tolerance = settingElement.attribute( u
"tolerance"_s ).toDouble();
546 const double minScale = settingElement.attribute( u
"minScale"_s ).toDouble();
547 const double maxScale = settingElement.attribute( u
"maxScale"_s ).toDouble();
556 mIndividualLayerSettings.insert( vl, setting );
563 QDomElement snapSettingsElem = doc.createElement( u
"snapping-settings"_s );
564 snapSettingsElem.setAttribute( u
"enabled"_s, QString::number( mEnabled ) );
565 snapSettingsElem.setAttribute( u
"mode"_s,
static_cast<int>( mMode ) );
566 snapSettingsElem.setAttribute( u
"type"_s,
static_cast<int>( mType ) );
567 snapSettingsElem.setAttribute( u
"tolerance"_s, mTolerance );
568 snapSettingsElem.setAttribute( u
"unit"_s,
static_cast<int>( mUnits ) );
569 snapSettingsElem.setAttribute( u
"intersection-snapping"_s, QString::number( mIntersectionSnapping ) );
570 snapSettingsElem.setAttribute( u
"self-snapping"_s, QString::number( mSelfSnapping ) );
571 snapSettingsElem.setAttribute( u
"scaleDependencyMode"_s, QString::number( mScaleDependencyMode ) );
572 snapSettingsElem.setAttribute( u
"minScale"_s, mMinimumScale );
573 snapSettingsElem.setAttribute( u
"maxScale"_s, mMaximumScale );
575 QDomElement ilsElement = doc.createElement( u
"individual-layer-settings"_s );
576 QHash<QgsVectorLayer *, IndividualLayerSettings>::const_iterator layerIt = mIndividualLayerSettings.constBegin();
577 for ( ; layerIt != mIndividualLayerSettings.constEnd(); ++layerIt )
581 QDomElement layerElement = doc.createElement( u
"layer-setting"_s );
582 layerElement.setAttribute( u
"id"_s, layerIt.key()->id() );
583 layerElement.setAttribute( u
"enabled"_s, QString::number( setting.
enabled() ) );
584 layerElement.setAttribute( u
"type"_s,
static_cast<int>( setting.
typeFlag() ) );
585 layerElement.setAttribute( u
"tolerance"_s, setting.
tolerance() );
586 layerElement.setAttribute( u
"units"_s,
static_cast<int>( setting.
units() ) );
587 layerElement.setAttribute( u
"minScale"_s, setting.
minimumScale() );
588 layerElement.setAttribute( u
"maxScale"_s, setting.
maximumScale() );
589 ilsElement.appendChild( layerElement );
591 snapSettingsElem.appendChild( ilsElement );
593 doc.firstChildElement( u
"qgis"_s ).appendChild( snapSettingsElem );
598 bool changed =
false;
604 const auto constLayers = layers;
619 bool changed =
false;
620 const auto constLayers = layers;
626 mIndividualLayerSettings.remove( vl );
633void QgsSnappingConfig::readLegacySettings()
638 const QString snapMode = mProject->
readEntry( u
"Digitizing"_s, u
"/SnappingMode"_s );
640 mTolerance = mProject->
readDoubleEntry( u
"Digitizing"_s, u
"/DefaultSnapTolerance"_s, 0 );
643 mIntersectionSnapping = mProject->
readNumEntry( u
"Digitizing"_s, u
"/IntersectionSnapping"_s, 0 );
646 const QStringList layerIdList = mProject->
readListEntry( u
"Digitizing"_s, u
"/LayerSnappingList"_s, QStringList() );
647 const QStringList enabledList = mProject->
readListEntry( u
"Digitizing"_s, u
"/LayerSnappingEnabledList"_s, QStringList() );
648 const QStringList toleranceList = mProject->
readListEntry( u
"Digitizing"_s, u
"/LayerSnappingToleranceList"_s, QStringList() );
649 const QStringList toleranceUnitList = mProject->
readListEntry( u
"Digitizing"_s, u
"/LayerSnappingToleranceUnitList"_s, QStringList() );
650 const QStringList snapToList = mProject->
readListEntry( u
"Digitizing"_s, u
"/LayerSnapToList"_s, QStringList() );
653 if ( layerIdList.size() != enabledList.size() ||
654 layerIdList.size() != toleranceList.size() ||
655 layerIdList.size() != toleranceUnitList.size() ||
656 layerIdList.size() != snapToList.size() )
660 if ( snapMode ==
"current_layer"_L1 )
662 else if ( snapMode ==
"all_layers"_L1 )
668 QStringList::const_iterator layerIt( layerIdList.constBegin() );
669 QStringList::const_iterator tolIt( toleranceList.constBegin() );
670 QStringList::const_iterator tolUnitIt( toleranceUnitList.constBegin() );
671 QStringList::const_iterator snapIt( snapToList.constBegin() );
672 QStringList::const_iterator enabledIt( enabledList.constBegin() );
673 for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt )
685 mIndividualLayerSettings.insert( vlayer, IndividualLayerSettings( *enabledIt ==
"enabled"_L1, t, tolIt->toDouble(),
static_cast<Qgis::MapToolUnit>( tolUnitIt->toInt() ), 0.0, 0.0 ) );
688 const QString snapType = mProject->readEntry( u
"Digitizing"_s, u
"/DefaultSnapType"_s, u
"off"_s );
690 if ( snapType ==
"to segment"_L1 )
692 else if ( snapType ==
"to vertex and segment"_L1 )
694 else if ( snapType ==
"to vertex"_L1 )
719 return mMinimumScale;
724 mMinimumScale = minScale;
729 return mMaximumScale;
734 mMaximumScale = maxScale;
739 mScaleDependencyMode =
mode;
744 return mScaleDependencyMode;
MapToolUnit
Type of unit of tolerance value from settings.
@ Project
Map (project) units.
SnappingType
SnappingTypeFlag defines on what object the snapping is performed.
@ LineEndpoint
Start or end points of lines, or first vertex in polygon rings only.
@ MiddleOfSegment
On Middle segment.
QFlags< SnappingType > SnappingTypes
Snapping types.
SnappingMode
SnappingMode defines on which layer the snapping is performed.
@ ActiveLayer
On the active layer.
@ AdvancedConfiguration
On a per layer configuration basis.
@ AllLayers
On all vector layers.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static void warning(const QString &msg)
Goes to qWarning.
Base class for all map layer types.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
Reads an integer from the specified scope and key.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=nullptr) const
Reads a double from the specified scope and key.
QStringList readListEntry(const QString &scope, const QString &key, const QStringList &def=QStringList(), bool *ok=nullptr) const
Reads a string list from the specified scope and key.
static const QgsSettingsEntryBool * settingsDigitizingDefaultSnapEnabled
Settings entry digitizing default snap enabled.
static const QgsSettingsEntryEnumFlag< Qgis::MapToolUnit > * settingsDigitizingDefaultSnappingToleranceUnit
Settings entry digitizing default snapping tolerance unit.
static const QgsSettingsEntryDouble * settingsDigitizingDefaultSnappingTolerance
Settings entry digitizing default snapping tolerance.
static const QgsSettingsEntryEnumFlag< Qgis::SnappingMode > * settingsDigitizingDefaultSnapMode
Settings entry digitizing default snap type.
static const QgsSettingsEntryEnumFlag< Qgis::SnappingType > * settingsDigitizingDefaultSnapType
Settings entry digitizing default snap type.
A container of advanced configuration (per layer) of the snapping of the project.
double tolerance() const
Returns the tolerance.
void setEnabled(bool enabled)
enables the snapping
bool operator!=(const QgsSnappingConfig::IndividualLayerSettings &other) const
void setTypeFlag(Qgis::SnappingTypes type)
define the type of snapping
bool valid() const
Returns if settings are valid.
IndividualLayerSettings()=default
Constructs an invalid setting.
double maximumScale() const
Returns max scale on which snapping is limited.
void setMinimumScale(double minScale)
Sets the min scale value on which snapping is used, 0.0 disable scale limit.
Qgis::MapToolUnit units() const
Returns the type of units.
void setMaximumScale(double maxScale)
Sets the max scale value on which snapping is used, 0.0 disable scale limit.
Q_DECL_DEPRECATED void setType(SnappingType type)
define the type of snapping
bool enabled() const
Returns if snapping is enabled.
bool operator==(const QgsSnappingConfig::IndividualLayerSettings &other) const
Q_DECL_DEPRECATED QgsSnappingConfig::SnappingType type() const
Returns the flags type (vertices | segments | area | centroid | middle).
double minimumScale() const
Returns minimum scale on which snapping is limited.
void setUnits(Qgis::MapToolUnit units)
Sets the type of units.
Qgis::SnappingTypes typeFlag() const
Returns the flags type (vertices | segments | area | centroid | middle).
void setTolerance(double tolerance)
Sets the tolerance.
bool addLayers(const QList< QgsMapLayer * > &layers)
Adds the specified layers as individual layers to the configuration with standard configuration.
void readProject(const QDomDocument &doc)
Reads the configuration from the specified QGIS project document.
void setScaleDependencyMode(ScaleDependencyMode mode)
Set the scale dependency mode.
QgsSnappingConfig(QgsProject *project=nullptr)
Constructor with default parameters defined in global settings.
void setMinimumScale(double minScale)
Sets the min scale on which snapping is enabled, 0.0 disable scale limit.
void setUnits(Qgis::MapToolUnit units)
Sets the type of units.
bool intersectionSnapping() const
Returns if the snapping on intersection is enabled.
ScaleDependencyMode
ScaleDependencyMode the scale dependency mode of snapping.
@ Disabled
No scale dependency.
void setTypeFlag(Qgis::SnappingTypes type)
define the type of snapping
double minimumScale() const
Returns the min scale (i.e.
double tolerance() const
Returns the tolerance.
void setMode(Qgis::SnappingMode mode)
define the mode of snapping
static QIcon snappingTypeToIcon(Qgis::SnappingType type)
Convenient method to return an icon corresponding to the enum type Qgis::SnappingTypes.
void reset()
reset to default values
Q_DECL_DEPRECATED void setType(QgsSnappingConfig::SnappingType type)
define the type of snapping
void writeProject(QDomDocument &doc)
Writes the configuration to the specified QGIS project document.
void setMaximumScale(double maxScale)
Set the max scale on which snapping is enabled, 0.0 disable scale limit.
bool selfSnapping() const
Returns if self snapping (snapping to the currently digitized feature) is enabled.
void setTolerance(double tolerance)
Sets the tolerance.
Qgis::SnappingTypes typeFlag() const
Returns the flags type (vertices | segments | area | centroid | middle).
void clearIndividualLayerSettings()
Removes all individual layer snapping settings.
Q_DECL_DEPRECATED QgsSnappingConfig::SnappingType type() const
Returns the flags type (vertices | segments | area | centroid | middle).
double maximumScale() const
Returns the max scale (i.e.
void setProject(QgsProject *project)
The project from which the snapped layers should be retrieved.
static QString snappingTypeToString(Qgis::SnappingType type)
Convenient method to returns the translated name of the enum type Qgis::SnappingTypes.
Qgis::MapToolUnit units() const
Returns the type of units.
bool operator!=(const QgsSnappingConfig &other) const
bool operator==(const QgsSnappingConfig &other) const
SnappingType
SnappingType defines on what object the snapping is performed.
@ VertexAndSegment
Both on vertices and segments.
@ Vertex
On vertices only.
@ Segment
On segments only.
void setSelfSnapping(bool enabled)
Sets if self snapping (snapping to the currently digitized feature) is enabled.
QHash< QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings > individualLayerSettings() const
Returns individual snapping settings for all layers.
bool removeLayers(const QList< QgsMapLayer * > &layers)
Removes the specified layers from the individual layer configuration.
ScaleDependencyMode scaleDependencyMode() const
Returns the scale dependency mode.
void setEnabled(bool enabled)
enables the snapping
void setIndividualLayerSettings(QgsVectorLayer *vl, const QgsSnappingConfig::IndividualLayerSettings &individualLayerSettings)
Sets individual layer snappings settings (applied if mode is AdvancedConfiguration).
void setIntersectionSnapping(bool enabled)
Sets if the snapping on intersection is enabled.
Represents a vector layer which manages a vector based dataset.
bool isSpatial() const final
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH