20#include <QRegularExpression>
34 , mTolerance( tolerance )
36 , mMinimumScale( minScale )
37 , mMaximumScale( maxScale )
74 if ( ( mType & QgsSnappingConfig::SnappingType::Segment ) && ( mType & QgsSnappingConfig::SnappingType::Vertex ) )
75 return QgsSnappingConfig::SnappingType::VertexAndSegment;
76 else if ( mType & QgsSnappingConfig::SnappingType::Segment )
77 return QgsSnappingConfig::SnappingType::Segment;
79 return QgsSnappingConfig::SnappingType::Vertex;
88 mType = Qgis::SnappingType::Vertex;
91 mType = Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment;
94 mType = Qgis::SnappingType::Segment;
97 mType = Qgis::SnappingType::NoSnap;
128 return mMinimumScale;
133 mMinimumScale = minScale;
138 return mMaximumScale;
143 mMaximumScale = maxScale;
148 return mValid != other.mValid
149 || mEnabled != other.mEnabled
150 || mType != other.mType
151 || mTolerance != other.mTolerance
152 || mUnits != other.mUnits
153 || mMinimumScale != other.mMinimumScale
154 || mMaximumScale != other.mMaximumScale;
159 return mValid == other.mValid
160 && mEnabled == other.mEnabled
161 && mType == other.mType
162 && mTolerance == other.mTolerance
163 && mUnits == other.mUnits
164 && mMinimumScale == other.mMinimumScale
165 && mMaximumScale == other.mMaximumScale;
177 return mEnabled == other.mEnabled
178 && mMode == other.mMode
179 && mType == other.mType
180 && mTolerance == other.mTolerance
181 && mUnits == other.mUnits
182 && mIntersectionSnapping == other.mIntersectionSnapping
183 && mSelfSnapping == other.mSelfSnapping
184 && mIndividualLayerSettings == other.mIndividualLayerSettings
185 && mScaleDependencyMode == other.mScaleDependencyMode
186 && mMinimumScale == other.mMinimumScale
187 && mMaximumScale == other.mMaximumScale;
210 mUnits = Qgis::MapToolUnit::Project;
216 mIntersectionSnapping =
false;
217 mSelfSnapping =
false;
222 mIndividualLayerSettings = QHash<QgsVectorLayer *, IndividualLayerSettings>();
223 const auto constMapLayers = mProject->
mapLayers();
270 if ( ( mType & QgsSnappingConfig::SnappingType::Segment ) && ( mType & QgsSnappingConfig::SnappingType::Vertex ) )
271 return QgsSnappingConfig::SnappingType::VertexAndSegment;
272 else if ( mType & QgsSnappingConfig::SnappingType::Segment )
273 return QgsSnappingConfig::SnappingType::Segment;
275 return QgsSnappingConfig::SnappingType::Vertex;
282 case Qgis::SnappingType::NoSnap:
283 return QObject::tr(
"No Snapping" );
284 case Qgis::SnappingType::Vertex:
285 return QObject::tr(
"Vertex" );
286 case Qgis::SnappingType::Segment:
287 return QObject::tr(
"Segment" );
288 case Qgis::SnappingType::Area:
289 return QObject::tr(
"Area" );
290 case Qgis::SnappingType::Centroid:
291 return QObject::tr(
"Centroid" );
292 case Qgis::SnappingType::MiddleOfSegment:
293 return QObject::tr(
"Middle of Segments" );
294 case Qgis::SnappingType::LineEndpoint:
295 return QObject::tr(
"Line Endpoints" );
304 case Qgis::SnappingType::NoSnap:
306 case Qgis::SnappingType::Vertex:
308 case Qgis::SnappingType::Segment:
310 case Qgis::SnappingType::Area:
312 case Qgis::SnappingType::Centroid:
314 case Qgis::SnappingType::MiddleOfSegment:
316 case Qgis::SnappingType::LineEndpoint:
326 case SnappingType::Vertex:
327 mType = Qgis::SnappingType::Vertex;
329 case SnappingType::VertexAndSegment:
330 mType =
static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment );
332 case SnappingType::Segment:
333 mType = Qgis::SnappingType::Segment;
336 mType = Qgis::SnappingType::NoSnap;
370 if ( mUnits ==
units )
379 return mIntersectionSnapping;
384 mIntersectionSnapping =
enabled;
389 return mSelfSnapping;
399 return mIndividualLayerSettings;
404 if ( vl && mIndividualLayerSettings.contains( vl ) )
406 return mIndividualLayerSettings.value( vl );
417 mIndividualLayerSettings.clear();
431 return mEnabled != other.mEnabled
432 || mMode != other.mMode
433 || mType != other.mType
434 || mTolerance != other.mTolerance
435 || mUnits != other.mUnits
436 || mIndividualLayerSettings != other.mIndividualLayerSettings
437 || mScaleDependencyMode != other.mScaleDependencyMode
438 || mMinimumScale != other.mMinimumScale
439 || mMaximumScale != other.mMaximumScale;
444 const QDomElement snapSettingsElem = doc.firstChildElement( QStringLiteral(
"qgis" ) ).firstChildElement( QStringLiteral(
"snapping-settings" ) );
445 if ( snapSettingsElem.isNull() )
447 readLegacySettings();
451 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"enabled" ) ) )
452 mEnabled = snapSettingsElem.attribute( QStringLiteral(
"enabled" ) ) == QLatin1String(
"1" );
454 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"mode" ) ) )
455 mMode =
static_cast< Qgis::SnappingMode >( snapSettingsElem.attribute( QStringLiteral(
"mode" ) ).toInt() );
457 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"type" ) ) )
459 const int type = snapSettingsElem.attribute( QStringLiteral(
"type" ) ).toInt();
460 const QDomElement versionElem = doc.firstChildElement( QStringLiteral(
"qgis" ) );
462 bool before3_14 =
false;
463 if ( versionElem.hasAttribute( QStringLiteral(
"version" ) ) )
465 version = versionElem.attribute( QStringLiteral(
"version" ) );
466 const thread_local QRegularExpression re( QStringLiteral(
"([\\d]+)\\.([\\d]+)" ) );
467 const QRegularExpressionMatch match = re.match( version );
468 if ( match.hasMatch() )
470 if ( ( match.captured( 1 ).toInt() <= 3 ) && ( match.captured( 2 ).toInt() <= 12 ) )
483 mType = Qgis::SnappingType::Vertex;
486 mType =
static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment );
489 mType = Qgis::SnappingType::Segment;
492 mType = Qgis::SnappingType::NoSnap;
497 mType =
static_cast<Qgis::SnappingTypes
>(
type );
500 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"tolerance" ) ) )
501 mTolerance = snapSettingsElem.attribute( QStringLiteral(
"tolerance" ) ).toDouble();
503 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"scaleDependencyMode" ) ) )
506 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"minScale" ) ) )
507 mMinimumScale = snapSettingsElem.attribute( QStringLiteral(
"minScale" ) ).toDouble();
509 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"maxScale" ) ) )
510 mMaximumScale = snapSettingsElem.attribute( QStringLiteral(
"maxScale" ) ).toDouble();
512 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"unit" ) ) )
513 mUnits =
static_cast< Qgis::MapToolUnit >( snapSettingsElem.attribute( QStringLiteral(
"unit" ) ).toInt() );
515 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"intersection-snapping" ) ) )
516 mIntersectionSnapping = snapSettingsElem.attribute( QStringLiteral(
"intersection-snapping" ) ) == QLatin1String(
"1" );
518 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"self-snapping" ) ) )
519 mSelfSnapping = snapSettingsElem.attribute( QStringLiteral(
"self-snapping" ) ) == QLatin1String(
"1" );
522 const QDomNodeList nodes = snapSettingsElem.elementsByTagName( QStringLiteral(
"individual-layer-settings" ) );
525 const QDomNode node = nodes.item( 0 );
526 const QDomNodeList settingNodes = node.childNodes();
527 const int layerCount = settingNodes.count();
528 for (
int i = 0; i < layerCount; ++i )
530 const QDomElement settingElement = settingNodes.at( i ).toElement();
531 if ( settingElement.tagName() != QLatin1String(
"layer-setting" ) )
533 QgsLogger::warning( QApplication::translate(
"QgsProjectSnappingSettings",
"Cannot read individual settings. Unexpected tag '%1'" ).arg( settingElement.tagName() ) );
537 const QString layerId = settingElement.attribute( QStringLiteral(
"id" ) );
538 const bool enabled = settingElement.attribute( QStringLiteral(
"enabled" ) ) == QLatin1String(
"1" );
539 const Qgis::SnappingTypes
type =
static_cast<Qgis::SnappingTypes
>( settingElement.attribute( QStringLiteral(
"type" ) ).toInt() );
540 const double tolerance = settingElement.attribute( QStringLiteral(
"tolerance" ) ).toDouble();
542 const double minScale = settingElement.attribute( QStringLiteral(
"minScale" ) ).toDouble();
543 const double maxScale = settingElement.attribute( QStringLiteral(
"maxScale" ) ).toDouble();
546 if ( !ml || ml->
type() != Qgis::LayerType::Vector )
552 mIndividualLayerSettings.insert( vl, setting );
559 QDomElement snapSettingsElem = doc.createElement( QStringLiteral(
"snapping-settings" ) );
560 snapSettingsElem.setAttribute( QStringLiteral(
"enabled" ), QString::number( mEnabled ) );
561 snapSettingsElem.setAttribute( QStringLiteral(
"mode" ),
static_cast<int>( mMode ) );
562 snapSettingsElem.setAttribute( QStringLiteral(
"type" ),
static_cast<int>( mType ) );
563 snapSettingsElem.setAttribute( QStringLiteral(
"tolerance" ), mTolerance );
564 snapSettingsElem.setAttribute( QStringLiteral(
"unit" ),
static_cast<int>( mUnits ) );
565 snapSettingsElem.setAttribute( QStringLiteral(
"intersection-snapping" ), QString::number( mIntersectionSnapping ) );
566 snapSettingsElem.setAttribute( QStringLiteral(
"self-snapping" ), QString::number( mSelfSnapping ) );
567 snapSettingsElem.setAttribute( QStringLiteral(
"scaleDependencyMode" ), QString::number( mScaleDependencyMode ) );
568 snapSettingsElem.setAttribute( QStringLiteral(
"minScale" ), mMinimumScale );
569 snapSettingsElem.setAttribute( QStringLiteral(
"maxScale" ), mMaximumScale );
571 QDomElement ilsElement = doc.createElement( QStringLiteral(
"individual-layer-settings" ) );
572 QHash<QgsVectorLayer *, IndividualLayerSettings>::const_iterator layerIt = mIndividualLayerSettings.constBegin();
573 for ( ; layerIt != mIndividualLayerSettings.constEnd(); ++layerIt )
577 QDomElement layerElement = doc.createElement( QStringLiteral(
"layer-setting" ) );
578 layerElement.setAttribute( QStringLiteral(
"id" ), layerIt.key()->id() );
579 layerElement.setAttribute( QStringLiteral(
"enabled" ), QString::number( setting.
enabled() ) );
580 layerElement.setAttribute( QStringLiteral(
"type" ),
static_cast<int>( setting.
typeFlag() ) );
581 layerElement.setAttribute( QStringLiteral(
"tolerance" ), setting.
tolerance() );
582 layerElement.setAttribute( QStringLiteral(
"units" ),
static_cast<int>( setting.
units() ) );
583 layerElement.setAttribute( QStringLiteral(
"minScale" ), setting.
minimumScale() );
584 layerElement.setAttribute( QStringLiteral(
"maxScale" ), setting.
maximumScale() );
585 ilsElement.appendChild( layerElement );
587 snapSettingsElem.appendChild( ilsElement );
589 doc.firstChildElement( QStringLiteral(
"qgis" ) ).appendChild( snapSettingsElem );
594 bool changed =
false;
600 const auto constLayers = layers;
615 bool changed =
false;
616 const auto constLayers = layers;
622 mIndividualLayerSettings.remove( vl );
629void QgsSnappingConfig::readLegacySettings()
634 const QString snapMode = mProject->
readEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/SnappingMode" ) );
636 mTolerance = mProject->
readDoubleEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/DefaultSnapTolerance" ), 0 );
637 mUnits =
static_cast< Qgis::MapToolUnit >( mProject->
readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/DefaultSnapToleranceUnit" ),
static_cast<int>( Qgis::MapToolUnit::Project ) ) );
639 mIntersectionSnapping = mProject->
readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/IntersectionSnapping" ), 0 );
642 const QStringList layerIdList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingList" ), QStringList() );
643 const QStringList enabledList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingEnabledList" ), QStringList() );
644 const QStringList toleranceList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingToleranceList" ), QStringList() );
645 const QStringList toleranceUnitList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingToleranceUnitList" ), QStringList() );
646 const QStringList snapToList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnapToList" ), QStringList() );
649 if ( layerIdList.size() != enabledList.size() ||
650 layerIdList.size() != toleranceList.size() ||
651 layerIdList.size() != toleranceUnitList.size() ||
652 layerIdList.size() != snapToList.size() )
656 if ( snapMode == QLatin1String(
"current_layer" ) )
658 else if ( snapMode == QLatin1String(
"all_layers" ) )
664 QStringList::const_iterator layerIt( layerIdList.constBegin() );
665 QStringList::const_iterator tolIt( toleranceList.constBegin() );
666 QStringList::const_iterator tolUnitIt( toleranceUnitList.constBegin() );
667 QStringList::const_iterator snapIt( snapToList.constBegin() );
668 QStringList::const_iterator enabledIt( enabledList.constBegin() );
669 for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt )
675 const Qgis::SnappingTypes t( *snapIt == QLatin1String(
"to_vertex" ) ? Qgis::SnappingType::Vertex :
676 ( *snapIt == QLatin1String(
"to_segment" ) ? Qgis::SnappingType::Segment :
677 static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment )
681 mIndividualLayerSettings.insert( vlayer, IndividualLayerSettings( *enabledIt == QLatin1String(
"enabled" ), t, tolIt->toDouble(),
static_cast<Qgis::MapToolUnit>( tolUnitIt->toInt() ), 0.0, 0.0 ) );
684 const QString snapType = mProject->
readEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/DefaultSnapType" ), QStringLiteral(
"off" ) );
686 if ( snapType == QLatin1String(
"to segment" ) )
687 mType = Qgis::SnappingType::Segment;
688 else if ( snapType == QLatin1String(
"to vertex and segment" ) )
689 mType =
static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment );
690 else if ( snapType == QLatin1String(
"to vertex" ) )
691 mType = Qgis::SnappingType::Vertex;
713 return mMinimumScale;
718 mMinimumScale = minScale;
723 return mMaximumScale;
728 mMaximumScale = maxScale;
733 mScaleDependencyMode =
mode;
738 return mScaleDependencyMode;
MapToolUnit
Type of unit of tolerance value from settings.
SnappingType
SnappingTypeFlag defines on what object the snapping is performed.
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.
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
T valueWithDefaultOverride(const T &defaultValueOverride, const QString &dynamicKeyPart=QString()) const
Returns the settings value with a defaultValueOverride and with an optional dynamicKeyPart.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
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.
This is 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
Compare this configuration to other.
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.
This is a container for configuration of the snapping of the project.
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.
Q_GADGET QgsProject * project
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
Compare this configuration to other.
bool operator==(const QgsSnappingConfig &other) const
Qgis::SnappingMode mode() const
Returns the mode (all layers, active layer, per layer settings)
SnappingType
SnappingType defines on what object the snapping is performed.
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
bool enabled() const
Returns if snapping is enabled.
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 data sets.
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