LCOV - code coverage report
Current view: top level - core - qgssnappingconfig.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 66 444 14.9 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

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

Generated by: LCOV version 1.14