18 #include <QDomElement>
19 #include <QHeaderView>
20 #include <QRegularExpression>
33 , mTolerance( tolerance )
35 , mMinimumScale( minScale )
36 , mMaximumScale( maxScale )
73 if ( ( mType & QgsSnappingConfig::SnappingType::Segment ) && ( mType & QgsSnappingConfig::SnappingType::Vertex ) )
74 return QgsSnappingConfig::SnappingType::VertexAndSegment;
75 else if ( mType & QgsSnappingConfig::SnappingType::Segment )
76 return QgsSnappingConfig::SnappingType::Segment;
78 return QgsSnappingConfig::SnappingType::Vertex;
87 mType = Qgis::SnappingType::Vertex;
90 mType = Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment;
93 mType = Qgis::SnappingType::Segment;
96 mType = Qgis::SnappingType::NoSnap;
127 return mMinimumScale;
132 mMinimumScale = minScale;
137 return mMaximumScale;
142 mMaximumScale = maxScale;
147 return mValid != other.mValid
148 || mEnabled != other.mEnabled
149 || mType != other.mType
150 || mTolerance != other.mTolerance
151 || mUnits != other.mUnits
152 || mMinimumScale != other.mMinimumScale
153 || mMaximumScale != other.mMaximumScale;
158 return mValid == other.mValid
159 && mEnabled == other.mEnabled
160 && mType == other.mType
161 && mTolerance == other.mTolerance
162 && mUnits == other.mUnits
163 && mMinimumScale == other.mMinimumScale
164 && mMaximumScale == other.mMaximumScale;
176 return mEnabled == other.mEnabled
177 && mMode == other.mMode
178 && mType == other.mType
179 && mTolerance == other.mTolerance
180 && mUnits == other.mUnits
181 && mIntersectionSnapping == other.mIntersectionSnapping
182 && mSelfSnapping == other.mSelfSnapping
183 && mIndividualLayerSettings == other.mIndividualLayerSettings
184 && mScaleDependencyMode == other.mScaleDependencyMode
185 && mMinimumScale == other.mMinimumScale
186 && mMaximumScale == other.mMaximumScale;
215 mIntersectionSnapping =
false;
216 mSelfSnapping =
false;
221 mIndividualLayerSettings = QHash<QgsVectorLayer *, IndividualLayerSettings>();
222 const auto constMapLayers = mProject->
mapLayers();
269 if ( ( mType & QgsSnappingConfig::SnappingType::Segment ) && ( mType & QgsSnappingConfig::SnappingType::Vertex ) )
270 return QgsSnappingConfig::SnappingType::VertexAndSegment;
271 else if ( mType & QgsSnappingConfig::SnappingType::Segment )
272 return QgsSnappingConfig::SnappingType::Segment;
274 return QgsSnappingConfig::SnappingType::Vertex;
281 case Qgis::SnappingType::NoSnap:
282 return QObject::tr(
"No Snapping" );
283 case Qgis::SnappingType::Vertex:
284 return QObject::tr(
"Vertex" );
285 case Qgis::SnappingType::Segment:
286 return QObject::tr(
"Segment" );
287 case Qgis::SnappingType::Area:
288 return QObject::tr(
"Area" );
289 case Qgis::SnappingType::Centroid:
290 return QObject::tr(
"Centroid" );
291 case Qgis::SnappingType::MiddleOfSegment:
292 return QObject::tr(
"Middle of Segments" );
293 case Qgis::SnappingType::LineEndpoint:
294 return QObject::tr(
"Line Endpoints" );
303 case Qgis::SnappingType::NoSnap:
305 case Qgis::SnappingType::Vertex:
307 case Qgis::SnappingType::Segment:
309 case Qgis::SnappingType::Area:
311 case Qgis::SnappingType::Centroid:
313 case Qgis::SnappingType::MiddleOfSegment:
315 case Qgis::SnappingType::LineEndpoint:
325 case SnappingType::Vertex:
326 mType = Qgis::SnappingType::Vertex;
328 case SnappingType::VertexAndSegment:
329 mType =
static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment );
331 case SnappingType::Segment:
332 mType = Qgis::SnappingType::Segment;
335 mType = Qgis::SnappingType::NoSnap;
369 if ( mUnits ==
units )
378 return mIntersectionSnapping;
383 mIntersectionSnapping =
enabled;
388 return mSelfSnapping;
398 return mIndividualLayerSettings;
403 if ( vl && mIndividualLayerSettings.contains( vl ) )
405 return mIndividualLayerSettings.value( vl );
416 mIndividualLayerSettings.clear();
430 return mEnabled != other.mEnabled
431 || mMode != other.mMode
432 || mType != other.mType
433 || mTolerance != other.mTolerance
434 || mUnits != other.mUnits
435 || mIndividualLayerSettings != other.mIndividualLayerSettings
436 || mScaleDependencyMode != other.mScaleDependencyMode
437 || mMinimumScale != other.mMinimumScale
438 || mMaximumScale != other.mMaximumScale;
443 const QDomElement snapSettingsElem = doc.firstChildElement( QStringLiteral(
"qgis" ) ).firstChildElement( QStringLiteral(
"snapping-settings" ) );
444 if ( snapSettingsElem.isNull() )
446 readLegacySettings();
450 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"enabled" ) ) )
451 mEnabled = snapSettingsElem.attribute( QStringLiteral(
"enabled" ) ) == QLatin1String(
"1" );
453 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"mode" ) ) )
454 mMode =
static_cast< Qgis::SnappingMode >( snapSettingsElem.attribute( QStringLiteral(
"mode" ) ).toInt() );
456 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"type" ) ) )
458 const int type = snapSettingsElem.attribute( QStringLiteral(
"type" ) ).toInt();
459 const QDomElement versionElem = doc.firstChildElement( QStringLiteral(
"qgis" ) );
461 bool before3_14 =
false;
462 if ( versionElem.hasAttribute( QStringLiteral(
"version" ) ) )
464 version = versionElem.attribute( QStringLiteral(
"version" ) );
465 const QRegularExpression re( QStringLiteral(
"([\\d]+)\\.([\\d]+)" ) );
466 const QRegularExpressionMatch match = re.match( version );
467 if ( match.hasMatch() )
469 if ( ( match.captured( 1 ).toInt() <= 3 ) && ( match.captured( 2 ).toInt() <= 12 ) )
482 mType = Qgis::SnappingType::Vertex;
485 mType =
static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment );
488 mType = Qgis::SnappingType::Segment;
491 mType = Qgis::SnappingType::NoSnap;
496 mType =
static_cast<Qgis::SnappingTypes
>(
type );
499 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"tolerance" ) ) )
500 mTolerance = snapSettingsElem.attribute( QStringLiteral(
"tolerance" ) ).toDouble();
502 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"scaleDependencyMode" ) ) )
505 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"minScale" ) ) )
506 mMinimumScale = snapSettingsElem.attribute( QStringLiteral(
"minScale" ) ).toDouble();
508 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"maxScale" ) ) )
509 mMaximumScale = snapSettingsElem.attribute( QStringLiteral(
"maxScale" ) ).toDouble();
511 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"unit" ) ) )
512 mUnits =
static_cast< QgsTolerance::UnitType >( snapSettingsElem.attribute( QStringLiteral(
"unit" ) ).toInt() );
514 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"intersection-snapping" ) ) )
515 mIntersectionSnapping = snapSettingsElem.attribute( QStringLiteral(
"intersection-snapping" ) ) == QLatin1String(
"1" );
517 if ( snapSettingsElem.hasAttribute( QStringLiteral(
"self-snapping" ) ) )
518 mSelfSnapping = snapSettingsElem.attribute( QStringLiteral(
"self-snapping" ) ) == QLatin1String(
"1" );
521 const QDomNodeList nodes = snapSettingsElem.elementsByTagName( QStringLiteral(
"individual-layer-settings" ) );
524 const QDomNode node = nodes.item( 0 );
525 const QDomNodeList settingNodes = node.childNodes();
526 const int layerCount = settingNodes.count();
527 for (
int i = 0; i < layerCount; ++i )
529 const QDomElement settingElement = settingNodes.at( i ).toElement();
530 if ( settingElement.tagName() != QLatin1String(
"layer-setting" ) )
532 QgsLogger::warning( QApplication::translate(
"QgsProjectSnappingSettings",
"Cannot read individual settings. Unexpected tag '%1'" ).arg( settingElement.tagName() ) );
536 const QString layerId = settingElement.attribute( QStringLiteral(
"id" ) );
537 const bool enabled = settingElement.attribute( QStringLiteral(
"enabled" ) ) == QLatin1String(
"1" );
538 const Qgis::SnappingTypes
type =
static_cast<Qgis::SnappingTypes
>( settingElement.attribute( QStringLiteral(
"type" ) ).toInt() );
539 const double tolerance = settingElement.attribute( QStringLiteral(
"tolerance" ) ).toDouble();
541 const double minScale = settingElement.attribute( QStringLiteral(
"minScale" ) ).toDouble();
542 const double maxScale = settingElement.attribute( QStringLiteral(
"maxScale" ) ).toDouble();
551 mIndividualLayerSettings.insert( vl, setting );
558 QDomElement snapSettingsElem = doc.createElement( QStringLiteral(
"snapping-settings" ) );
559 snapSettingsElem.setAttribute( QStringLiteral(
"enabled" ), QString::number( mEnabled ) );
560 snapSettingsElem.setAttribute( QStringLiteral(
"mode" ),
static_cast<int>( mMode ) );
561 snapSettingsElem.setAttribute( QStringLiteral(
"type" ),
static_cast<int>( mType ) );
562 snapSettingsElem.setAttribute( QStringLiteral(
"tolerance" ), mTolerance );
563 snapSettingsElem.setAttribute( QStringLiteral(
"unit" ),
static_cast<int>( mUnits ) );
564 snapSettingsElem.setAttribute( QStringLiteral(
"intersection-snapping" ), QString::number( mIntersectionSnapping ) );
565 snapSettingsElem.setAttribute( QStringLiteral(
"self-snapping" ), QString::number( mSelfSnapping ) );
566 snapSettingsElem.setAttribute( QStringLiteral(
"scaleDependencyMode" ), QString::number( mScaleDependencyMode ) );
567 snapSettingsElem.setAttribute( QStringLiteral(
"minScale" ), mMinimumScale );
568 snapSettingsElem.setAttribute( QStringLiteral(
"maxScale" ), mMaximumScale );
570 QDomElement ilsElement = doc.createElement( QStringLiteral(
"individual-layer-settings" ) );
571 QHash<QgsVectorLayer *, IndividualLayerSettings>::const_iterator layerIt = mIndividualLayerSettings.constBegin();
572 for ( ; layerIt != mIndividualLayerSettings.constEnd(); ++layerIt )
576 QDomElement layerElement = doc.createElement( QStringLiteral(
"layer-setting" ) );
577 layerElement.setAttribute( QStringLiteral(
"id" ), layerIt.key()->id() );
578 layerElement.setAttribute( QStringLiteral(
"enabled" ), QString::number( setting.
enabled() ) );
579 layerElement.setAttribute( QStringLiteral(
"type" ),
static_cast<int>( setting.
typeFlag() ) );
580 layerElement.setAttribute( QStringLiteral(
"tolerance" ), setting.
tolerance() );
581 layerElement.setAttribute( QStringLiteral(
"units" ),
static_cast<int>( setting.
units() ) );
582 layerElement.setAttribute( QStringLiteral(
"minScale" ), setting.
minimumScale() );
583 layerElement.setAttribute( QStringLiteral(
"maxScale" ), setting.
maximumScale() );
584 ilsElement.appendChild( layerElement );
586 snapSettingsElem.appendChild( ilsElement );
588 doc.firstChildElement( QStringLiteral(
"qgis" ) ).appendChild( snapSettingsElem );
593 bool changed =
false;
599 const auto constLayers = layers;
614 bool changed =
false;
615 const auto constLayers = layers;
621 mIndividualLayerSettings.remove( vl );
628 void QgsSnappingConfig::readLegacySettings()
633 const QString snapMode = mProject->
readEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/SnappingMode" ) );
635 mTolerance = mProject->
readDoubleEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/DefaultSnapTolerance" ), 0 );
638 mIntersectionSnapping = mProject->
readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/IntersectionSnapping" ), 0 );
641 const QStringList layerIdList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingList" ), QStringList() );
642 const QStringList enabledList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingEnabledList" ), QStringList() );
643 const QStringList toleranceList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingToleranceList" ), QStringList() );
644 const QStringList toleranceUnitList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnappingToleranceUnitList" ), QStringList() );
645 const QStringList snapToList = mProject->
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/LayerSnapToList" ), QStringList() );
648 if ( layerIdList.size() != enabledList.size() ||
649 layerIdList.size() != toleranceList.size() ||
650 layerIdList.size() != toleranceUnitList.size() ||
651 layerIdList.size() != snapToList.size() )
655 if ( snapMode == QLatin1String(
"current_layer" ) )
657 else if ( snapMode == QLatin1String(
"all_layers" ) )
663 QStringList::const_iterator layerIt( layerIdList.constBegin() );
664 QStringList::const_iterator tolIt( toleranceList.constBegin() );
665 QStringList::const_iterator tolUnitIt( toleranceUnitList.constBegin() );
666 QStringList::const_iterator snapIt( snapToList.constBegin() );
667 QStringList::const_iterator enabledIt( enabledList.constBegin() );
668 for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt )
674 const Qgis::SnappingTypes t( *snapIt == QLatin1String(
"to_vertex" ) ? Qgis::SnappingType::Vertex :
675 ( *snapIt == QLatin1String(
"to_segment" ) ? Qgis::SnappingType::Segment :
676 static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment )
680 mIndividualLayerSettings.insert( vlayer, IndividualLayerSettings( *enabledIt == QLatin1String(
"enabled" ), t, tolIt->toDouble(),
static_cast<QgsTolerance::UnitType>( tolUnitIt->toInt() ), 0.0, 0.0 ) );
683 const QString snapType = mProject->
readEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/DefaultSnapType" ), QStringLiteral(
"off" ) );
685 if ( snapType == QLatin1String(
"to segment" ) )
686 mType = Qgis::SnappingType::Segment;
687 else if ( snapType == QLatin1String(
"to vertex and segment" ) )
688 mType =
static_cast<Qgis::SnappingTypes
>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment );
689 else if ( snapType == QLatin1String(
"to vertex" ) )
690 mType = Qgis::SnappingType::Vertex;
712 return mMinimumScale;
717 mMinimumScale = minScale;
722 return mMaximumScale;
727 mMaximumScale = maxScale;
732 mScaleDependencyMode =
mode;
737 return mScaleDependencyMode;