QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgssnappingconfig.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprojectsnappingsettings.cpp - QgsProjectSnappingSettings
3 
4  ---------------------
5  begin : 29.8.2016
6  copyright : (C) 2016 by Denis Rouzaud
7  email : [email protected]
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 #include "qgssnappingconfig.h"
17 
18 #include <QDomElement>
19 #include <QHeaderView>
20 #include <QRegularExpression>
21 
22 #include "qgssettingsregistrycore.h"
23 #include "qgslogger.h"
24 #include "qgsvectorlayer.h"
25 #include "qgsproject.h"
26 #include "qgsapplication.h"
27 
28 
29 QgsSnappingConfig::IndividualLayerSettings::IndividualLayerSettings( bool enabled, SnappingTypeFlag type, double tolerance, QgsTolerance::UnitType units, double minScale, double maxScale )
30  : mValid( true )
31  , mEnabled( enabled )
32  , mType( type )
33  , mTolerance( tolerance )
34  , mUnits( units )
35  , mMinimumScale( minScale )
36  , mMaximumScale( maxScale )
37 {}
38 
40  : mValid( true )
41  , mEnabled( enabled )
42  , mTolerance( tolerance )
43  , mUnits( units )
44 {
46  setType( type );
48 }
49 
51 {
52  return mValid;
53 }
54 
56 {
57  return mEnabled;
58 }
59 
61 {
62  mEnabled = enabled;
63 }
64 
65 QgsSnappingConfig::SnappingTypeFlag QgsSnappingConfig::IndividualLayerSettings::typeFlag() const
66 {
67  return mType;
68 }
69 
71 {
72 
73  if ( ( mType & SegmentFlag ) && ( mType & VertexFlag ) )
74  return QgsSnappingConfig::SnappingType::VertexAndSegment;
75  else if ( mType & SegmentFlag )
76  return QgsSnappingConfig::SnappingType::Segment;
77  else
78  return QgsSnappingConfig::SnappingType::Vertex;
79 
80 }
81 
83 {
84  switch ( type )
85  {
86  case 1:
87  mType = VertexFlag;
88  break;
89  case 2:
90  mType = VertexFlag | SegmentFlag;
91  break;
92  case 3:
93  mType = SegmentFlag;
94  break;
95  default:
96  mType = NoSnapFlag;
97  break;
98  }
99 }
100 void QgsSnappingConfig::IndividualLayerSettings::setTypeFlag( QgsSnappingConfig::SnappingTypeFlag type )
101 {
102  mType = type;
103 }
104 
106 {
107  return mTolerance;
108 }
109 
111 {
112  mTolerance = tolerance;
113 }
114 
116 {
117  return mUnits;
118 }
119 
121 {
122  mUnits = units;
123 }
124 
126 {
127  return mMinimumScale;
128 }
129 
131 {
132  mMinimumScale = minScale;
133 }
134 
136 {
137  return mMaximumScale;
138 }
139 
141 {
142  mMaximumScale = maxScale;
143 }
144 
146 {
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;
154 }
155 
157 {
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;
165 }
166 
168  : mProject( project )
169 {
170  if ( project )
171  reset();
172 }
173 
175 {
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;
187 }
188 
190 {
191  // get defaults values. They are both used for standard and advanced configuration (per layer)
192  const bool enabled = QgsSettingsRegistryCore::settingsDigitizingDefaultSnapEnabled.value();
193  SnappingMode mode = QgsSettings().enumValue( QStringLiteral( "/qgis/digitizing/default_snap_mode" ), AllLayers );
194  if ( mode == 0 )
195  {
196  // backward compatibility with QGIS 2.x
197  // could be removed in 3.4+
198  mode = AllLayers;
199  }
200  const QgsSnappingConfig::SnappingTypeFlag type = QgsSettingsRegistryCore::settingsDigitizingDefaultSnapType.value();
201  const double tolerance = QgsSettingsRegistryCore::settingsDigitizingDefaultSnappingTolerance.value();
202  const QgsTolerance::UnitType units = QgsSettingsRegistryCore::settingsDigitizingDefaultSnappingToleranceUnit.value();
203 
204  // assign main (standard) config
205  mEnabled = enabled;
206  mMode = mode;
207  mType = type;
208  mTolerance = tolerance;
209  mScaleDependencyMode = Disabled;
210  mMinimumScale = 0.0;
211  mMaximumScale = 0.0;
212  // do not allow unit to be "layer" if not in advanced configuration
213  if ( mUnits == QgsTolerance::LayerUnits && mMode != AdvancedConfiguration )
214  {
216  }
217  else
218  {
219  mUnits = units;
220  }
221  mIntersectionSnapping = false;
222  mSelfSnapping = false;
223 
224  // set advanced config
225  if ( mProject )
226  {
227  mIndividualLayerSettings = QHash<QgsVectorLayer *, IndividualLayerSettings>();
228  const auto constMapLayers = mProject->mapLayers();
229  for ( QgsMapLayer *ml : constMapLayers )
230  {
231  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
232  if ( vl )
233  {
234  mIndividualLayerSettings.insert( vl, IndividualLayerSettings( enabled, type, tolerance, units, 0.0, 0.0 ) );
235  }
236  }
237  }
238 }
239 
241 {
242  return mEnabled;
243 }
244 
245 void QgsSnappingConfig::setEnabled( bool enabled )
246 {
247  if ( mEnabled == enabled )
248  {
249  return;
250  }
251  mEnabled = enabled;
252 }
253 
255 {
256  return mMode;
257 }
258 
260 {
261  if ( mMode == mode )
262  {
263  return;
264  }
265  mMode = mode;
266 }
267 
268 QgsSnappingConfig::SnappingTypeFlag QgsSnappingConfig::typeFlag() const
269 {
270  return mType;
271 }
272 
274 {
275  if ( ( mType & SegmentFlag ) && ( mType & VertexFlag ) )
276  return QgsSnappingConfig::SnappingType::VertexAndSegment;
277  else if ( mType & SegmentFlag )
278  return QgsSnappingConfig::SnappingType::Segment;
279  else
280  return QgsSnappingConfig::SnappingType::Vertex;
281 }
282 
283 QString QgsSnappingConfig::snappingTypeFlagToString( SnappingTypeFlag type )
284 {
285  switch ( type )
286  {
288  return QObject::tr( "No Snapping" );
290  return QObject::tr( "Vertex" );
292  return QObject::tr( "Segment" );
294  return QObject::tr( "Area" );
296  return QObject::tr( "Centroid" );
298  return QObject::tr( "Middle of Segments" );
300  return QObject::tr( "Line Endpoints" );
301  }
302  return QString();
303 }
304 
305 QIcon QgsSnappingConfig::snappingTypeFlagToIcon( SnappingTypeFlag type )
306 {
307  switch ( type )
308  {
310  return QIcon();
312  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconSnappingVertex.svg" ) );
314  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconSnappingSegment.svg" ) );
316  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconSnappingArea.svg" ) );
318  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconSnappingCentroid.svg" ) );
320  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconSnappingMiddle.svg" ) );
322  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconSnappingEndpoint.svg" ) );
323  }
324  return QIcon();
325 }
326 
328 {
329  switch ( type )
330  {
331  case SnappingType::Vertex:
332  mType = VertexFlag;
333  break;
334  case SnappingType::VertexAndSegment:
335  mType = static_cast<QgsSnappingConfig::SnappingTypeFlag>( QgsSnappingConfig::VertexFlag | QgsSnappingConfig::SegmentFlag );
336  break;
337  case SnappingType::Segment:
338  mType = SegmentFlag;
339  break;
340  default:
341  mType = NoSnapFlag;
342  break;
343  }
344 }
345 void QgsSnappingConfig::setTypeFlag( QgsSnappingConfig::SnappingTypeFlag type )
346 {
347  if ( mType == type )
348  {
349  return;
350  }
351  mType = type;
352 }
353 
355 {
356  return mTolerance;
357 }
358 
359 void QgsSnappingConfig::setTolerance( double tolerance )
360 {
361  if ( mTolerance == tolerance )
362  {
363  return;
364  }
365  mTolerance = tolerance;
366 }
367 
369 {
370  return mUnits;
371 }
372 
374 {
375  if ( mUnits == units )
376  {
377  return;
378  }
379  mUnits = units;
380 }
381 
383 {
384  return mIntersectionSnapping;
385 }
386 
388 {
389  mIntersectionSnapping = enabled;
390 }
391 
393 {
394  return mSelfSnapping;
395 }
396 
398 {
399  mSelfSnapping = enabled;
400 }
401 
402 QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings> QgsSnappingConfig::individualLayerSettings() const
403 {
404  return mIndividualLayerSettings;
405 }
406 
408 {
409  if ( vl && mIndividualLayerSettings.contains( vl ) )
410  {
411  return mIndividualLayerSettings.value( vl );
412  }
413  else
414  {
415  // return invalid settings
416  return IndividualLayerSettings();
417  }
418 }
419 
421 {
422  mIndividualLayerSettings.clear();
423 }
424 
426 {
427  if ( !vl || !vl->isSpatial() || mIndividualLayerSettings.value( vl ) == individualLayerSettings )
428  {
429  return;
430  }
431  mIndividualLayerSettings.insert( vl, individualLayerSettings );
432 }
433 
435 {
436  return mEnabled != other.mEnabled
437  || mMode != other.mMode
438  || mType != other.mType
439  || mTolerance != other.mTolerance
440  || mUnits != other.mUnits
441  || mIndividualLayerSettings != other.mIndividualLayerSettings
442  || mScaleDependencyMode != other.mScaleDependencyMode
443  || mMinimumScale != other.mMinimumScale
444  || mMaximumScale != other.mMaximumScale;
445 }
446 
447 void QgsSnappingConfig::readProject( const QDomDocument &doc )
448 {
449  const QDomElement snapSettingsElem = doc.firstChildElement( QStringLiteral( "qgis" ) ).firstChildElement( QStringLiteral( "snapping-settings" ) );
450  if ( snapSettingsElem.isNull() )
451  {
452  readLegacySettings();
453  return;
454  }
455 
456  if ( snapSettingsElem.hasAttribute( QStringLiteral( "enabled" ) ) )
457  mEnabled = snapSettingsElem.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "1" );
458 
459  if ( snapSettingsElem.hasAttribute( QStringLiteral( "mode" ) ) )
460  mMode = static_cast< SnappingMode >( snapSettingsElem.attribute( QStringLiteral( "mode" ) ).toInt() );
461 
462  if ( snapSettingsElem.hasAttribute( QStringLiteral( "type" ) ) )
463  {
464  const int type = snapSettingsElem.attribute( QStringLiteral( "type" ) ).toInt();
465  const QDomElement versionElem = doc.firstChildElement( QStringLiteral( "qgis" ) );
466  QString version;
467  bool before3_14 = false;
468  if ( versionElem.hasAttribute( QStringLiteral( "version" ) ) )
469  {
470  version = versionElem.attribute( QStringLiteral( "version" ) );
471  const QRegularExpression re( QStringLiteral( "([\\d]+)\\.([\\d]+)" ) );
472  const QRegularExpressionMatch match = re.match( version );
473  if ( match.hasMatch() )
474  {
475  if ( ( match.captured( 1 ).toInt() <= 3 ) && ( match.captured( 2 ).toInt() <= 12 ) )
476  before3_14 = true;
477  }
478  }
479  if ( before3_14 )
480  {
481  // BEFORE 3.12:
482  // 1 = vertex
483  // 2 = vertexandsegment
484  // 3 = segment
485  switch ( type )
486  {
487  case 1:
488  mType = VertexFlag;
489  break;
490  case 2:
491  mType = static_cast<QgsSnappingConfig::SnappingTypeFlag>( QgsSnappingConfig::VertexFlag | QgsSnappingConfig::SegmentFlag );
492  break;
493  case 3:
494  mType = SegmentFlag;
495  break;
496  default:
497  mType = NoSnapFlag;
498  break;
499  }
500  }
501  else
502  mType = static_cast<QgsSnappingConfig::SnappingTypeFlag>( type );
503  }
504 
505  if ( snapSettingsElem.hasAttribute( QStringLiteral( "tolerance" ) ) )
506  mTolerance = snapSettingsElem.attribute( QStringLiteral( "tolerance" ) ).toDouble();
507 
508  if ( snapSettingsElem.hasAttribute( QStringLiteral( "scaleDependencyMode" ) ) )
509  mScaleDependencyMode = static_cast<QgsSnappingConfig::ScaleDependencyMode>( snapSettingsElem.attribute( QStringLiteral( "scaleDependencyMode" ) ).toInt() );
510 
511  if ( snapSettingsElem.hasAttribute( QStringLiteral( "minScale" ) ) )
512  mMinimumScale = snapSettingsElem.attribute( QStringLiteral( "minScale" ) ).toDouble();
513 
514  if ( snapSettingsElem.hasAttribute( QStringLiteral( "maxScale" ) ) )
515  mMaximumScale = snapSettingsElem.attribute( QStringLiteral( "maxScale" ) ).toDouble();
516 
517  if ( snapSettingsElem.hasAttribute( QStringLiteral( "unit" ) ) )
518  mUnits = static_cast< QgsTolerance::UnitType >( snapSettingsElem.attribute( QStringLiteral( "unit" ) ).toInt() );
519 
520  if ( snapSettingsElem.hasAttribute( QStringLiteral( "intersection-snapping" ) ) )
521  mIntersectionSnapping = snapSettingsElem.attribute( QStringLiteral( "intersection-snapping" ) ) == QLatin1String( "1" );
522 
523  if ( snapSettingsElem.hasAttribute( QStringLiteral( "self-snapping" ) ) )
524  mSelfSnapping = snapSettingsElem.attribute( QStringLiteral( "self-snapping" ) ) == QLatin1String( "1" );
525 
526  // do not clear the settings as they must be automatically synchronized with current layers
527  const QDomNodeList nodes = snapSettingsElem.elementsByTagName( QStringLiteral( "individual-layer-settings" ) );
528  if ( nodes.count() )
529  {
530  const QDomNode node = nodes.item( 0 );
531  const QDomNodeList settingNodes = node.childNodes();
532  const int layerCount = settingNodes.count();
533  for ( int i = 0; i < layerCount; ++i )
534  {
535  const QDomElement settingElement = settingNodes.at( i ).toElement();
536  if ( settingElement.tagName() != QLatin1String( "layer-setting" ) )
537  {
538  QgsLogger::warning( QApplication::translate( "QgsProjectSnappingSettings", "Cannot read individual settings. Unexpected tag '%1'" ).arg( settingElement.tagName() ) );
539  continue;
540  }
541 
542  const QString layerId = settingElement.attribute( QStringLiteral( "id" ) );
543  const bool enabled = settingElement.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "1" );
544  const QgsSnappingConfig::SnappingTypeFlag type = static_cast<QgsSnappingConfig::SnappingTypeFlag>( settingElement.attribute( QStringLiteral( "type" ) ).toInt() );
545  const double tolerance = settingElement.attribute( QStringLiteral( "tolerance" ) ).toDouble();
546  const QgsTolerance::UnitType units = static_cast< QgsTolerance::UnitType >( settingElement.attribute( QStringLiteral( "units" ) ).toInt() );
547  const double minScale = settingElement.attribute( QStringLiteral( "minScale" ) ).toDouble();
548  const double maxScale = settingElement.attribute( QStringLiteral( "maxScale" ) ).toDouble();
549 
550  QgsMapLayer *ml = mProject->mapLayer( layerId );
551  if ( !ml || ml->type() != QgsMapLayerType::VectorLayer )
552  continue;
553 
554  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
555 
556  const IndividualLayerSettings setting = IndividualLayerSettings( enabled, type, tolerance, units, minScale, maxScale );
557  mIndividualLayerSettings.insert( vl, setting );
558  }
559  }
560 }
561 
562 void QgsSnappingConfig::writeProject( QDomDocument &doc )
563 {
564  QDomElement snapSettingsElem = doc.createElement( QStringLiteral( "snapping-settings" ) );
565  snapSettingsElem.setAttribute( QStringLiteral( "enabled" ), QString::number( mEnabled ) );
566  snapSettingsElem.setAttribute( QStringLiteral( "mode" ), static_cast<int>( mMode ) );
567  snapSettingsElem.setAttribute( QStringLiteral( "type" ), static_cast<int>( mType ) );
568  snapSettingsElem.setAttribute( QStringLiteral( "tolerance" ), mTolerance );
569  snapSettingsElem.setAttribute( QStringLiteral( "unit" ), static_cast<int>( mUnits ) );
570  snapSettingsElem.setAttribute( QStringLiteral( "intersection-snapping" ), QString::number( mIntersectionSnapping ) );
571  snapSettingsElem.setAttribute( QStringLiteral( "self-snapping" ), QString::number( mSelfSnapping ) );
572  snapSettingsElem.setAttribute( QStringLiteral( "scaleDependencyMode" ), QString::number( mScaleDependencyMode ) );
573  snapSettingsElem.setAttribute( QStringLiteral( "minScale" ), mMinimumScale );
574  snapSettingsElem.setAttribute( QStringLiteral( "maxScale" ), mMaximumScale );
575 
576  QDomElement ilsElement = doc.createElement( QStringLiteral( "individual-layer-settings" ) );
577  QHash<QgsVectorLayer *, IndividualLayerSettings>::const_iterator layerIt = mIndividualLayerSettings.constBegin();
578  for ( ; layerIt != mIndividualLayerSettings.constEnd(); ++layerIt )
579  {
580  const IndividualLayerSettings &setting = layerIt.value();
581 
582  QDomElement layerElement = doc.createElement( QStringLiteral( "layer-setting" ) );
583  layerElement.setAttribute( QStringLiteral( "id" ), layerIt.key()->id() );
584  layerElement.setAttribute( QStringLiteral( "enabled" ), QString::number( setting.enabled() ) );
585  layerElement.setAttribute( QStringLiteral( "type" ), static_cast<int>( setting.typeFlag() ) );
586  layerElement.setAttribute( QStringLiteral( "tolerance" ), setting.tolerance() );
587  layerElement.setAttribute( QStringLiteral( "units" ), static_cast<int>( setting.units() ) );
588  layerElement.setAttribute( QStringLiteral( "minScale" ), setting.minimumScale() );
589  layerElement.setAttribute( QStringLiteral( "maxScale" ), setting.maximumScale() );
590  ilsElement.appendChild( layerElement );
591  }
592  snapSettingsElem.appendChild( ilsElement );
593 
594  doc.firstChildElement( QStringLiteral( "qgis" ) ).appendChild( snapSettingsElem );
595 }
596 
597 bool QgsSnappingConfig::addLayers( const QList<QgsMapLayer *> &layers )
598 {
599  bool changed = false;
600  const bool enabled = QgsSettingsRegistryCore::settingsDigitizingDefaultSnapEnabled.value( QString(), true, true );
601  const QgsSnappingConfig::SnappingTypeFlag type = QgsSettingsRegistryCore::settingsDigitizingDefaultSnapType.value();
602  const double tolerance = QgsSettingsRegistryCore::settingsDigitizingDefaultSnappingTolerance.value();
603  const QgsTolerance::UnitType units = QgsSettingsRegistryCore::settingsDigitizingDefaultSnappingToleranceUnit.value();
604 
605  const auto constLayers = layers;
606  for ( QgsMapLayer *ml : constLayers )
607  {
608  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
609  if ( vl && vl->isSpatial() )
610  {
611  mIndividualLayerSettings.insert( vl, IndividualLayerSettings( enabled, type, tolerance, units, 0.0, 0.0 ) );
612  changed = true;
613  }
614  }
615  return changed;
616 }
617 
618 bool QgsSnappingConfig::removeLayers( const QList<QgsMapLayer *> &layers )
619 {
620  bool changed = false;
621  const auto constLayers = layers;
622  for ( QgsMapLayer *ml : constLayers )
623  {
624  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
625  if ( vl )
626  {
627  mIndividualLayerSettings.remove( vl );
628  changed = true;
629  }
630  }
631  return changed;
632 }
633 
634 void QgsSnappingConfig::readLegacySettings()
635 {
636  //
637  mMode = ActiveLayer;
638 
639  const QString snapMode = mProject->readEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/SnappingMode" ) );
640 
641  mTolerance = mProject->readDoubleEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/DefaultSnapTolerance" ), 0 );
642  mUnits = static_cast< QgsTolerance::UnitType >( mProject->readNumEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/DefaultSnapToleranceUnit" ), QgsTolerance::ProjectUnits ) );
643 
644  mIntersectionSnapping = mProject->readNumEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/IntersectionSnapping" ), 0 );
645 
646  //read snapping settings from project
647  const QStringList layerIdList = mProject->readListEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/LayerSnappingList" ), QStringList() );
648  const QStringList enabledList = mProject->readListEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/LayerSnappingEnabledList" ), QStringList() );
649  const QStringList toleranceList = mProject->readListEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/LayerSnappingToleranceList" ), QStringList() );
650  const QStringList toleranceUnitList = mProject->readListEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/LayerSnappingToleranceUnitList" ), QStringList() );
651  const QStringList snapToList = mProject->readListEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/LayerSnapToList" ), QStringList() );
652 
653  // lists must have the same size, otherwise something is wrong
654  if ( layerIdList.size() != enabledList.size() ||
655  layerIdList.size() != toleranceList.size() ||
656  layerIdList.size() != toleranceUnitList.size() ||
657  layerIdList.size() != snapToList.size() )
658  return;
659 
660  // Use snapping information from the project
661  if ( snapMode == QLatin1String( "current_layer" ) )
662  mMode = ActiveLayer;
663  else if ( snapMode == QLatin1String( "all_layers" ) )
664  mMode = AllLayers;
665  else // either "advanced" or empty (for background compatibility)
666  mMode = AdvancedConfiguration;
667 
668  // load layers, tolerances, snap type
669  QStringList::const_iterator layerIt( layerIdList.constBegin() );
670  QStringList::const_iterator tolIt( toleranceList.constBegin() );
671  QStringList::const_iterator tolUnitIt( toleranceUnitList.constBegin() );
672  QStringList::const_iterator snapIt( snapToList.constBegin() );
673  QStringList::const_iterator enabledIt( enabledList.constBegin() );
674  for ( ; layerIt != layerIdList.constEnd(); ++layerIt, ++tolIt, ++tolUnitIt, ++snapIt, ++enabledIt )
675  {
676  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mProject->mapLayer( *layerIt ) );
677  if ( !vlayer || !vlayer->isSpatial() )
678  continue;
679 
680  const QgsSnappingConfig::SnappingTypeFlag t( *snapIt == QLatin1String( "to_vertex" ) ? VertexFlag :
681  ( *snapIt == QLatin1String( "to_segment" ) ? SegmentFlag :
682  static_cast<QgsSnappingConfig::SnappingTypeFlag>( QgsSnappingConfig::VertexFlag | QgsSnappingConfig::SegmentFlag )
683  )
684  );
685 
686  mIndividualLayerSettings.insert( vlayer, IndividualLayerSettings( *enabledIt == QLatin1String( "enabled" ), t, tolIt->toDouble(), static_cast<QgsTolerance::UnitType>( tolUnitIt->toInt() ), 0.0, 0.0 ) );
687  }
688 
689  const QString snapType = mProject->readEntry( QStringLiteral( "Digitizing" ), QStringLiteral( "/DefaultSnapType" ), QStringLiteral( "off" ) );
690  mEnabled = true;
691  if ( snapType == QLatin1String( "to segment" ) )
692  mType = SegmentFlag;
693  else if ( snapType == QLatin1String( "to vertex and segment" ) )
694  mType = static_cast<QgsSnappingConfig::SnappingTypeFlag>( QgsSnappingConfig::VertexFlag | QgsSnappingConfig::SegmentFlag );
695  else if ( snapType == QLatin1String( "to vertex" ) )
696  mType = VertexFlag;
697  else if ( mMode != AdvancedConfiguration ) // Type is off but mode is advanced
698  {
699  mEnabled = false;
700  }
701 }
702 
704 {
705  return mProject;
706 }
707 
709 {
710  if ( mProject != project )
711  mProject = project;
712 
713  reset();
714 }
715 
717 {
718  return mMinimumScale;
719 }
720 
721 void QgsSnappingConfig::setMinimumScale( double minScale )
722 {
723  mMinimumScale = minScale;
724 }
725 
727 {
728  return mMaximumScale;
729 }
730 
731 void QgsSnappingConfig::setMaximumScale( double maxScale )
732 {
733  mMaximumScale = maxScale;
734 }
735 
737 {
738  mScaleDependencyMode = mode;
739 }
740 
742 {
743  return mScaleDependencyMode;
744 }
745 
746 
747 
748 
749 
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.
Definition: qgslogger.cpp:122
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QgsMapLayerType type
Definition: qgsmaplayer.h:80
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:101
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.
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
void setUnits(QgsTolerance::UnitType units)
Sets the type of units.
bool operator!=(const QgsSnappingConfig::IndividualLayerSettings &other) const
Compare this configuration to other.
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.
QgsTolerance::UnitType units() const
Returns the type of units.
void setMinimumScale(double minScale)
Sets the min scale value on which snapping is used, 0.0 disable scale limit.
void setMaximumScale(double maxScale)
Sets the max scale value on which snapping is used, 0.0 disable scale limit.
bool enabled() const
Returns if snapping is enabled.
void setTypeFlag(QgsSnappingConfig::SnappingTypeFlag type)
define the type of snapping
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.
QgsSnappingConfig::SnappingTypeFlag typeFlag() const
Returns the flags type (vertices | segments | area | centroid | middle)
Q_DECL_DEPRECATED void setType(QgsSnappingConfig::SnappingType type)
define the type of snapping
void setTolerance(double tolerance)
Sets the tolerance.
This is a container for configuration of the snapping of the project.
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.
@ CentroidFlag
On centroid.
@ SegmentFlag
On segments.
@ NoSnapFlag
No snapping.
@ VertexFlag
On vertices.
@ LineEndpointFlag
Start or end points of lines, or first vertex in polygon rings only (since QGIS 3....
@ MiddleOfSegmentFlag
On Middle segment.
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.
QgsTolerance::UnitType units() const
Returns the type of units.
void setUnits(QgsTolerance::UnitType units)
Sets the type of units.
bool intersectionSnapping() const
Returns if the snapping on intersection is enabled.
void setTypeFlag(QgsSnappingConfig::SnappingTypeFlag type)
define the type of snapping
void setMode(SnappingMode mode)
define the mode of snapping
ScaleDependencyMode
ScaleDependencyMode the scale dependency mode of snapping.
@ Disabled
No scale dependency.
double minimumScale() const
Returns the min scale (i.e.
double tolerance() const
Returns the tolerance.
Q_GADGET QgsProject * project
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.
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.
SnappingMode mode() const
Returns the mode (all layers, active layer, per layer settings)
static QIcon snappingTypeFlagToIcon(SnappingTypeFlag type)
Convenient method to return an icon corresponding to the enum type QgsSnappingConfig::SnappingTypeFla...
bool operator!=(const QgsSnappingConfig &other) const
Compare this configuration to other.
QgsSnappingConfig::SnappingTypeFlag typeFlag() const
Returns the flags type (vertices | segments | area | centroid | middle)
bool operator==(const QgsSnappingConfig &other) const
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.
static QString snappingTypeFlagToString(SnappingTypeFlag type)
Convenient method to returns the translated name of the enum type QgsSnappingConfig::SnappingTypeFlag...
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.
UnitType
Type of unit of tolerance value from settings.
Definition: qgstolerance.h:42
@ ProjectUnits
Map (project) units. Added in 2.8.
Definition: qgstolerance.h:48
@ LayerUnits
Layer unit value.
Definition: qgstolerance.h:44
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
Definition: qgis.h:1730
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:1729