LCOV - code coverage report
Current view: top level - core/vector - qgsvectorlayer.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 352 3404 10.3 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                                qgsvectorlayer.cpp
       3                 :            :                               --------------------
       4                 :            :           begin                : Oct 29, 2003
       5                 :            :           copyright            : (C) 2003 by Gary E.Sherman
       6                 :            :           email                : sherman at mrcc.com
       7                 :            : 
       8                 :            :   This class implements a generic means to display vector layers. The features
       9                 :            :   and attributes are read from the data store using a "data provider" plugin.
      10                 :            :   QgsVectorLayer can be used with any data store for which an appropriate
      11                 :            :   plugin is available.
      12                 :            : 
      13                 :            : ***************************************************************************/
      14                 :            : 
      15                 :            : /***************************************************************************
      16                 :            :  *                                                                         *
      17                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      18                 :            :  *   it under the terms of the GNU General Public License as published by  *
      19                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      20                 :            :  *   (at your option) any later version.                                   *
      21                 :            :  *                                                                         *
      22                 :            :  ***************************************************************************/
      23                 :            : 
      24                 :            : #include <limits>
      25                 :            : 
      26                 :            : #include <QDir>
      27                 :            : #include <QFile>
      28                 :            : #include <QImage>
      29                 :            : #include <QPainter>
      30                 :            : #include <QPainterPath>
      31                 :            : #include <QPolygonF>
      32                 :            : #include <QProgressDialog>
      33                 :            : #include <QString>
      34                 :            : #include <QDomNode>
      35                 :            : #include <QVector>
      36                 :            : #include <QStringBuilder>
      37                 :            : #include <QUrl>
      38                 :            : #include <QUndoCommand>
      39                 :            : #include <QUrlQuery>
      40                 :            : #include <QUuid>
      41                 :            : 
      42                 :            : #include "qgssettings.h"
      43                 :            : #include "qgsvectorlayer.h"
      44                 :            : #include "qgsactionmanager.h"
      45                 :            : #include "qgis.h" //for globals
      46                 :            : #include "qgsapplication.h"
      47                 :            : #include "qgsclipper.h"
      48                 :            : #include "qgsconditionalstyle.h"
      49                 :            : #include "qgscoordinatereferencesystem.h"
      50                 :            : #include "qgscoordinatetransform.h"
      51                 :            : #include "qgsexception.h"
      52                 :            : #include "qgscurve.h"
      53                 :            : #include "qgsdatasourceuri.h"
      54                 :            : #include "qgsexpressionfieldbuffer.h"
      55                 :            : #include "qgsexpressionnodeimpl.h"
      56                 :            : #include "qgsfeature.h"
      57                 :            : #include "qgsfeaturerequest.h"
      58                 :            : #include "qgsfields.h"
      59                 :            : #include "qgsmaplayerfactory.h"
      60                 :            : #include "qgsgeometry.h"
      61                 :            : #include "qgslayermetadataformatter.h"
      62                 :            : #include "qgslogger.h"
      63                 :            : #include "qgsmaplayerlegend.h"
      64                 :            : #include "qgsmaptopixel.h"
      65                 :            : #include "qgsmessagelog.h"
      66                 :            : #include "qgsogcutils.h"
      67                 :            : #include "qgspainting.h"
      68                 :            : #include "qgspointxy.h"
      69                 :            : #include "qgsproject.h"
      70                 :            : #include "qgsproviderregistry.h"
      71                 :            : #include "qgsrectangle.h"
      72                 :            : #include "qgsrelationmanager.h"
      73                 :            : #include "qgsweakrelation.h"
      74                 :            : #include "qgsrendercontext.h"
      75                 :            : #include "qgsvectordataprovider.h"
      76                 :            : #include "qgsvectorlayertemporalproperties.h"
      77                 :            : #include "qgsvectorlayereditbuffer.h"
      78                 :            : #include "qgsvectorlayereditpassthrough.h"
      79                 :            : #include "qgsvectorlayereditutils.h"
      80                 :            : #include "qgsvectorlayerfeatureiterator.h"
      81                 :            : #include "qgsvectorlayerjoinbuffer.h"
      82                 :            : #include "qgsvectorlayerlabeling.h"
      83                 :            : #include "qgsvectorlayerrenderer.h"
      84                 :            : #include "qgsvectorlayerundocommand.h"
      85                 :            : #include "qgsvectorlayerfeaturecounter.h"
      86                 :            : #include "qgspoint.h"
      87                 :            : #include "qgsrenderer.h"
      88                 :            : #include "qgssymbollayer.h"
      89                 :            : #include "qgssinglesymbolrenderer.h"
      90                 :            : #include "qgsdiagramrenderer.h"
      91                 :            : #include "qgsstyle.h"
      92                 :            : #include "qgspallabeling.h"
      93                 :            : #include "qgsrulebasedlabeling.h"
      94                 :            : #include "qgssimplifymethod.h"
      95                 :            : #include "qgsstoredexpressionmanager.h"
      96                 :            : #include "qgsexpressioncontext.h"
      97                 :            : #include "qgsfeedback.h"
      98                 :            : #include "qgsxmlutils.h"
      99                 :            : #include "qgsunittypes.h"
     100                 :            : #include "qgstaskmanager.h"
     101                 :            : #include "qgstransaction.h"
     102                 :            : #include "qgsauxiliarystorage.h"
     103                 :            : #include "qgsgeometryoptions.h"
     104                 :            : #include "qgsexpressioncontextutils.h"
     105                 :            : #include "qgsruntimeprofiler.h"
     106                 :            : #include "qgsfeaturerenderergenerator.h"
     107                 :            : #include "qgsvectorlayerutils.h"
     108                 :            : 
     109                 :            : #include "diagram/qgsdiagram.h"
     110                 :            : 
     111                 :            : #ifdef TESTPROVIDERLIB
     112                 :            : #include <dlfcn.h>
     113                 :            : #endif
     114                 :            : 
     115                 :            : typedef bool saveStyle_t(
     116                 :            :   const QString &uri,
     117                 :            :   const QString &qmlStyle,
     118                 :            :   const QString &sldStyle,
     119                 :            :   const QString &styleName,
     120                 :            :   const QString &styleDescription,
     121                 :            :   const QString &uiFileContent,
     122                 :            :   bool useAsDefault,
     123                 :            :   QString &errCause
     124                 :            : );
     125                 :            : 
     126                 :            : typedef QString loadStyle_t(
     127                 :            :   const QString &uri,
     128                 :            :   QString &errCause
     129                 :            : );
     130                 :            : 
     131                 :            : typedef int listStyles_t(
     132                 :            :   const QString &uri,
     133                 :            :   QStringList &ids,
     134                 :            :   QStringList &names,
     135                 :            :   QStringList &descriptions,
     136                 :            :   QString &errCause
     137                 :            : );
     138                 :            : 
     139                 :            : typedef QString getStyleById_t(
     140                 :            :   const QString &uri,
     141                 :            :   QString styleID,
     142                 :            :   QString &errCause
     143                 :            : );
     144                 :            : 
     145                 :            : typedef bool deleteStyleById_t(
     146                 :            :   const QString &uri,
     147                 :            :   QString styleID,
     148                 :            :   QString &errCause
     149                 :            : );
     150                 :            : 
     151                 :            : 
     152                 :        390 : QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
     153                 :            :                                 const QString &baseName,
     154                 :            :                                 const QString &providerKey,
     155                 :            :                                 const QgsVectorLayer::LayerOptions &options )
     156                 :         78 :   : QgsMapLayer( QgsMapLayerType::VectorLayer, baseName, vectorLayerPath )
     157                 :         78 :   , mTemporalProperties( new QgsVectorLayerTemporalProperties( this ) )
     158                 :         78 :   , mServerProperties( new QgsVectorLayerServerProperties( this ) )
     159                 :         78 :   , mAuxiliaryLayer( nullptr )
     160                 :         78 :   , mAuxiliaryLayerKey( QString() )
     161                 :         78 :   , mReadExtentFromXml( options.readExtentFromXml )
     162                 :        468 : {
     163                 :         78 :   mShouldValidateCrs = !options.skipCrsValidation;
     164                 :            : 
     165                 :         78 :   if ( options.fallbackCrs.isValid() )
     166                 :          0 :     setCrs( options.fallbackCrs, false );
     167                 :         78 :   mWkbType = options.fallbackWkbType;
     168                 :            : 
     169                 :         78 :   setProviderType( providerKey );
     170                 :            : 
     171                 :         78 :   mGeometryOptions = std::make_unique<QgsGeometryOptions>();
     172                 :         78 :   mActions = new QgsActionManager( this );
     173                 :         78 :   mConditionalStyles = new QgsConditionalLayerStyles( this );
     174                 :         78 :   mStoredExpressionManager = new QgsStoredExpressionManager();
     175                 :         78 :   mStoredExpressionManager->setParent( this );
     176                 :            : 
     177                 :         78 :   mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
     178                 :         78 :   mJoinBuffer->setParent( this );
     179                 :         78 :   connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
     180                 :            : 
     181                 :         78 :   mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
     182                 :            :   // if we're given a provider type, try to create and bind one to this layer
     183                 :         78 :   if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
     184                 :            :   {
     185                 :         78 :     QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
     186                 :         78 :     setDataSource( vectorLayerPath, baseName, providerKey, providerOptions, options.loadDefaultStyle );
     187                 :         78 :   }
     188                 :            : 
     189                 :        162 :   for ( const QgsField &field : std::as_const( mFields ) )
     190                 :            :   {
     191                 :         84 :     mAttributeAliasMap.insert( field.name(), QString() );
     192                 :            :   }
     193                 :            : 
     194                 :         78 :   if ( isValid() )
     195                 :            :   {
     196                 :         78 :     mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
     197                 :         78 :     if ( !mTemporalProperties->isActive() )
     198                 :            :     {
     199                 :            :       // didn't populate temporal properties from provider metadata, so at least try to setup some initially nice
     200                 :            :       // selections
     201                 :         78 :       mTemporalProperties->guessDefaultsFromFields( mFields );
     202                 :         78 :     }
     203                 :         78 :   }
     204                 :            : 
     205                 :         78 :   connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { triggerRepaint(); } );
     206                 :         78 :   connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
     207                 :            : 
     208                 :         78 :   connect( this, &QgsVectorLayer::subsetStringChanged, this, &QgsMapLayer::configChanged );
     209                 :         78 :   connect( this, &QgsVectorLayer::dataSourceChanged, this, &QgsVectorLayer::supportsEditingChanged );
     210                 :         78 :   connect( this, &QgsVectorLayer::readOnlyChanged, this, &QgsVectorLayer::supportsEditingChanged );
     211                 :            : 
     212                 :            :   // Default simplify drawing settings
     213                 :         78 :   QgsSettings settings;
     214                 :        156 :   mSimplifyMethod.setSimplifyHints( settings.flagValue( QStringLiteral( "qgis/simplifyDrawingHints" ), mSimplifyMethod.simplifyHints(), QgsSettings::NoSection ) );
     215                 :        156 :   mSimplifyMethod.setSimplifyAlgorithm( settings.enumValue( QStringLiteral( "qgis/simplifyAlgorithm" ), mSimplifyMethod.simplifyAlgorithm() ) );
     216                 :        156 :   mSimplifyMethod.setThreshold( settings.value( QStringLiteral( "qgis/simplifyDrawingTol" ), mSimplifyMethod.threshold() ).toFloat() );
     217                 :        156 :   mSimplifyMethod.setForceLocalOptimization( settings.value( QStringLiteral( "qgis/simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ).toBool() );
     218                 :        156 :   mSimplifyMethod.setMaximumScale( settings.value( QStringLiteral( "qgis/simplifyMaxScale" ), mSimplifyMethod.maximumScale() ).toFloat() );
     219                 :         78 : } // QgsVectorLayer ctor
     220                 :            : 
     221                 :            : 
     222                 :        124 : QgsVectorLayer::~QgsVectorLayer()
     223                 :        124 : {
     224                 :         62 :   emit willBeDeleted();
     225                 :            : 
     226                 :         62 :   setValid( false );
     227                 :            : 
     228                 :         62 :   delete mDataProvider;
     229                 :         62 :   delete mEditBuffer;
     230                 :         62 :   delete mJoinBuffer;
     231                 :         62 :   delete mExpressionFieldBuffer;
     232                 :         62 :   delete mLabeling;
     233                 :         62 :   delete mDiagramLayerSettings;
     234                 :         62 :   delete mDiagramRenderer;
     235                 :            : 
     236                 :         62 :   delete mActions;
     237                 :            : 
     238                 :         62 :   delete mRenderer;
     239                 :         62 :   delete mConditionalStyles;
     240                 :         62 :   delete mStoredExpressionManager;
     241                 :            : 
     242                 :         62 :   if ( mFeatureCounter )
     243                 :          0 :     mFeatureCounter->cancel();
     244                 :            : 
     245                 :         62 :   qDeleteAll( mRendererGenerators );
     246                 :        124 : }
     247                 :            : 
     248                 :          0 : QgsVectorLayer *QgsVectorLayer::clone() const
     249                 :            : {
     250                 :          0 :   QgsVectorLayer::LayerOptions options;
     251                 :            :   // We get the data source string from the provider when
     252                 :            :   // possible because some providers may have changed it
     253                 :            :   // directly (memory provider does that).
     254                 :          0 :   QString dataSource;
     255                 :          0 :   if ( mDataProvider )
     256                 :            :   {
     257                 :          0 :     dataSource = mDataProvider->dataSourceUri();
     258                 :          0 :     options.transformContext = mDataProvider->transformContext();
     259                 :          0 :   }
     260                 :            :   else
     261                 :            :   {
     262                 :          0 :     dataSource = source();
     263                 :            :   }
     264                 :          0 :   QgsVectorLayer *layer = new QgsVectorLayer( dataSource, name(), mProviderKey, options );
     265                 :          0 :   if ( mDataProvider && layer->dataProvider() )
     266                 :            :   {
     267                 :          0 :     layer->dataProvider()->handlePostCloneOperations( mDataProvider );
     268                 :          0 :   }
     269                 :          0 :   QgsMapLayer::clone( layer );
     270                 :            : 
     271                 :          0 :   QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
     272                 :          0 :   const auto constJoins = joins;
     273                 :          0 :   for ( const QgsVectorLayerJoinInfo &join : constJoins )
     274                 :            :   {
     275                 :            :     // do not copy join information for auxiliary layer
     276                 :          0 :     if ( !auxiliaryLayer()
     277                 :          0 :          || ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() ) )
     278                 :          0 :       layer->addJoin( join );
     279                 :            :   }
     280                 :            : 
     281                 :          0 :   layer->setProviderEncoding( dataProvider()->encoding() );
     282                 :          0 :   layer->setDisplayExpression( displayExpression() );
     283                 :          0 :   layer->setMapTipTemplate( mapTipTemplate() );
     284                 :          0 :   layer->setReadOnly( isReadOnly() );
     285                 :          0 :   layer->selectByIds( selectedFeatureIds() );
     286                 :          0 :   layer->setAttributeTableConfig( attributeTableConfig() );
     287                 :          0 :   layer->setFeatureBlendMode( featureBlendMode() );
     288                 :          0 :   layer->setReadExtentFromXml( readExtentFromXml() );
     289                 :            : 
     290                 :          0 :   const auto constActions = actions()->actions();
     291                 :          0 :   for ( const QgsAction &action : constActions )
     292                 :            :   {
     293                 :          0 :     layer->actions()->addAction( action );
     294                 :            :   }
     295                 :            : 
     296                 :          0 :   if ( auto *lRenderer = renderer() )
     297                 :            :   {
     298                 :          0 :     layer->setRenderer( lRenderer->clone() );
     299                 :          0 :   }
     300                 :            : 
     301                 :          0 :   if ( auto *lLabeling = labeling() )
     302                 :            :   {
     303                 :          0 :     layer->setLabeling( lLabeling->clone() );
     304                 :          0 :   }
     305                 :          0 :   layer->setLabelsEnabled( labelsEnabled() );
     306                 :            : 
     307                 :          0 :   layer->setSimplifyMethod( simplifyMethod() );
     308                 :            : 
     309                 :          0 :   if ( auto *lDiagramRenderer = diagramRenderer() )
     310                 :            :   {
     311                 :          0 :     layer->setDiagramRenderer( lDiagramRenderer->clone() );
     312                 :          0 :   }
     313                 :            : 
     314                 :          0 :   if ( auto *lDiagramLayerSettings = diagramLayerSettings() )
     315                 :            :   {
     316                 :          0 :     layer->setDiagramLayerSettings( *lDiagramLayerSettings );
     317                 :          0 :   }
     318                 :            : 
     319                 :          0 :   for ( int i = 0; i < fields().count(); i++ )
     320                 :            :   {
     321                 :          0 :     layer->setFieldAlias( i, attributeAlias( i ) );
     322                 :          0 :     layer->setFieldConfigurationFlags( i, fieldConfigurationFlags( i ) );
     323                 :          0 :     layer->setEditorWidgetSetup( i, editorWidgetSetup( i ) );
     324                 :          0 :     layer->setConstraintExpression( i, constraintExpression( i ), constraintDescription( i ) );
     325                 :          0 :     layer->setDefaultValueDefinition( i, defaultValueDefinition( i ) );
     326                 :            : 
     327                 :          0 :     QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> constraints = fieldConstraintsAndStrength( i );
     328                 :          0 :     auto constraintIt = constraints.constBegin();
     329                 :          0 :     for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
     330                 :            :     {
     331                 :          0 :       layer->setFieldConstraint( i, constraintIt.key(), constraintIt.value() );
     332                 :          0 :     }
     333                 :            : 
     334                 :          0 :     if ( fields().fieldOrigin( i ) == QgsFields::OriginExpression )
     335                 :            :     {
     336                 :          0 :       layer->addExpressionField( expressionField( i ), fields().at( i ) );
     337                 :          0 :     }
     338                 :          0 :   }
     339                 :            : 
     340                 :          0 :   layer->setEditFormConfig( editFormConfig() );
     341                 :            : 
     342                 :          0 :   if ( auto *lAuxiliaryLayer = auxiliaryLayer() )
     343                 :          0 :     layer->setAuxiliaryLayer( lAuxiliaryLayer->clone( layer ) );
     344                 :            : 
     345                 :          0 :   return layer;
     346                 :          0 : }
     347                 :            : 
     348                 :          0 : QString QgsVectorLayer::storageType() const
     349                 :            : {
     350                 :          0 :   if ( mDataProvider )
     351                 :            :   {
     352                 :          0 :     return mDataProvider->storageType();
     353                 :            :   }
     354                 :          0 :   return QString();
     355                 :          0 : }
     356                 :            : 
     357                 :            : 
     358                 :          0 : QString QgsVectorLayer::capabilitiesString() const
     359                 :            : {
     360                 :          0 :   if ( mDataProvider )
     361                 :            :   {
     362                 :          0 :     return mDataProvider->capabilitiesString();
     363                 :            :   }
     364                 :          0 :   return QString();
     365                 :          0 : }
     366                 :            : 
     367                 :          0 : QString QgsVectorLayer::dataComment() const
     368                 :            : {
     369                 :          0 :   if ( mDataProvider )
     370                 :            :   {
     371                 :          0 :     return mDataProvider->dataComment();
     372                 :            :   }
     373                 :          0 :   return QString();
     374                 :          0 : }
     375                 :            : 
     376                 :          0 : QgsCoordinateReferenceSystem QgsVectorLayer::sourceCrs() const
     377                 :            : {
     378                 :          0 :   return crs();
     379                 :            : }
     380                 :            : 
     381                 :          0 : QString QgsVectorLayer::sourceName() const
     382                 :            : {
     383                 :          0 :   return name();
     384                 :            : }
     385                 :            : 
     386                 :          0 : void QgsVectorLayer::reload()
     387                 :            : {
     388                 :          0 :   if ( mDataProvider )
     389                 :            :   {
     390                 :          0 :     mDataProvider->reloadData();
     391                 :          0 :     updateFields();
     392                 :          0 :   }
     393                 :          0 : }
     394                 :            : 
     395                 :          0 : QgsMapLayerRenderer *QgsVectorLayer::createMapRenderer( QgsRenderContext &rendererContext )
     396                 :            : {
     397                 :          0 :   return new QgsVectorLayerRenderer( this, rendererContext );
     398                 :          0 : }
     399                 :            : 
     400                 :            : 
     401                 :          0 : void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int m )
     402                 :            : {
     403                 :          0 :   if ( type == QgsVectorLayer::SemiTransparentCircle )
     404                 :            :   {
     405                 :          0 :     p.setPen( QColor( 50, 100, 120, 200 ) );
     406                 :          0 :     p.setBrush( QColor( 200, 200, 210, 120 ) );
     407                 :          0 :     p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
     408                 :          0 :   }
     409                 :          0 :   else if ( type == QgsVectorLayer::Cross )
     410                 :            :   {
     411                 :          0 :     p.setPen( QColor( 255, 0, 0 ) );
     412                 :          0 :     p.drawLine( x - m, y + m, x + m, y - m );
     413                 :          0 :     p.drawLine( x - m, y - m, x + m, y + m );
     414                 :          0 :   }
     415                 :          0 : }
     416                 :            : 
     417                 :          0 : void QgsVectorLayer::select( QgsFeatureId fid )
     418                 :            : {
     419                 :          0 :   mSelectedFeatureIds.insert( fid );
     420                 :          0 :   mPreviousSelectedFeatureIds.clear();
     421                 :            : 
     422                 :          0 :   emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
     423                 :          0 : }
     424                 :            : 
     425                 :          0 : void QgsVectorLayer::select( const QgsFeatureIds &featureIds )
     426                 :            : {
     427                 :          0 :   mSelectedFeatureIds.unite( featureIds );
     428                 :          0 :   mPreviousSelectedFeatureIds.clear();
     429                 :            : 
     430                 :          0 :   emit selectionChanged( featureIds, QgsFeatureIds(), false );
     431                 :          0 : }
     432                 :            : 
     433                 :          0 : void QgsVectorLayer::deselect( const QgsFeatureId fid )
     434                 :            : {
     435                 :          0 :   mSelectedFeatureIds.remove( fid );
     436                 :          0 :   mPreviousSelectedFeatureIds.clear();
     437                 :            : 
     438                 :          0 :   emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
     439                 :          0 : }
     440                 :            : 
     441                 :          0 : void QgsVectorLayer::deselect( const QgsFeatureIds &featureIds )
     442                 :            : {
     443                 :          0 :   mSelectedFeatureIds.subtract( featureIds );
     444                 :          0 :   mPreviousSelectedFeatureIds.clear();
     445                 :            : 
     446                 :          0 :   emit selectionChanged( QgsFeatureIds(), featureIds, false );
     447                 :          0 : }
     448                 :            : 
     449                 :          0 : void QgsVectorLayer::selectByRect( QgsRectangle &rect, QgsVectorLayer::SelectBehavior behavior )
     450                 :            : {
     451                 :            :   // normalize the rectangle
     452                 :          0 :   rect.normalize();
     453                 :            : 
     454                 :          0 :   QgsFeatureIds newSelection;
     455                 :            : 
     456                 :          0 :   QgsFeatureIterator features = getFeatures( QgsFeatureRequest()
     457                 :          0 :                                 .setFilterRect( rect )
     458                 :          0 :                                 .setFlags( QgsFeatureRequest::ExactIntersect | QgsFeatureRequest::NoGeometry )
     459                 :          0 :                                 .setNoAttributes() );
     460                 :            : 
     461                 :          0 :   QgsFeature feat;
     462                 :          0 :   while ( features.nextFeature( feat ) )
     463                 :            :   {
     464                 :          0 :     newSelection << feat.id();
     465                 :            :   }
     466                 :          0 :   features.close();
     467                 :            : 
     468                 :          0 :   selectByIds( newSelection, behavior );
     469                 :          0 : }
     470                 :            : 
     471                 :          0 : void QgsVectorLayer::selectByExpression( const QString &expression, QgsVectorLayer::SelectBehavior behavior )
     472                 :            : {
     473                 :          0 :   QgsFeatureIds newSelection;
     474                 :            : 
     475                 :          0 :   QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( this ) );
     476                 :            : 
     477                 :          0 :   if ( behavior == SetSelection || behavior == AddToSelection )
     478                 :            :   {
     479                 :          0 :     QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( expression )
     480                 :          0 :                                 .setExpressionContext( context )
     481                 :          0 :                                 .setFlags( QgsFeatureRequest::NoGeometry )
     482                 :          0 :                                 .setNoAttributes();
     483                 :            : 
     484                 :          0 :     QgsFeatureIterator features = getFeatures( request );
     485                 :            : 
     486                 :          0 :     if ( behavior == AddToSelection )
     487                 :            :     {
     488                 :          0 :       newSelection = selectedFeatureIds();
     489                 :          0 :     }
     490                 :          0 :     QgsFeature feat;
     491                 :          0 :     while ( features.nextFeature( feat ) )
     492                 :            :     {
     493                 :          0 :       newSelection << feat.id();
     494                 :            :     }
     495                 :          0 :     features.close();
     496                 :          0 :   }
     497                 :          0 :   else if ( behavior == IntersectSelection || behavior == RemoveFromSelection )
     498                 :            :   {
     499                 :          0 :     QgsExpression exp( expression );
     500                 :          0 :     exp.prepare( &context );
     501                 :            : 
     502                 :          0 :     QgsFeatureIds oldSelection = selectedFeatureIds();
     503                 :          0 :     QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
     504                 :            : 
     505                 :            :     //refine request
     506                 :          0 :     if ( !exp.needsGeometry() )
     507                 :          0 :       request.setFlags( QgsFeatureRequest::NoGeometry );
     508                 :          0 :     request.setSubsetOfAttributes( exp.referencedColumns(), fields() );
     509                 :            : 
     510                 :          0 :     QgsFeatureIterator features = getFeatures( request );
     511                 :          0 :     QgsFeature feat;
     512                 :          0 :     while ( features.nextFeature( feat ) )
     513                 :            :     {
     514                 :          0 :       context.setFeature( feat );
     515                 :          0 :       bool matches = exp.evaluate( &context ).toBool();
     516                 :            : 
     517                 :          0 :       if ( matches && behavior == IntersectSelection )
     518                 :            :       {
     519                 :          0 :         newSelection << feat.id();
     520                 :          0 :       }
     521                 :          0 :       else if ( !matches && behavior == RemoveFromSelection )
     522                 :            :       {
     523                 :          0 :         newSelection << feat.id();
     524                 :          0 :       }
     525                 :            :     }
     526                 :          0 :   }
     527                 :            : 
     528                 :          0 :   selectByIds( newSelection );
     529                 :          0 : }
     530                 :            : 
     531                 :          0 : void QgsVectorLayer::selectByIds( const QgsFeatureIds &ids, QgsVectorLayer::SelectBehavior behavior )
     532                 :            : {
     533                 :          0 :   QgsFeatureIds newSelection;
     534                 :            : 
     535                 :          0 :   switch ( behavior )
     536                 :            :   {
     537                 :            :     case SetSelection:
     538                 :          0 :       newSelection = ids;
     539                 :          0 :       break;
     540                 :            : 
     541                 :            :     case AddToSelection:
     542                 :          0 :       newSelection = mSelectedFeatureIds + ids;
     543                 :          0 :       break;
     544                 :            : 
     545                 :            :     case RemoveFromSelection:
     546                 :          0 :       newSelection = mSelectedFeatureIds - ids;
     547                 :          0 :       break;
     548                 :            : 
     549                 :            :     case IntersectSelection:
     550                 :          0 :       newSelection = mSelectedFeatureIds.intersect( ids );
     551                 :          0 :       break;
     552                 :            :   }
     553                 :            : 
     554                 :          0 :   QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
     555                 :          0 :   mSelectedFeatureIds = newSelection;
     556                 :          0 :   mPreviousSelectedFeatureIds.clear();
     557                 :            : 
     558                 :          0 :   emit selectionChanged( newSelection, deselectedFeatures, true );
     559                 :          0 : }
     560                 :            : 
     561                 :          0 : void QgsVectorLayer::modifySelection( const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds )
     562                 :            : {
     563                 :          0 :   QgsFeatureIds intersectingIds = selectIds & deselectIds;
     564                 :          0 :   if ( !intersectingIds.isEmpty() )
     565                 :            :   {
     566                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." ), 3 );
     567                 :          0 :   }
     568                 :            : 
     569                 :          0 :   mSelectedFeatureIds -= deselectIds;
     570                 :          0 :   mSelectedFeatureIds += selectIds;
     571                 :          0 :   mPreviousSelectedFeatureIds.clear();
     572                 :            : 
     573                 :          0 :   emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
     574                 :          0 : }
     575                 :            : 
     576                 :          0 : void QgsVectorLayer::invertSelection()
     577                 :            : {
     578                 :          0 :   QgsFeatureIds ids = allFeatureIds();
     579                 :          0 :   ids.subtract( mSelectedFeatureIds );
     580                 :          0 :   selectByIds( ids );
     581                 :          0 : }
     582                 :            : 
     583                 :          0 : void QgsVectorLayer::selectAll()
     584                 :            : {
     585                 :          0 :   selectByIds( allFeatureIds() );
     586                 :          0 : }
     587                 :            : 
     588                 :          0 : void QgsVectorLayer::invertSelectionInRectangle( QgsRectangle &rect )
     589                 :            : {
     590                 :            :   // normalize the rectangle
     591                 :          0 :   rect.normalize();
     592                 :            : 
     593                 :          0 :   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
     594                 :          0 :                                         .setFilterRect( rect )
     595                 :          0 :                                         .setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect )
     596                 :          0 :                                         .setNoAttributes() );
     597                 :            : 
     598                 :          0 :   QgsFeatureIds selectIds;
     599                 :          0 :   QgsFeatureIds deselectIds;
     600                 :            : 
     601                 :          0 :   QgsFeature fet;
     602                 :          0 :   while ( fit.nextFeature( fet ) )
     603                 :            :   {
     604                 :          0 :     if ( mSelectedFeatureIds.contains( fet.id() ) )
     605                 :            :     {
     606                 :          0 :       deselectIds << fet.id();
     607                 :          0 :     }
     608                 :            :     else
     609                 :            :     {
     610                 :          0 :       selectIds << fet.id();
     611                 :            :     }
     612                 :            :   }
     613                 :            : 
     614                 :          0 :   modifySelection( selectIds, deselectIds );
     615                 :          0 : }
     616                 :            : 
     617                 :          5 : void QgsVectorLayer::removeSelection()
     618                 :            : {
     619                 :          5 :   if ( mSelectedFeatureIds.isEmpty() )
     620                 :          5 :     return;
     621                 :            : 
     622                 :          0 :   const QgsFeatureIds previous = mSelectedFeatureIds;
     623                 :          0 :   selectByIds( QgsFeatureIds() );
     624                 :          0 :   mPreviousSelectedFeatureIds = previous;
     625                 :          5 : }
     626                 :            : 
     627                 :          0 : void QgsVectorLayer::reselect()
     628                 :            : {
     629                 :          0 :   if ( mPreviousSelectedFeatureIds.isEmpty() || !mSelectedFeatureIds.empty() )
     630                 :          0 :     return;
     631                 :            : 
     632                 :          0 :   selectByIds( mPreviousSelectedFeatureIds );
     633                 :          0 : }
     634                 :            : 
     635                 :        184 : QgsVectorDataProvider *QgsVectorLayer::dataProvider()
     636                 :            : {
     637                 :        184 :   return mDataProvider;
     638                 :            : }
     639                 :            : 
     640                 :        211 : const QgsVectorDataProvider *QgsVectorLayer::dataProvider() const
     641                 :            : {
     642                 :        211 :   return mDataProvider;
     643                 :            : }
     644                 :            : 
     645                 :          0 : QgsMapLayerTemporalProperties *QgsVectorLayer::temporalProperties()
     646                 :            : {
     647                 :          0 :   return mTemporalProperties;
     648                 :            : }
     649                 :            : 
     650                 :          0 : void QgsVectorLayer::setProviderEncoding( const QString &encoding )
     651                 :            : {
     652                 :          0 :   if ( isValid() && mDataProvider && mDataProvider->encoding() != encoding )
     653                 :            :   {
     654                 :          0 :     mDataProvider->setEncoding( encoding );
     655                 :          0 :     updateFields();
     656                 :          0 :   }
     657                 :          0 : }
     658                 :            : 
     659                 :          0 : void QgsVectorLayer::setDiagramRenderer( QgsDiagramRenderer *r )
     660                 :            : {
     661                 :          0 :   delete mDiagramRenderer;
     662                 :          0 :   mDiagramRenderer = r;
     663                 :          0 :   emit rendererChanged();
     664                 :          0 :   emit styleChanged();
     665                 :          0 : }
     666                 :            : 
     667                 :        778 : QgsWkbTypes::GeometryType QgsVectorLayer::geometryType() const
     668                 :            : {
     669                 :        778 :   return QgsWkbTypes::geometryType( mWkbType );
     670                 :            : }
     671                 :            : 
     672                 :          4 : QgsWkbTypes::Type QgsVectorLayer::wkbType() const
     673                 :            : {
     674                 :          4 :   return mWkbType;
     675                 :            : }
     676                 :            : 
     677                 :          0 : QgsRectangle QgsVectorLayer::boundingBoxOfSelected() const
     678                 :            : {
     679                 :          0 :   if ( !isValid() || !isSpatial() || mSelectedFeatureIds.isEmpty() || !mDataProvider ) //no selected features
     680                 :            :   {
     681                 :          0 :     return QgsRectangle( 0, 0, 0, 0 );
     682                 :            :   }
     683                 :            : 
     684                 :          0 :   QgsRectangle r, retval;
     685                 :          0 :   retval.setMinimal();
     686                 :            : 
     687                 :          0 :   QgsFeature fet;
     688                 :          0 :   if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
     689                 :            :   {
     690                 :          0 :     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
     691                 :          0 :                                           .setFilterFids( mSelectedFeatureIds )
     692                 :          0 :                                           .setNoAttributes() );
     693                 :            : 
     694                 :          0 :     while ( fit.nextFeature( fet ) )
     695                 :            :     {
     696                 :          0 :       if ( !fet.hasGeometry() )
     697                 :          0 :         continue;
     698                 :          0 :       r = fet.geometry().boundingBox();
     699                 :          0 :       retval.combineExtentWith( r );
     700                 :            :     }
     701                 :          0 :   }
     702                 :            :   else
     703                 :            :   {
     704                 :          0 :     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
     705                 :          0 :                                           .setNoAttributes() );
     706                 :            : 
     707                 :          0 :     while ( fit.nextFeature( fet ) )
     708                 :            :     {
     709                 :          0 :       if ( mSelectedFeatureIds.contains( fet.id() ) )
     710                 :            :       {
     711                 :          0 :         if ( fet.hasGeometry() )
     712                 :            :         {
     713                 :          0 :           r = fet.geometry().boundingBox();
     714                 :          0 :           retval.combineExtentWith( r );
     715                 :          0 :         }
     716                 :          0 :       }
     717                 :            :     }
     718                 :          0 :   }
     719                 :            : 
     720                 :          0 :   if ( retval.width() == 0.0 || retval.height() == 0.0 )
     721                 :            :   {
     722                 :            :     // If all of the features are at the one point, buffer the
     723                 :            :     // rectangle a bit. If they are all at zero, do something a bit
     724                 :            :     // more crude.
     725                 :            : 
     726                 :          0 :     if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
     727                 :          0 :          retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
     728                 :            :     {
     729                 :          0 :       retval.set( -1.0, -1.0, 1.0, 1.0 );
     730                 :          0 :     }
     731                 :          0 :   }
     732                 :            : 
     733                 :          0 :   return retval;
     734                 :          0 : }
     735                 :            : 
     736                 :          0 : bool QgsVectorLayer::labelsEnabled() const
     737                 :            : {
     738                 :          0 :   return mLabelsEnabled && static_cast< bool >( mLabeling );
     739                 :            : }
     740                 :            : 
     741                 :          0 : void QgsVectorLayer::setLabelsEnabled( bool enabled )
     742                 :            : {
     743                 :          0 :   mLabelsEnabled = enabled;
     744                 :          0 : }
     745                 :            : 
     746                 :          0 : bool QgsVectorLayer::diagramsEnabled() const
     747                 :            : {
     748                 :          0 :   if ( !mDiagramRenderer || !mDiagramLayerSettings )
     749                 :          0 :     return false;
     750                 :            : 
     751                 :          0 :   QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
     752                 :          0 :   if ( !settingList.isEmpty() )
     753                 :            :   {
     754                 :          0 :     return settingList.at( 0 ).enabled;
     755                 :            :   }
     756                 :          0 :   return false;
     757                 :          0 : }
     758                 :            : 
     759                 :          0 : long QgsVectorLayer::featureCount( const QString &legendKey ) const
     760                 :            : {
     761                 :          0 :   if ( !mSymbolFeatureCounted )
     762                 :          0 :     return -1;
     763                 :            : 
     764                 :          0 :   return mSymbolFeatureCountMap.value( legendKey, -1 );
     765                 :          0 : }
     766                 :            : 
     767                 :          0 : QgsFeatureIds QgsVectorLayer::symbolFeatureIds( const QString &legendKey ) const
     768                 :            : {
     769                 :          0 :   if ( !mSymbolFeatureCounted )
     770                 :          0 :     return QgsFeatureIds();
     771                 :            : 
     772                 :          0 :   return mSymbolFeatureIdMap.value( legendKey, QgsFeatureIds() );
     773                 :          0 : }
     774                 :          0 : QgsVectorLayerFeatureCounter *QgsVectorLayer::countSymbolFeatures( bool storeSymbolFids )
     775                 :            : {
     776                 :          0 :   if ( ( mSymbolFeatureCounted || mFeatureCounter ) && !( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
     777                 :          0 :     return mFeatureCounter;
     778                 :            : 
     779                 :          0 :   mSymbolFeatureCountMap.clear();
     780                 :          0 :   mSymbolFeatureIdMap.clear();
     781                 :            : 
     782                 :          0 :   if ( !isValid() )
     783                 :            :   {
     784                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer" ), 3 );
     785                 :          0 :     return mFeatureCounter;
     786                 :            :   }
     787                 :          0 :   if ( !mDataProvider )
     788                 :            :   {
     789                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked with null mDataProvider" ), 3 );
     790                 :          0 :     return mFeatureCounter;
     791                 :            :   }
     792                 :          0 :   if ( !mRenderer )
     793                 :            :   {
     794                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked with null mRenderer" ), 3 );
     795                 :          0 :     return mFeatureCounter;
     796                 :            :   }
     797                 :            : 
     798                 :          0 :   if ( !mFeatureCounter || ( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
     799                 :            :   {
     800                 :          0 :     mFeatureCounter = new QgsVectorLayerFeatureCounter( this, QgsExpressionContext(), storeSymbolFids );
     801                 :          0 :     connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted, Qt::UniqueConnection );
     802                 :          0 :     connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated, Qt::UniqueConnection );
     803                 :          0 :     QgsApplication::taskManager()->addTask( mFeatureCounter );
     804                 :          0 :   }
     805                 :            : 
     806                 :          0 :   return mFeatureCounter;
     807                 :          0 : }
     808                 :            : 
     809                 :          9 : void QgsVectorLayer::updateExtents( bool force )
     810                 :            : {
     811                 :            :   // do not update extent by default when trust project option is activated
     812                 :          9 :   if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.isNull() ) )
     813                 :          9 :     mValidExtent = false;
     814                 :          9 : }
     815                 :            : 
     816                 :          0 : void QgsVectorLayer::setExtent( const QgsRectangle &r )
     817                 :            : {
     818                 :          0 :   QgsMapLayer::setExtent( r );
     819                 :          0 :   mValidExtent = true;
     820                 :          0 : }
     821                 :            : 
     822                 :          0 : void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
     823                 :            : {
     824                 :          0 :   if ( !mDefaultValueOnUpdateFields.isEmpty() )
     825                 :            :   {
     826                 :          0 :     if ( !feature.isValid() )
     827                 :          0 :       feature = getFeature( fid );
     828                 :            : 
     829                 :          0 :     int size = mFields.size();
     830                 :          0 :     for ( int idx : std::as_const( mDefaultValueOnUpdateFields ) )
     831                 :            :     {
     832                 :          0 :       if ( idx < 0 || idx >= size )
     833                 :          0 :         continue;
     834                 :            : 
     835                 :          0 :       feature.setAttribute( idx, defaultValue( idx, feature ) );
     836                 :          0 :       updateFeature( feature, true );
     837                 :            :     }
     838                 :          0 :   }
     839                 :          0 : }
     840                 :            : 
     841                 :         88 : QgsRectangle QgsVectorLayer::extent() const
     842                 :            : {
     843                 :         88 :   QgsRectangle rect;
     844                 :         88 :   rect.setMinimal();
     845                 :            : 
     846                 :         88 :   if ( !isSpatial() )
     847                 :          0 :     return rect;
     848                 :            : 
     849                 :         88 :   if ( !mValidExtent && mLazyExtent && mReadExtentFromXml && !mXmlExtent.isNull() )
     850                 :            :   {
     851                 :          0 :     updateExtent( mXmlExtent );
     852                 :          0 :     mValidExtent = true;
     853                 :          0 :     mLazyExtent = false;
     854                 :          0 :   }
     855                 :            : 
     856                 :         88 :   if ( !mValidExtent && mLazyExtent && mDataProvider && mDataProvider->isValid() )
     857                 :            :   {
     858                 :            :     // store the extent
     859                 :          4 :     updateExtent( mDataProvider->extent() );
     860                 :          4 :     mValidExtent = true;
     861                 :          4 :     mLazyExtent = false;
     862                 :            : 
     863                 :            :     // show the extent
     864                 :          4 :     QgsDebugMsgLevel( QStringLiteral( "Extent of layer: %1" ).arg( mExtent.toString() ), 3 );
     865                 :          4 :   }
     866                 :            : 
     867                 :         88 :   if ( mValidExtent )
     868                 :         88 :     return QgsMapLayer::extent();
     869                 :            : 
     870                 :          0 :   if ( !isValid() || !mDataProvider )
     871                 :            :   {
     872                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
     873                 :          0 :     return rect;
     874                 :            :   }
     875                 :            : 
     876                 :          0 :   if ( !mEditBuffer ||
     877                 :          0 :        ( !mDataProvider->transaction() && ( mEditBuffer->deletedFeatureIds().isEmpty() && mEditBuffer->changedGeometries().isEmpty() ) ) ||
     878                 :          0 :        QgsDataSourceUri( mDataProvider->dataSourceUri() ).useEstimatedMetadata() )
     879                 :            :   {
     880                 :          0 :     mDataProvider->updateExtents();
     881                 :            : 
     882                 :            :     // get the extent of the layer from the provider
     883                 :            :     // but only when there are some features already
     884                 :          0 :     if ( mDataProvider->featureCount() != 0 )
     885                 :            :     {
     886                 :          0 :       const QgsRectangle r = mDataProvider->extent();
     887                 :          0 :       rect.combineExtentWith( r );
     888                 :          0 :     }
     889                 :            : 
     890                 :          0 :     if ( mEditBuffer && !mDataProvider->transaction() )
     891                 :            :     {
     892                 :          0 :       const auto addedFeatures = mEditBuffer->addedFeatures();
     893                 :          0 :       for ( QgsFeatureMap::const_iterator it = addedFeatures.constBegin(); it != addedFeatures.constEnd(); ++it )
     894                 :            :       {
     895                 :          0 :         if ( it->hasGeometry() )
     896                 :            :         {
     897                 :          0 :           const QgsRectangle r = it->geometry().boundingBox();
     898                 :          0 :           rect.combineExtentWith( r );
     899                 :          0 :         }
     900                 :          0 :       }
     901                 :          0 :     }
     902                 :          0 :   }
     903                 :            :   else
     904                 :            :   {
     905                 :          0 :     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
     906                 :          0 :                                           .setNoAttributes() );
     907                 :            : 
     908                 :          0 :     QgsFeature fet;
     909                 :          0 :     while ( fit.nextFeature( fet ) )
     910                 :            :     {
     911                 :          0 :       if ( fet.hasGeometry() && fet.geometry().type() != QgsWkbTypes::UnknownGeometry )
     912                 :            :       {
     913                 :          0 :         const QgsRectangle bb = fet.geometry().boundingBox();
     914                 :          0 :         rect.combineExtentWith( bb );
     915                 :          0 :       }
     916                 :            :     }
     917                 :          0 :   }
     918                 :            : 
     919                 :          0 :   if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
     920                 :            :   {
     921                 :            :     // special case when there are no features in provider nor any added
     922                 :          0 :     rect = QgsRectangle(); // use rectangle with zero coordinates
     923                 :          0 :   }
     924                 :            : 
     925                 :          0 :   updateExtent( rect );
     926                 :          0 :   mValidExtent = true;
     927                 :            : 
     928                 :            :   // Send this (hopefully) up the chain to the map canvas
     929                 :          0 :   emit recalculateExtents();
     930                 :            : 
     931                 :          0 :   return rect;
     932                 :         88 : }
     933                 :            : 
     934                 :          0 : QgsRectangle QgsVectorLayer::sourceExtent() const
     935                 :            : {
     936                 :          0 :   return extent();
     937                 :            : }
     938                 :            : 
     939                 :          0 : QString QgsVectorLayer::subsetString() const
     940                 :            : {
     941                 :          0 :   if ( !isValid() || !mDataProvider )
     942                 :            :   {
     943                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
     944                 :          0 :     return customProperty( QStringLiteral( "storedSubsetString" ) ).toString();
     945                 :            :   }
     946                 :          0 :   return mDataProvider->subsetString();
     947                 :          0 : }
     948                 :            : 
     949                 :          0 : bool QgsVectorLayer::setSubsetString( const QString &subset )
     950                 :            : {
     951                 :          0 :   if ( !isValid() || !mDataProvider )
     952                 :            :   {
     953                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
     954                 :          0 :     setCustomProperty( QStringLiteral( "storedSubsetString" ), subset );
     955                 :          0 :     return false;
     956                 :            :   }
     957                 :          0 :   else if ( mEditBuffer )
     958                 :            :   {
     959                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "invoked while editing" ), 3 );
     960                 :          0 :     return false;
     961                 :            :   }
     962                 :            : 
     963                 :          0 :   if ( subset == mDataProvider->subsetString() )
     964                 :          0 :     return true;
     965                 :            : 
     966                 :          0 :   bool res = mDataProvider->setSubsetString( subset );
     967                 :            : 
     968                 :            :   // get the updated data source string from the provider
     969                 :          0 :   mDataSource = mDataProvider->dataSourceUri();
     970                 :          0 :   updateExtents();
     971                 :          0 :   updateFields();
     972                 :            : 
     973                 :          0 :   if ( res )
     974                 :            :   {
     975                 :          0 :     emit subsetStringChanged();
     976                 :          0 :     triggerRepaint();
     977                 :          0 :   }
     978                 :            : 
     979                 :          0 :   return res;
     980                 :          0 : }
     981                 :            : 
     982                 :          0 : bool QgsVectorLayer::simplifyDrawingCanbeApplied( const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint ) const
     983                 :            : {
     984                 :          0 :   if ( isValid() && mDataProvider && !mEditBuffer && ( isSpatial() && geometryType() != QgsWkbTypes::PointGeometry ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
     985                 :            :   {
     986                 :          0 :     double maximumSimplificationScale = mSimplifyMethod.maximumScale();
     987                 :            : 
     988                 :            :     // check maximum scale at which generalisation should be carried out
     989                 :          0 :     return !( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale );
     990                 :            :   }
     991                 :          0 :   return false;
     992                 :          0 : }
     993                 :            : 
     994                 :          0 : QgsConditionalLayerStyles *QgsVectorLayer::conditionalStyles() const
     995                 :            : {
     996                 :          0 :   return mConditionalStyles;
     997                 :            : }
     998                 :            : 
     999                 :        132 : QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest &request ) const
    1000                 :            : {
    1001                 :        132 :   if ( !isValid() || !mDataProvider )
    1002                 :          0 :     return QgsFeatureIterator();
    1003                 :            : 
    1004                 :        132 :   return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
    1005                 :        132 : }
    1006                 :            : 
    1007                 :          0 : QgsGeometry QgsVectorLayer::getGeometry( QgsFeatureId fid ) const
    1008                 :            : {
    1009                 :          0 :   QgsFeature feature;
    1010                 :          0 :   getFeatures( QgsFeatureRequest( fid ).setFlags( QgsFeatureRequest::SubsetOfAttributes ) ).nextFeature( feature );
    1011                 :          0 :   if ( feature.isValid() )
    1012                 :          0 :     return feature.geometry();
    1013                 :            :   else
    1014                 :          0 :     return QgsGeometry();
    1015                 :          0 : }
    1016                 :            : 
    1017                 :          0 : bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
    1018                 :            : {
    1019                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1020                 :          0 :     return false;
    1021                 :            : 
    1022                 :            : 
    1023                 :          0 :   if ( mGeometryOptions->isActive() )
    1024                 :            :   {
    1025                 :          0 :     QgsGeometry geom = feature.geometry();
    1026                 :          0 :     mGeometryOptions->apply( geom );
    1027                 :          0 :     feature.setGeometry( geom );
    1028                 :          0 :   }
    1029                 :            : 
    1030                 :          0 :   bool success = mEditBuffer->addFeature( feature );
    1031                 :            : 
    1032                 :          0 :   if ( success )
    1033                 :            :   {
    1034                 :          0 :     updateExtents();
    1035                 :            : 
    1036                 :          0 :     if ( mJoinBuffer->containsJoins() )
    1037                 :          0 :       success = mJoinBuffer->addFeature( feature );
    1038                 :          0 :   }
    1039                 :            : 
    1040                 :          0 :   return success;
    1041                 :          0 : }
    1042                 :            : 
    1043                 :          1 : bool QgsVectorLayer::updateFeature( QgsFeature &updatedFeature, bool skipDefaultValues )
    1044                 :            : {
    1045                 :          1 :   if ( !mEditBuffer || !mDataProvider )
    1046                 :            :   {
    1047                 :          0 :     return false;
    1048                 :            :   }
    1049                 :            : 
    1050                 :          1 :   QgsFeature currentFeature = getFeature( updatedFeature.id() );
    1051                 :          1 :   if ( currentFeature.isValid() )
    1052                 :            :   {
    1053                 :          1 :     bool hasChanged = false;
    1054                 :          1 :     bool hasError = false;
    1055                 :            : 
    1056                 :          1 :     if ( ( updatedFeature.hasGeometry() || currentFeature.hasGeometry() ) && !updatedFeature.geometry().equals( currentFeature.geometry() ) )
    1057                 :            :     {
    1058                 :          1 :       QgsGeometry geometry = updatedFeature.geometry();
    1059                 :          1 :       if ( changeGeometry( updatedFeature.id(), geometry, true ) )
    1060                 :            :       {
    1061                 :          1 :         hasChanged = true;
    1062                 :          1 :         updatedFeature.setGeometry( geometry );
    1063                 :          1 :       }
    1064                 :            :       else
    1065                 :            :       {
    1066                 :          0 :         QgsDebugMsgLevel( QStringLiteral( "geometry of feature %1 could not be changed." ).arg( updatedFeature.id() ), 3 );
    1067                 :            :       }
    1068                 :          1 :     }
    1069                 :            : 
    1070                 :          1 :     QgsAttributes fa = updatedFeature.attributes();
    1071                 :          1 :     QgsAttributes ca = currentFeature.attributes();
    1072                 :            : 
    1073                 :          1 :     for ( int attr = 0; attr < fa.count(); ++attr )
    1074                 :            :     {
    1075                 :          0 :       if ( fa.at( attr ) != ca.at( attr ) )
    1076                 :            :       {
    1077                 :          0 :         if ( changeAttributeValue( updatedFeature.id(), attr, fa.at( attr ), ca.at( attr ), true ) )
    1078                 :            :         {
    1079                 :          0 :           hasChanged = true;
    1080                 :          0 :         }
    1081                 :            :         else
    1082                 :            :         {
    1083                 :          0 :           QgsDebugMsgLevel( QStringLiteral( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.id() ), 3 );
    1084                 :          0 :           hasError = true;
    1085                 :            :         }
    1086                 :          0 :       }
    1087                 :          0 :     }
    1088                 :          1 :     if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() && !skipDefaultValues )
    1089                 :          0 :       updateDefaultValues( updatedFeature.id(), updatedFeature );
    1090                 :            : 
    1091                 :          1 :     return !hasError;
    1092                 :          1 :   }
    1093                 :            :   else
    1094                 :            :   {
    1095                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "feature %1 could not be retrieved" ).arg( updatedFeature.id() ), 3 );
    1096                 :          0 :     return false;
    1097                 :            :   }
    1098                 :          1 : }
    1099                 :            : 
    1100                 :            : 
    1101                 :          0 : bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
    1102                 :            : {
    1103                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1104                 :          0 :     return false;
    1105                 :            : 
    1106                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1107                 :          0 :   bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
    1108                 :          0 :   if ( result )
    1109                 :          0 :     updateExtents();
    1110                 :          0 :   return result;
    1111                 :          0 : }
    1112                 :            : 
    1113                 :            : 
    1114                 :          0 : bool QgsVectorLayer::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
    1115                 :            : {
    1116                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1117                 :          0 :     return false;
    1118                 :            : 
    1119                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1120                 :          0 :   bool result = utils.insertVertex( point, atFeatureId, beforeVertex );
    1121                 :          0 :   if ( result )
    1122                 :          0 :     updateExtents();
    1123                 :          0 :   return result;
    1124                 :          0 : }
    1125                 :            : 
    1126                 :            : 
    1127                 :          0 : bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
    1128                 :            : {
    1129                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1130                 :          0 :     return false;
    1131                 :            : 
    1132                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1133                 :          0 :   bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
    1134                 :            : 
    1135                 :          0 :   if ( result )
    1136                 :          0 :     updateExtents();
    1137                 :          0 :   return result;
    1138                 :          0 : }
    1139                 :            : 
    1140                 :          0 : bool QgsVectorLayer::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
    1141                 :            : {
    1142                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1143                 :          0 :     return false;
    1144                 :            : 
    1145                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1146                 :          0 :   bool result = utils.moveVertex( p, atFeatureId, atVertex );
    1147                 :            : 
    1148                 :          0 :   if ( result )
    1149                 :          0 :     updateExtents();
    1150                 :          0 :   return result;
    1151                 :          0 : }
    1152                 :            : 
    1153                 :          0 : QgsVectorLayer::EditResult QgsVectorLayer::deleteVertex( QgsFeatureId featureId, int vertex )
    1154                 :            : {
    1155                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1156                 :          0 :     return QgsVectorLayer::InvalidLayer;
    1157                 :            : 
    1158                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1159                 :          0 :   EditResult result = utils.deleteVertex( featureId, vertex );
    1160                 :            : 
    1161                 :          0 :   if ( result == Success )
    1162                 :          0 :     updateExtents();
    1163                 :          0 :   return result;
    1164                 :          0 : }
    1165                 :            : 
    1166                 :            : 
    1167                 :          0 : bool QgsVectorLayer::deleteSelectedFeatures( int *deletedCount, QgsVectorLayer::DeleteContext *context )
    1168                 :            : {
    1169                 :          0 :   if ( !isValid() || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
    1170                 :            :   {
    1171                 :          0 :     return false;
    1172                 :            :   }
    1173                 :            : 
    1174                 :          0 :   if ( !isEditable() )
    1175                 :            :   {
    1176                 :          0 :     return false;
    1177                 :            :   }
    1178                 :            : 
    1179                 :          0 :   int deleted = 0;
    1180                 :          0 :   int count = mSelectedFeatureIds.size();
    1181                 :            :   // Make a copy since deleteFeature modifies mSelectedFeatureIds
    1182                 :          0 :   QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
    1183                 :          0 :   const auto constSelectedFeatures = selectedFeatures;
    1184                 :          0 :   for ( QgsFeatureId fid : constSelectedFeatures )
    1185                 :            :   {
    1186                 :          0 :     deleted += deleteFeature( fid, context );  // removes from selection
    1187                 :            :   }
    1188                 :            : 
    1189                 :          0 :   triggerRepaint();
    1190                 :          0 :   updateExtents();
    1191                 :            : 
    1192                 :          0 :   if ( deletedCount )
    1193                 :            :   {
    1194                 :          0 :     *deletedCount = deleted;
    1195                 :          0 :   }
    1196                 :            : 
    1197                 :          0 :   return deleted == count;
    1198                 :          0 : }
    1199                 :            : 
    1200                 :          0 : static const QgsPointSequence vectorPointXY2pointSequence( const QVector<QgsPointXY> &points )
    1201                 :            : {
    1202                 :          0 :   QgsPointSequence pts;
    1203                 :          0 :   pts.reserve( points.size() );
    1204                 :          0 :   QVector<QgsPointXY>::const_iterator it = points.constBegin();
    1205                 :          0 :   while ( it != points.constEnd() )
    1206                 :            :   {
    1207                 :          0 :     pts.append( QgsPoint( *it ) );
    1208                 :          0 :     ++it;
    1209                 :            :   }
    1210                 :          0 :   return pts;
    1211                 :          0 : }
    1212                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addRing( const QVector<QgsPointXY> &ring, QgsFeatureId *featureId )
    1213                 :            : {
    1214                 :          0 :   return addRing( vectorPointXY2pointSequence( ring ), featureId );
    1215                 :          0 : }
    1216                 :            : 
    1217                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addRing( const QgsPointSequence &ring, QgsFeatureId *featureId )
    1218                 :            : {
    1219                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1220                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1221                 :            : 
    1222                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1223                 :          0 :   QgsGeometry::OperationResult result = QgsGeometry::OperationResult::AddRingNotInExistingFeature;
    1224                 :            : 
    1225                 :            :   //first try with selected features
    1226                 :          0 :   if ( !mSelectedFeatureIds.isEmpty() )
    1227                 :            :   {
    1228                 :          0 :     result = utils.addRing( ring, mSelectedFeatureIds, featureId );
    1229                 :          0 :   }
    1230                 :            : 
    1231                 :          0 :   if ( result != QgsGeometry::OperationResult::Success )
    1232                 :            :   {
    1233                 :            :     //try with all intersecting features
    1234                 :          0 :     result = utils.addRing( ring, QgsFeatureIds(), featureId );
    1235                 :          0 :   }
    1236                 :            : 
    1237                 :          0 :   return result;
    1238                 :          0 : }
    1239                 :            : 
    1240                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addRing( QgsCurve *ring, QgsFeatureId *featureId )
    1241                 :            : {
    1242                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1243                 :            :   {
    1244                 :          0 :     delete ring;
    1245                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1246                 :            :   }
    1247                 :            : 
    1248                 :          0 :   if ( !ring )
    1249                 :            :   {
    1250                 :          0 :     return QgsGeometry::OperationResult::InvalidInputGeometryType;
    1251                 :            :   }
    1252                 :            : 
    1253                 :          0 :   if ( !ring->isClosed() )
    1254                 :            :   {
    1255                 :          0 :     delete ring;
    1256                 :          0 :     return QgsGeometry::OperationResult::AddRingNotClosed;
    1257                 :            :   }
    1258                 :            : 
    1259                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1260                 :          0 :   QgsGeometry::OperationResult result = QgsGeometry::OperationResult::AddRingNotInExistingFeature;
    1261                 :            : 
    1262                 :            :   //first try with selected features
    1263                 :          0 :   if ( !mSelectedFeatureIds.isEmpty() )
    1264                 :            :   {
    1265                 :          0 :     result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), mSelectedFeatureIds, featureId );
    1266                 :          0 :   }
    1267                 :            : 
    1268                 :          0 :   if ( result != QgsGeometry::OperationResult::Success )
    1269                 :            :   {
    1270                 :            :     //try with all intersecting features
    1271                 :          0 :     result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), QgsFeatureIds(), featureId );
    1272                 :          0 :   }
    1273                 :            : 
    1274                 :          0 :   delete ring;
    1275                 :          0 :   return result;
    1276                 :          0 : }
    1277                 :            : 
    1278                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addPart( const QList<QgsPointXY> &points )
    1279                 :            : {
    1280                 :          0 :   QgsPointSequence pts;
    1281                 :          0 :   pts.reserve( points.size() );
    1282                 :          0 :   for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd() ; ++it )
    1283                 :            :   {
    1284                 :          0 :     pts.append( QgsPoint( *it ) );
    1285                 :          0 :   }
    1286                 :          0 :   return addPart( pts );
    1287                 :          0 : }
    1288                 :            : 
    1289                 :            : #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    1290                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addPart( const QVector<QgsPointXY> &points )
    1291                 :            : {
    1292                 :          0 :   return addPart( vectorPointXY2pointSequence( points ) );
    1293                 :          0 : }
    1294                 :            : #endif
    1295                 :            : 
    1296                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addPart( const QgsPointSequence &points )
    1297                 :            : {
    1298                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1299                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1300                 :            : 
    1301                 :            :   //number of selected features must be 1
    1302                 :            : 
    1303                 :          0 :   if ( mSelectedFeatureIds.empty() )
    1304                 :            :   {
    1305                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
    1306                 :          0 :     return QgsGeometry::OperationResult::SelectionIsEmpty;
    1307                 :            :   }
    1308                 :          0 :   else if ( mSelectedFeatureIds.size() > 1 )
    1309                 :            :   {
    1310                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
    1311                 :          0 :     return QgsGeometry::OperationResult::SelectionIsGreaterThanOne;
    1312                 :            :   }
    1313                 :            : 
    1314                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1315                 :          0 :   QgsGeometry::OperationResult result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
    1316                 :            : 
    1317                 :          0 :   if ( result == QgsGeometry::OperationResult::Success )
    1318                 :          0 :     updateExtents();
    1319                 :          0 :   return result;
    1320                 :          0 : }
    1321                 :            : 
    1322                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::addPart( QgsCurve *ring )
    1323                 :            : {
    1324                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1325                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1326                 :            : 
    1327                 :            :   //number of selected features must be 1
    1328                 :            : 
    1329                 :          0 :   if ( mSelectedFeatureIds.empty() )
    1330                 :            :   {
    1331                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
    1332                 :          0 :     return QgsGeometry::OperationResult::SelectionIsEmpty;
    1333                 :            :   }
    1334                 :          0 :   else if ( mSelectedFeatureIds.size() > 1 )
    1335                 :            :   {
    1336                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
    1337                 :          0 :     return QgsGeometry::OperationResult::SelectionIsGreaterThanOne;
    1338                 :            :   }
    1339                 :            : 
    1340                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1341                 :          0 :   QgsGeometry::OperationResult result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
    1342                 :            : 
    1343                 :          0 :   if ( result == QgsGeometry::OperationResult::Success )
    1344                 :          0 :     updateExtents();
    1345                 :          0 :   return result;
    1346                 :          0 : }
    1347                 :            : 
    1348                 :          0 : int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
    1349                 :            : {
    1350                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1351                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1352                 :            : 
    1353                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1354                 :          0 :   int result = utils.translateFeature( featureId, dx, dy );
    1355                 :            : 
    1356                 :          0 :   if ( result == QgsGeometry::OperationResult::Success )
    1357                 :          0 :     updateExtents();
    1358                 :          0 :   return result;
    1359                 :          0 : }
    1360                 :            : 
    1361                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
    1362                 :            : {
    1363                 :          0 :   return splitParts( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
    1364                 :          0 : }
    1365                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::splitParts( const QgsPointSequence &splitLine, bool topologicalEditing )
    1366                 :            : {
    1367                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1368                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1369                 :            : 
    1370                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1371                 :          0 :   return utils.splitParts( splitLine, topologicalEditing );
    1372                 :          0 : }
    1373                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
    1374                 :            : {
    1375                 :          0 :   return splitFeatures( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
    1376                 :          0 : }
    1377                 :            : 
    1378                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::splitFeatures( const QgsPointSequence &splitLine, bool topologicalEditing )
    1379                 :            : {
    1380                 :          0 :   QgsLineString splitLineString( splitLine );
    1381                 :          0 :   QgsPointSequence topologyTestPoints;
    1382                 :          0 :   bool preserveCircular = false;
    1383                 :          0 :   return splitFeatures( &splitLineString, topologyTestPoints, preserveCircular, topologicalEditing );
    1384                 :          0 : }
    1385                 :            : 
    1386                 :          0 : QgsGeometry::OperationResult QgsVectorLayer::splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints, bool preserveCircular, bool topologicalEditing )
    1387                 :            : {
    1388                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1389                 :          0 :     return QgsGeometry::OperationResult::LayerNotEditable;
    1390                 :            : 
    1391                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1392                 :          0 :   return utils.splitFeatures( curve, topologyTestPoints, preserveCircular, topologicalEditing );
    1393                 :          0 : }
    1394                 :            : 
    1395                 :          0 : int QgsVectorLayer::addTopologicalPoints( const QgsGeometry &geom )
    1396                 :            : {
    1397                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1398                 :          0 :     return -1;
    1399                 :            : 
    1400                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1401                 :          0 :   return utils.addTopologicalPoints( geom );
    1402                 :          0 : }
    1403                 :            : 
    1404                 :          0 : int QgsVectorLayer::addTopologicalPoints( const QgsPointXY &p )
    1405                 :            : {
    1406                 :          0 :   return addTopologicalPoints( QgsPoint( p ) );
    1407                 :          0 : }
    1408                 :            : 
    1409                 :          0 : int QgsVectorLayer::addTopologicalPoints( const QgsPoint &p )
    1410                 :            : {
    1411                 :          0 :   if ( !isValid() || !mEditBuffer || !mDataProvider )
    1412                 :          0 :     return -1;
    1413                 :            : 
    1414                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1415                 :          0 :   return utils.addTopologicalPoints( p );
    1416                 :          0 : }
    1417                 :            : 
    1418                 :          0 : int QgsVectorLayer::addTopologicalPoints( const QgsPointSequence &ps )
    1419                 :            : {
    1420                 :          0 :   if ( !mValid || !mEditBuffer || !mDataProvider )
    1421                 :          0 :     return -1;
    1422                 :            : 
    1423                 :          0 :   QgsVectorLayerEditUtils utils( this );
    1424                 :          0 :   return utils.addTopologicalPoints( ps );
    1425                 :          0 : }
    1426                 :            : 
    1427                 :          0 : void QgsVectorLayer::setLabeling( QgsAbstractVectorLayerLabeling *labeling )
    1428                 :            : {
    1429                 :          0 :   if ( mLabeling == labeling )
    1430                 :          0 :     return;
    1431                 :            : 
    1432                 :          0 :   delete mLabeling;
    1433                 :          0 :   mLabeling = labeling;
    1434                 :          0 : }
    1435                 :            : 
    1436                 :          2 : bool QgsVectorLayer::startEditing()
    1437                 :            : {
    1438                 :          2 :   if ( !isValid() || !mDataProvider )
    1439                 :            :   {
    1440                 :          0 :     return false;
    1441                 :            :   }
    1442                 :            : 
    1443                 :            :   // allow editing if provider supports any of the capabilities
    1444                 :          2 :   if ( !supportsEditing() )
    1445                 :            :   {
    1446                 :          0 :     return false;
    1447                 :            :   }
    1448                 :            : 
    1449                 :          2 :   if ( mEditBuffer )
    1450                 :            :   {
    1451                 :            :     // editing already underway
    1452                 :          1 :     return false;
    1453                 :            :   }
    1454                 :            : 
    1455                 :          1 :   emit beforeEditingStarted();
    1456                 :            : 
    1457                 :          1 :   mDataProvider->enterUpdateMode();
    1458                 :            : 
    1459                 :          1 :   if ( mDataProvider->transaction() )
    1460                 :            :   {
    1461                 :          0 :     mEditBuffer = new QgsVectorLayerEditPassthrough( this );
    1462                 :            : 
    1463                 :          0 :     connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
    1464                 :          0 :   }
    1465                 :            :   else
    1466                 :            :   {
    1467                 :          1 :     mEditBuffer = new QgsVectorLayerEditBuffer( this );
    1468                 :            :   }
    1469                 :            :   // forward signals
    1470                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
    1471                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
    1472                 :            :   //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
    1473                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureAdded, this, &QgsVectorLayer::featureAdded );
    1474                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
    1475                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::geometryChanged, this, &QgsVectorLayer::geometryChanged );
    1476                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::attributeValueChanged, this, &QgsVectorLayer::attributeValueChanged );
    1477                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::attributeAdded, this, &QgsVectorLayer::attributeAdded );
    1478                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::attributeDeleted, this, &QgsVectorLayer::attributeDeleted );
    1479                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::committedAttributesDeleted, this, &QgsVectorLayer::committedAttributesDeleted );
    1480                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::committedAttributesAdded, this, &QgsVectorLayer::committedAttributesAdded );
    1481                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::committedFeaturesAdded, this, &QgsVectorLayer::committedFeaturesAdded );
    1482                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::committedFeaturesRemoved, this, &QgsVectorLayer::committedFeaturesRemoved );
    1483                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::committedAttributeValuesChanges, this, &QgsVectorLayer::committedAttributeValuesChanges );
    1484                 :          1 :   connect( mEditBuffer, &QgsVectorLayerEditBuffer::committedGeometriesChanges, this, &QgsVectorLayer::committedGeometriesChanges );
    1485                 :            : 
    1486                 :          1 :   updateFields();
    1487                 :            : 
    1488                 :          1 :   emit editingStarted();
    1489                 :            : 
    1490                 :          1 :   return true;
    1491                 :          2 : }
    1492                 :            : 
    1493                 :          1 : void QgsVectorLayer::setTransformContext( const QgsCoordinateTransformContext &transformContext )
    1494                 :            : {
    1495                 :          1 :   if ( mDataProvider )
    1496                 :          1 :     mDataProvider->setTransformContext( transformContext );
    1497                 :          1 : }
    1498                 :            : 
    1499                 :          0 : QgsFeatureSource::SpatialIndexPresence QgsVectorLayer::hasSpatialIndex() const
    1500                 :            : {
    1501                 :          0 :   return mDataProvider ? mDataProvider->hasSpatialIndex() : QgsFeatureSource::SpatialIndexUnknown;
    1502                 :            : }
    1503                 :            : 
    1504                 :          0 : bool QgsVectorLayer::accept( QgsStyleEntityVisitorInterface *visitor ) const
    1505                 :            : {
    1506                 :          0 :   if ( mRenderer )
    1507                 :          0 :     if ( !mRenderer->accept( visitor ) )
    1508                 :          0 :       return false;
    1509                 :            : 
    1510                 :          0 :   if ( mLabeling )
    1511                 :          0 :     if ( !mLabeling->accept( visitor ) )
    1512                 :          0 :       return false;
    1513                 :            : 
    1514                 :          0 :   return true;
    1515                 :          0 : }
    1516                 :            : 
    1517                 :          0 : bool QgsVectorLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
    1518                 :            : {
    1519                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsVectorLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
    1520                 :            : 
    1521                 :            :   //process provider key
    1522                 :          0 :   QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
    1523                 :            : 
    1524                 :          0 :   if ( pkeyNode.isNull() )
    1525                 :            :   {
    1526                 :          0 :     mProviderKey.clear();
    1527                 :          0 :   }
    1528                 :            :   else
    1529                 :            :   {
    1530                 :          0 :     QDomElement pkeyElt = pkeyNode.toElement();
    1531                 :          0 :     mProviderKey = pkeyElt.text();
    1532                 :          0 :   }
    1533                 :            : 
    1534                 :            :   // determine type of vector layer
    1535                 :          0 :   if ( !mProviderKey.isNull() )
    1536                 :            :   {
    1537                 :            :     // if the provider string isn't empty, then we successfully
    1538                 :            :     // got the stored provider
    1539                 :          0 :   }
    1540                 :          0 :   else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
    1541                 :            :   {
    1542                 :          0 :     mProviderKey = QStringLiteral( "postgres" );
    1543                 :          0 :   }
    1544                 :            :   else
    1545                 :            :   {
    1546                 :          0 :     mProviderKey = QStringLiteral( "ogr" );
    1547                 :            :   }
    1548                 :            : 
    1549                 :          0 :   QgsDataProvider::ProviderOptions options { context.transformContext() };
    1550                 :          0 :   QgsDataProvider::ReadFlags flags;
    1551                 :          0 :   if ( mReadFlags & QgsMapLayer::FlagTrustLayerMetadata )
    1552                 :            :   {
    1553                 :          0 :     flags |= QgsDataProvider::FlagTrustDataSource;
    1554                 :          0 :   }
    1555                 :          0 :   if ( ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) || !setDataProvider( mProviderKey, options, flags ) )
    1556                 :            :   {
    1557                 :          0 :     if ( !( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) )
    1558                 :            :     {
    1559                 :          0 :       QgsDebugMsg( QStringLiteral( "Could not set data provider for layer %1" ).arg( publicSource() ) );
    1560                 :          0 :     }
    1561                 :          0 :     const QDomElement elem = layer_node.toElement();
    1562                 :            : 
    1563                 :            :     // for invalid layer sources, we fallback to stored wkbType if available
    1564                 :          0 :     if ( elem.hasAttribute( QStringLiteral( "wkbType" ) ) )
    1565                 :          0 :       mWkbType = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "wkbType" ) ), mWkbType );
    1566                 :          0 :   }
    1567                 :            : 
    1568                 :          0 :   QDomElement pkeyElem = pkeyNode.toElement();
    1569                 :          0 :   if ( !pkeyElem.isNull() )
    1570                 :            :   {
    1571                 :          0 :     QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
    1572                 :          0 :     if ( mDataProvider && !encodingString.isEmpty() )
    1573                 :            :     {
    1574                 :          0 :       mDataProvider->setEncoding( encodingString );
    1575                 :          0 :     }
    1576                 :          0 :   }
    1577                 :            : 
    1578                 :            :   // load vector joins - does not resolve references to layers yet
    1579                 :          0 :   mJoinBuffer->readXml( layer_node );
    1580                 :            : 
    1581                 :          0 :   updateFields();
    1582                 :            : 
    1583                 :            :   // If style doesn't include a legend, we'll need to make a default one later...
    1584                 :          0 :   mSetLegendFromStyle = false;
    1585                 :            : 
    1586                 :          0 :   QString errorMsg;
    1587                 :          0 :   if ( !readSymbology( layer_node, errorMsg, context ) )
    1588                 :            :   {
    1589                 :          0 :     return false;
    1590                 :            :   }
    1591                 :            : 
    1592                 :          0 :   readStyleManager( layer_node );
    1593                 :            : 
    1594                 :          0 :   QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
    1595                 :          0 :   QDomNodeList depsNodes = depsNode.childNodes();
    1596                 :          0 :   QSet<QgsMapLayerDependency> sources;
    1597                 :          0 :   for ( int i = 0; i < depsNodes.count(); i++ )
    1598                 :            :   {
    1599                 :          0 :     QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
    1600                 :          0 :     sources << QgsMapLayerDependency( source );
    1601                 :          0 :   }
    1602                 :          0 :   setDependencies( sources );
    1603                 :            : 
    1604                 :          0 :   if ( !mSetLegendFromStyle )
    1605                 :          0 :     setLegend( QgsMapLayerLegend::defaultVectorLegend( this ) );
    1606                 :            : 
    1607                 :            :   // read extent
    1608                 :          0 :   if ( mReadExtentFromXml )
    1609                 :            :   {
    1610                 :          0 :     QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
    1611                 :          0 :     if ( !extentNode.isNull() )
    1612                 :            :     {
    1613                 :          0 :       mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
    1614                 :          0 :     }
    1615                 :          0 :   }
    1616                 :            : 
    1617                 :            :   // auxiliary layer
    1618                 :          0 :   const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
    1619                 :          0 :   const QDomElement asElem = asNode.toElement();
    1620                 :          0 :   if ( !asElem.isNull() )
    1621                 :            :   {
    1622                 :          0 :     mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
    1623                 :          0 :   }
    1624                 :            : 
    1625                 :            :   // QGIS Server WMS Dimensions
    1626                 :          0 :   mServerProperties->readXml( layer_node );
    1627                 :            : 
    1628                 :          0 :   return isValid();               // should be true if read successfully
    1629                 :            : 
    1630                 :          0 : } // void QgsVectorLayer::readXml
    1631                 :            : 
    1632                 :            : 
    1633                 :          0 : void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag )
    1634                 :            : {
    1635                 :          0 :   QgsDataProvider::ProviderOptions options;
    1636                 :          0 :   setDataSource( dataSource, baseName, provider, options, loadDefaultStyleFlag );
    1637                 :          0 : }
    1638                 :            : 
    1639                 :         78 : void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag )
    1640                 :            : {
    1641                 :         78 :   QgsWkbTypes::GeometryType geomType = geometryType();
    1642                 :            : 
    1643                 :         78 :   mDataSource = dataSource;
    1644                 :         78 :   setName( baseName );
    1645                 :            : 
    1646                 :         78 :   QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
    1647                 :         78 :   if ( mReadFlags & QgsMapLayer::FlagTrustLayerMetadata )
    1648                 :            :   {
    1649                 :          0 :     flags |= QgsDataProvider::FlagTrustDataSource;
    1650                 :          0 :   }
    1651                 :         78 :   setDataProvider( provider, options, flags );
    1652                 :            : 
    1653                 :         78 :   if ( !isValid() )
    1654                 :            :   {
    1655                 :          0 :     emit dataSourceChanged();
    1656                 :          0 :     return;
    1657                 :            :   }
    1658                 :            : 
    1659                 :            :   // Always set crs
    1660                 :         78 :   setCoordinateSystem();
    1661                 :            : 
    1662                 :            :   // reset style if loading default style, style is missing, or geometry type is has changed (and layer is valid)
    1663                 :         78 :   if ( !renderer() || !legend() || ( isValid() && geomType != geometryType() ) || loadDefaultStyleFlag )
    1664                 :            :   {
    1665                 :         78 :     std::unique_ptr< QgsScopedRuntimeProfile > profile;
    1666                 :        156 :     if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
    1667                 :          0 :       profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Load layer style" ), QStringLiteral( "projectload" ) );
    1668                 :            : 
    1669                 :         78 :     bool defaultLoadedFlag = false;
    1670                 :            : 
    1671                 :         78 :     if ( loadDefaultStyleFlag && isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
    1672                 :            :     {
    1673                 :            :       // first try to create a renderer directly from the data provider
    1674                 :          0 :       std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
    1675                 :          0 :       if ( defaultRenderer )
    1676                 :            :       {
    1677                 :          0 :         defaultLoadedFlag = true;
    1678                 :          0 :         setRenderer( defaultRenderer.release() );
    1679                 :          0 :       }
    1680                 :          0 :     }
    1681                 :            : 
    1682                 :            :     // need to check whether the default style included a legend, and if not, we need to make a default legend
    1683                 :            :     // later...
    1684                 :         78 :     mSetLegendFromStyle = false;
    1685                 :            : 
    1686                 :            :     // else check if there is a default style / propertysheet defined
    1687                 :            :     // for this layer and if so apply it
    1688                 :         78 :     if ( !defaultLoadedFlag && loadDefaultStyleFlag )
    1689                 :            :     {
    1690                 :         78 :       loadDefaultStyle( defaultLoadedFlag );
    1691                 :         78 :     }
    1692                 :            : 
    1693                 :            :     // if the default style failed to load or was disabled use some very basic defaults
    1694                 :         78 :     if ( !defaultLoadedFlag && isSpatial() )
    1695                 :            :     {
    1696                 :            :       // add single symbol renderer
    1697                 :         78 :       setRenderer( QgsFeatureRenderer::defaultRenderer( geometryType() ) );
    1698                 :         78 :     }
    1699                 :            : 
    1700                 :         78 :     if ( !mSetLegendFromStyle )
    1701                 :         78 :       setLegend( QgsMapLayerLegend::defaultVectorLegend( this ) );
    1702                 :            : 
    1703                 :         78 :     if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
    1704                 :            :     {
    1705                 :          0 :       std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
    1706                 :          0 :       if ( defaultLabeling )
    1707                 :            :       {
    1708                 :          0 :         setLabeling( defaultLabeling.release() );
    1709                 :          0 :         setLabelsEnabled( true );
    1710                 :          0 :       }
    1711                 :          0 :     }
    1712                 :         78 :   }
    1713                 :            : 
    1714                 :         78 :   emit dataSourceChanged();
    1715                 :         78 :   triggerRepaint();
    1716                 :         78 : }
    1717                 :            : 
    1718                 :         78 : QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
    1719                 :            : {
    1720                 :         78 :   if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
    1721                 :            :   {
    1722                 :            :     // first try to create a renderer directly from the data provider
    1723                 :          0 :     std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
    1724                 :          0 :     if ( defaultRenderer )
    1725                 :            :     {
    1726                 :          0 :       resultFlag = true;
    1727                 :          0 :       setRenderer( defaultRenderer.release() );
    1728                 :          0 :       return QString();
    1729                 :            :     }
    1730                 :          0 :   }
    1731                 :            : 
    1732                 :         78 :   return QgsMapLayer::loadDefaultStyle( resultFlag );
    1733                 :         78 : }
    1734                 :            : 
    1735                 :            : 
    1736                 :         78 : bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
    1737                 :            : {
    1738                 :         78 :   mProviderKey = provider;
    1739                 :         78 :   delete mDataProvider;
    1740                 :            : 
    1741                 :            :   // For Postgres provider primary key unicity is tested at construction time,
    1742                 :            :   // so it has to be set before initializing the provider,
    1743                 :            :   // this manipulation is necessary to preserve default behavior when
    1744                 :            :   // "trust layer metadata" project level option is set and checkPrimaryKeyUnicity
    1745                 :            :   // was not explicitly passed in the uri
    1746                 :         78 :   if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
    1747                 :            :   {
    1748                 :          0 :     const QString checkUnicityKey { QStringLiteral( "checkPrimaryKeyUnicity" ) };
    1749                 :          0 :     QgsDataSourceUri uri( mDataSource );
    1750                 :          0 :     if ( ! uri.hasParam( checkUnicityKey ) )
    1751                 :            :     {
    1752                 :          0 :       uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
    1753                 :          0 :       mDataSource = uri.uri( false );
    1754                 :          0 :     }
    1755                 :          0 :   }
    1756                 :            : 
    1757                 :         78 :   std::unique_ptr< QgsScopedRuntimeProfile > profile;
    1758                 :        156 :   if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
    1759                 :          0 :     profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
    1760                 :            : 
    1761                 :         78 :   mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, mDataSource, options, flags ) );
    1762                 :         78 :   if ( !mDataProvider )
    1763                 :            :   {
    1764                 :          0 :     setValid( false );
    1765                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Unable to get data provider" ), 2 );
    1766                 :          0 :     return false;
    1767                 :            :   }
    1768                 :            : 
    1769                 :         78 :   mDataProvider->setParent( this );
    1770                 :         78 :   connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
    1771                 :            : 
    1772                 :         78 :   QgsDebugMsgLevel( QStringLiteral( "Instantiated the data provider plugin" ), 2 );
    1773                 :            : 
    1774                 :         78 :   setValid( mDataProvider->isValid() );
    1775                 :         78 :   if ( !isValid() )
    1776                 :            :   {
    1777                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Invalid provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
    1778                 :          0 :     return false;
    1779                 :            :   }
    1780                 :            : 
    1781                 :         78 :   if ( profile )
    1782                 :          0 :     profile->switchTask( tr( "Read layer metadata" ) );
    1783                 :         78 :   if ( mDataProvider->capabilities() & QgsVectorDataProvider::ReadLayerMetadata )
    1784                 :            :   {
    1785                 :         64 :     setMetadata( mDataProvider->layerMetadata() );
    1786                 :         64 :     QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
    1787                 :         64 :   }
    1788                 :            : 
    1789                 :            :   // TODO: Check if the provider has the capability to send fullExtentCalculated
    1790                 :         78 :   connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
    1791                 :            : 
    1792                 :            :   // get and store the feature type
    1793                 :         78 :   mWkbType = mDataProvider->wkbType();
    1794                 :            : 
    1795                 :         78 :   if ( profile )
    1796                 :          0 :     profile->switchTask( tr( "Read layer fields" ) );
    1797                 :         78 :   updateFields();
    1798                 :            : 
    1799                 :         78 :   if ( mProviderKey == QLatin1String( "postgres" ) )
    1800                 :            :   {
    1801                 :            :     // update datasource from data provider computed one
    1802                 :          0 :     mDataSource = mDataProvider->dataSourceUri( false );
    1803                 :            : 
    1804                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Beautifying layer name %1" ).arg( name() ), 3 );
    1805                 :            : 
    1806                 :            :     // adjust the display name for postgres layers
    1807                 :          0 :     QRegExp reg( R"lit("[^"]+"\."([^"] + )"( \([^)]+\))?)lit" );
    1808                 :          0 :     if ( reg.indexIn( name() ) >= 0 )
    1809                 :            :     {
    1810                 :          0 :       QStringList stuff = reg.capturedTexts();
    1811                 :          0 :       QString lName = stuff[1];
    1812                 :            : 
    1813                 :          0 :       const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
    1814                 :            : 
    1815                 :          0 :       QMap<QString, QgsMapLayer *>::const_iterator it;
    1816                 :          0 :       for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
    1817                 :            :         ;
    1818                 :            : 
    1819                 :          0 :       if ( it != layers.constEnd() && stuff.size() > 2 )
    1820                 :            :       {
    1821                 :          0 :         lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
    1822                 :          0 :       }
    1823                 :            : 
    1824                 :          0 :       if ( !lName.isEmpty() )
    1825                 :          0 :         setName( lName );
    1826                 :          0 :     }
    1827                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Beautified layer name %1" ).arg( name() ), 3 );
    1828                 :          0 :   }
    1829                 :         78 :   else if ( mProviderKey == QLatin1String( "osm" ) )
    1830                 :            :   {
    1831                 :            :     // make sure that the "observer" has been removed from URI to avoid crashes
    1832                 :          0 :     mDataSource = mDataProvider->dataSourceUri();
    1833                 :          0 :   }
    1834                 :         78 :   else if ( provider == QLatin1String( "ogr" ) )
    1835                 :            :   {
    1836                 :            :     // make sure that the /vsigzip or /vsizip is added to uri, if applicable
    1837                 :         64 :     mDataSource = mDataProvider->dataSourceUri();
    1838                 :         64 :     if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
    1839                 :          0 :       mDataSource.chop( 10 );
    1840                 :         64 :   }
    1841                 :         14 :   else if ( provider == QLatin1String( "memory" ) )
    1842                 :            :   {
    1843                 :            :     // required so that source differs between memory layers
    1844                 :         28 :     mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
    1845                 :         14 :   }
    1846                 :            : 
    1847                 :         78 :   connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::emitDataChanged );
    1848                 :         78 :   connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
    1849                 :            : 
    1850                 :         78 :   return true;
    1851                 :         78 : } // QgsVectorLayer:: setDataProvider
    1852                 :            : 
    1853                 :            : 
    1854                 :            : 
    1855                 :            : 
    1856                 :            : /* virtual */
    1857                 :          0 : bool QgsVectorLayer::writeXml( QDomNode &layer_node,
    1858                 :            :                                QDomDocument &document,
    1859                 :            :                                const QgsReadWriteContext &context ) const
    1860                 :            : {
    1861                 :            :   // first get the layer element so that we can append the type attribute
    1862                 :            : 
    1863                 :          0 :   QDomElement mapLayerNode = layer_node.toElement();
    1864                 :            : 
    1865                 :          0 :   if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
    1866                 :            :   {
    1867                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
    1868                 :          0 :     return false;
    1869                 :            :   }
    1870                 :            : 
    1871                 :          0 :   mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::VectorLayer ) );
    1872                 :            : 
    1873                 :            :   // set the geometry type
    1874                 :          0 :   mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
    1875                 :          0 :   mapLayerNode.setAttribute( QStringLiteral( "wkbType" ), qgsEnumValueToKey( wkbType() ) );
    1876                 :            : 
    1877                 :            :   // add provider node
    1878                 :          0 :   if ( mDataProvider )
    1879                 :            :   {
    1880                 :          0 :     QDomElement provider  = document.createElement( QStringLiteral( "provider" ) );
    1881                 :          0 :     provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
    1882                 :          0 :     QDomText providerText = document.createTextNode( providerType() );
    1883                 :          0 :     provider.appendChild( providerText );
    1884                 :          0 :     layer_node.appendChild( provider );
    1885                 :          0 :   }
    1886                 :            : 
    1887                 :            :   //save joins
    1888                 :          0 :   mJoinBuffer->writeXml( layer_node, document );
    1889                 :            : 
    1890                 :            :   // dependencies
    1891                 :          0 :   QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
    1892                 :          0 :   const auto constDependencies = dependencies();
    1893                 :          0 :   for ( const QgsMapLayerDependency &dep : constDependencies )
    1894                 :            :   {
    1895                 :          0 :     if ( dep.type() != QgsMapLayerDependency::PresenceDependency )
    1896                 :          0 :       continue;
    1897                 :          0 :     QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
    1898                 :          0 :     depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
    1899                 :          0 :     dependenciesElement.appendChild( depElem );
    1900                 :          0 :   }
    1901                 :          0 :   layer_node.appendChild( dependenciesElement );
    1902                 :            : 
    1903                 :            :   // change dependencies
    1904                 :          0 :   QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
    1905                 :          0 :   for ( const QgsMapLayerDependency &dep : constDependencies )
    1906                 :            :   {
    1907                 :          0 :     if ( dep.type() != QgsMapLayerDependency::DataDependency )
    1908                 :          0 :       continue;
    1909                 :          0 :     QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
    1910                 :          0 :     depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
    1911                 :          0 :     dataDependenciesElement.appendChild( depElem );
    1912                 :          0 :   }
    1913                 :          0 :   layer_node.appendChild( dataDependenciesElement );
    1914                 :            : 
    1915                 :            :   // save expression fields
    1916                 :          0 :   mExpressionFieldBuffer->writeXml( layer_node, document );
    1917                 :            : 
    1918                 :          0 :   writeStyleManager( layer_node, document );
    1919                 :            : 
    1920                 :            :   // auxiliary layer
    1921                 :          0 :   QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
    1922                 :          0 :   if ( mAuxiliaryLayer )
    1923                 :            :   {
    1924                 :          0 :     const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
    1925                 :          0 :     asElem.setAttribute( QStringLiteral( "key" ), pkField );
    1926                 :          0 :   }
    1927                 :          0 :   layer_node.appendChild( asElem );
    1928                 :            : 
    1929                 :            :   // save QGIS Server WMS Dimension definitions
    1930                 :          0 :   mServerProperties->writeXml( layer_node, document );
    1931                 :            : 
    1932                 :            :   // renderer specific settings
    1933                 :          0 :   QString errorMsg;
    1934                 :          0 :   return writeSymbology( layer_node, document, errorMsg, context );
    1935                 :          0 : }
    1936                 :            : 
    1937                 :          0 : QString QgsVectorLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
    1938                 :            : {
    1939                 :          0 :   QString src( source );
    1940                 :            : 
    1941                 :            :   // TODO: what about postgres, mysql and others, they should not go through writePath()
    1942                 :          0 :   if ( providerType() == QLatin1String( "spatialite" ) )
    1943                 :            :   {
    1944                 :          0 :     QgsDataSourceUri uri( src );
    1945                 :          0 :     QString database = context.pathResolver().writePath( uri.database() );
    1946                 :          0 :     uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
    1947                 :          0 :     src = uri.uri();
    1948                 :          0 :   }
    1949                 :          0 :   else if ( providerType() == QLatin1String( "ogr" ) )
    1950                 :            :   {
    1951                 :          0 :     QStringList theURIParts = src.split( '|' );
    1952                 :          0 :     theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
    1953                 :          0 :     src = theURIParts.join( QLatin1Char( '|' ) );
    1954                 :          0 :   }
    1955                 :          0 :   else if ( providerType() == QLatin1String( "gpx" ) )
    1956                 :            :   {
    1957                 :          0 :     QStringList theURIParts = src.split( '?' );
    1958                 :          0 :     theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
    1959                 :          0 :     src = theURIParts.join( QLatin1Char( '?' ) );
    1960                 :          0 :   }
    1961                 :          0 :   else if ( providerType() == QLatin1String( "delimitedtext" ) )
    1962                 :            :   {
    1963                 :          0 :     QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
    1964                 :          0 :     QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
    1965                 :          0 :     urlDest.setQuery( urlSource.query() );
    1966                 :          0 :     src = QString::fromLatin1( urlDest.toEncoded() );
    1967                 :          0 :   }
    1968                 :          0 :   else if ( providerType() == QLatin1String( "memory" ) )
    1969                 :            :   {
    1970                 :            :     // Refetch the source from the provider, because adding fields actually changes the source for this provider.
    1971                 :          0 :     src = dataProvider()->dataSourceUri();
    1972                 :          0 :   }
    1973                 :          0 :   else if ( providerType() == QLatin1String( "virtual" ) )
    1974                 :            :   {
    1975                 :          0 :     QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
    1976                 :          0 :     QStringList theURIParts;
    1977                 :            : 
    1978                 :          0 :     QUrlQuery query = QUrlQuery( urlSource.query() );
    1979                 :          0 :     QList<QPair<QString, QString> > queryItems = query.queryItems();
    1980                 :            : 
    1981                 :          0 :     for ( int i = 0; i < queryItems.size(); i++ )
    1982                 :            :     {
    1983                 :          0 :       QString key = queryItems.at( i ).first;
    1984                 :          0 :       QString value = queryItems.at( i ).second;
    1985                 :          0 :       if ( key == QLatin1String( "layer" ) )
    1986                 :            :       {
    1987                 :            :         // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
    1988                 :          0 :         theURIParts = value.split( ':' );
    1989                 :          0 :         theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
    1990                 :            : 
    1991                 :          0 :         if ( theURIParts[0] == QLatin1String( "delimitedtext" ) )
    1992                 :            :         {
    1993                 :          0 :           QUrl urlSource = QUrl( theURIParts[1] );
    1994                 :          0 :           QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
    1995                 :          0 :           urlDest.setQuery( urlSource.query() );
    1996                 :          0 :           theURIParts[1] = QUrl::toPercentEncoding( urlDest.toString(), QByteArray( "" ), QByteArray( ":" ) );
    1997                 :          0 :         }
    1998                 :            :         else
    1999                 :            :         {
    2000                 :          0 :           theURIParts[1] = context.pathResolver().writePath( theURIParts[1] );
    2001                 :          0 :           theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
    2002                 :            :         }
    2003                 :            : 
    2004                 :          0 :         queryItems[i].second =  theURIParts.join( QLatin1Char( ':' ) ) ;
    2005                 :          0 :       }
    2006                 :          0 :     }
    2007                 :            : 
    2008                 :          0 :     query.setQueryItems( queryItems );
    2009                 :            : 
    2010                 :          0 :     QUrl urlDest = QUrl( urlSource );
    2011                 :          0 :     urlDest.setQuery( query.query() );
    2012                 :          0 :     src = QString::fromLatin1( urlDest.toEncoded() );
    2013                 :          0 :   }
    2014                 :            :   else
    2015                 :            :   {
    2016                 :          0 :     src = context.pathResolver().writePath( src );
    2017                 :            :   }
    2018                 :            : 
    2019                 :          0 :   return src;
    2020                 :          0 : }
    2021                 :            : 
    2022                 :          0 : QString QgsVectorLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
    2023                 :            : {
    2024                 :          0 :   QString src( source );
    2025                 :            : 
    2026                 :          0 :   if ( provider == QLatin1String( "spatialite" ) )
    2027                 :            :   {
    2028                 :          0 :     QgsDataSourceUri uri( src );
    2029                 :          0 :     uri.setDatabase( context.pathResolver().readPath( uri.database() ) );
    2030                 :          0 :     src = uri.uri();
    2031                 :          0 :   }
    2032                 :          0 :   else if ( provider == QLatin1String( "ogr" ) )
    2033                 :            :   {
    2034                 :          0 :     QStringList theURIParts = src.split( '|' );
    2035                 :          0 :     theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
    2036                 :          0 :     src = theURIParts.join( QLatin1Char( '|' ) );
    2037                 :          0 :   }
    2038                 :          0 :   else if ( provider == QLatin1String( "gpx" ) )
    2039                 :            :   {
    2040                 :          0 :     QStringList theURIParts = src.split( '?' );
    2041                 :          0 :     theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
    2042                 :          0 :     src = theURIParts.join( QLatin1Char( '?' ) );
    2043                 :          0 :   }
    2044                 :          0 :   else if ( provider == QLatin1String( "delimitedtext" ) )
    2045                 :            :   {
    2046                 :          0 :     QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
    2047                 :            : 
    2048                 :          0 :     if ( !src.startsWith( QLatin1String( "file:" ) ) )
    2049                 :            :     {
    2050                 :          0 :       QUrl file = QUrl::fromLocalFile( src.left( src.indexOf( '?' ) ) );
    2051                 :          0 :       urlSource.setScheme( QStringLiteral( "file" ) );
    2052                 :          0 :       urlSource.setPath( file.path() );
    2053                 :          0 :     }
    2054                 :            : 
    2055                 :          0 :     QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
    2056                 :          0 :     urlDest.setQuery( urlSource.query() );
    2057                 :          0 :     src = QString::fromLatin1( urlDest.toEncoded() );
    2058                 :          0 :   }
    2059                 :          0 :   else if ( provider == QLatin1String( "virtual" ) )
    2060                 :            :   {
    2061                 :          0 :     QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
    2062                 :          0 :     QStringList theURIParts;
    2063                 :            : 
    2064                 :          0 :     QUrlQuery query = QUrlQuery( urlSource.query() );
    2065                 :          0 :     QList<QPair<QString, QString> > queryItems = query.queryItems();
    2066                 :            : 
    2067                 :          0 :     for ( int i = 0; i < queryItems.size(); i++ )
    2068                 :            :     {
    2069                 :          0 :       QString key = queryItems.at( i ).first;
    2070                 :          0 :       QString value = queryItems.at( i ).second;
    2071                 :          0 :       if ( key == QLatin1String( "layer" ) )
    2072                 :            :       {
    2073                 :            :         // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
    2074                 :          0 :         theURIParts = value.split( ':' );
    2075                 :          0 :         theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
    2076                 :            : 
    2077                 :          0 :         if ( theURIParts[0] == QLatin1String( "delimitedtext" ) )
    2078                 :            :         {
    2079                 :          0 :           QUrl urlSource = QUrl( theURIParts[1] );
    2080                 :            : 
    2081                 :          0 :           if ( !theURIParts[1].startsWith( QLatin1String( "file:" ) ) )
    2082                 :            :           {
    2083                 :          0 :             QUrl file = QUrl::fromLocalFile( theURIParts[1].left( theURIParts[1].indexOf( '?' ) ) );
    2084                 :          0 :             urlSource.setScheme( QStringLiteral( "file" ) );
    2085                 :          0 :             urlSource.setPath( file.path() );
    2086                 :          0 :           }
    2087                 :            : 
    2088                 :          0 :           QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
    2089                 :          0 :           urlDest.setQuery( urlSource.query() );
    2090                 :            : 
    2091                 :          0 :           theURIParts[1] = urlDest.toString();
    2092                 :          0 :         }
    2093                 :            :         else
    2094                 :            :         {
    2095                 :          0 :           theURIParts[1] = context.pathResolver().readPath( theURIParts[1] );
    2096                 :            :         }
    2097                 :            : 
    2098                 :          0 :         theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
    2099                 :          0 :         queryItems[i].second =  theURIParts.join( QLatin1Char( ':' ) ) ;
    2100                 :          0 :       }
    2101                 :          0 :     }
    2102                 :            : 
    2103                 :          0 :     query.setQueryItems( queryItems );
    2104                 :            : 
    2105                 :          0 :     QUrl urlDest = QUrl( urlSource );
    2106                 :          0 :     urlDest.setQuery( query.query() );
    2107                 :          0 :     src = QString::fromLatin1( urlDest.toEncoded() );
    2108                 :          0 :   }
    2109                 :            :   else
    2110                 :            :   {
    2111                 :          0 :     src = context.pathResolver().readPath( src );
    2112                 :            :   }
    2113                 :            : 
    2114                 :          0 :   return src;
    2115                 :          0 : }
    2116                 :            : 
    2117                 :            : 
    2118                 :            : 
    2119                 :          0 : void QgsVectorLayer::resolveReferences( QgsProject *project )
    2120                 :            : {
    2121                 :          0 :   QgsMapLayer::resolveReferences( project );
    2122                 :          0 :   mJoinBuffer->resolveReferences( project );
    2123                 :          0 : }
    2124                 :            : 
    2125                 :            : 
    2126                 :          0 : bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage,
    2127                 :            :                                     QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
    2128                 :            : {
    2129                 :          0 :   QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Symbology" ) );
    2130                 :            : 
    2131                 :          0 :   if ( categories.testFlag( Fields ) )
    2132                 :            :   {
    2133                 :          0 :     if ( !mExpressionFieldBuffer )
    2134                 :          0 :       mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
    2135                 :          0 :     mExpressionFieldBuffer->readXml( layerNode );
    2136                 :            : 
    2137                 :          0 :     updateFields();
    2138                 :          0 :   }
    2139                 :            : 
    2140                 :          0 :   if ( categories.testFlag( Relations ) )
    2141                 :            :   {
    2142                 :            : 
    2143                 :          0 :     const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
    2144                 :            : 
    2145                 :            :     // Restore referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
    2146                 :          0 :     QDomNodeList referencedLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencedLayers" ) );
    2147                 :          0 :     if ( referencedLayersNodeList.size() > 0 )
    2148                 :            :     {
    2149                 :          0 :       const QDomNodeList relationNodes { referencedLayersNodeList.at( 0 ).childNodes() };
    2150                 :          0 :       for ( int i = 0; i < relationNodes.length(); ++i )
    2151                 :            :       {
    2152                 :          0 :         const QDomElement relationElement = relationNodes.at( i ).toElement();
    2153                 :            : 
    2154                 :          0 :         mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referencing, relationElement, resolver ) );
    2155                 :          0 :       }
    2156                 :          0 :     }
    2157                 :            : 
    2158                 :            :     // Restore referencing layers: relations where "this" is the parent layer (the referenced part where the FK points to)
    2159                 :          0 :     QDomNodeList referencingLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencingLayers" ) );
    2160                 :          0 :     if ( referencingLayersNodeList.size() > 0 )
    2161                 :            :     {
    2162                 :          0 :       const QDomNodeList relationNodes { referencingLayersNodeList.at( 0 ).childNodes() };
    2163                 :          0 :       for ( int i = 0; i < relationNodes.length(); ++i )
    2164                 :            :       {
    2165                 :          0 :         const QDomElement relationElement = relationNodes.at( i ).toElement();
    2166                 :          0 :         mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referenced, relationElement, resolver ) );
    2167                 :          0 :       }
    2168                 :          0 :     }
    2169                 :          0 :   }
    2170                 :            : 
    2171                 :          0 :   QDomElement layerElement = layerNode.toElement();
    2172                 :            : 
    2173                 :          0 :   readCommonStyle( layerElement, context, categories );
    2174                 :            : 
    2175                 :          0 :   readStyle( layerNode, errorMessage, context, categories );
    2176                 :            : 
    2177                 :          0 :   if ( categories.testFlag( MapTips ) )
    2178                 :          0 :     mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
    2179                 :            : 
    2180                 :          0 :   if ( categories.testFlag( LayerConfiguration ) )
    2181                 :          0 :     mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
    2182                 :            : 
    2183                 :            :   // Try to migrate pre QGIS 3.0 display field property
    2184                 :          0 :   QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
    2185                 :          0 :   if ( mFields.lookupField( displayField ) < 0 )
    2186                 :            :   {
    2187                 :            :     // if it's not a field, it's a maptip
    2188                 :          0 :     if ( mMapTipTemplate.isEmpty() && categories.testFlag( MapTips ) )
    2189                 :          0 :       mMapTipTemplate = displayField;
    2190                 :          0 :   }
    2191                 :            :   else
    2192                 :            :   {
    2193                 :          0 :     if ( mDisplayExpression.isEmpty() && categories.testFlag( LayerConfiguration ) )
    2194                 :          0 :       mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
    2195                 :            :   }
    2196                 :            : 
    2197                 :            :   // process the attribute actions
    2198                 :          0 :   if ( categories.testFlag( Actions ) )
    2199                 :          0 :     mActions->readXml( layerNode );
    2200                 :            : 
    2201                 :          0 :   if ( categories.testFlag( Fields ) )
    2202                 :            :   {
    2203                 :          0 :     mAttributeAliasMap.clear();
    2204                 :          0 :     QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
    2205                 :          0 :     if ( !aliasesNode.isNull() )
    2206                 :            :     {
    2207                 :          0 :       QDomElement aliasElem;
    2208                 :            : 
    2209                 :          0 :       QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
    2210                 :          0 :       for ( int i = 0; i < aliasNodeList.size(); ++i )
    2211                 :            :       {
    2212                 :          0 :         aliasElem = aliasNodeList.at( i ).toElement();
    2213                 :            : 
    2214                 :          0 :         QString field;
    2215                 :          0 :         if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
    2216                 :            :         {
    2217                 :          0 :           field = aliasElem.attribute( QStringLiteral( "field" ) );
    2218                 :          0 :         }
    2219                 :            :         else
    2220                 :            :         {
    2221                 :          0 :           int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
    2222                 :            : 
    2223                 :          0 :           if ( index >= 0 && index < fields().count() )
    2224                 :          0 :             field = fields().at( index ).name();
    2225                 :            :         }
    2226                 :            : 
    2227                 :          0 :         QString alias;
    2228                 :            : 
    2229                 :          0 :         if ( !aliasElem.attribute( QStringLiteral( "name" ) ).isEmpty() )
    2230                 :            :         {
    2231                 :            :           //if it has alias
    2232                 :          0 :           alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral( "name" ) ) );
    2233                 :          0 :           QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + aliasElem.attribute( QStringLiteral( "name" ) ), 3 );
    2234                 :          0 :         }
    2235                 :            :         else
    2236                 :            :         {
    2237                 :            :           //if it has no alias, it should be the fields translation
    2238                 :          0 :           alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), field );
    2239                 :          0 :           QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + field, 3 );
    2240                 :            :           //if it gets the exact field value, there has been no translation (or not even translation loaded) - so no alias should be generated;
    2241                 :          0 :           if ( alias == aliasElem.attribute( QStringLiteral( "field" ) ) )
    2242                 :          0 :             alias.clear();
    2243                 :            :         }
    2244                 :            : 
    2245                 :          0 :         QgsDebugMsgLevel( "field " + field + " origalias " + aliasElem.attribute( QStringLiteral( "name" ) ) + " trans " + alias, 3 );
    2246                 :          0 :         mAttributeAliasMap.insert( field, alias );
    2247                 :          0 :       }
    2248                 :          0 :     }
    2249                 :            : 
    2250                 :            :     // default expressions
    2251                 :          0 :     mDefaultExpressionMap.clear();
    2252                 :          0 :     QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
    2253                 :          0 :     if ( !defaultsNode.isNull() )
    2254                 :            :     {
    2255                 :          0 :       QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
    2256                 :          0 :       for ( int i = 0; i < defaultNodeList.size(); ++i )
    2257                 :            :       {
    2258                 :          0 :         QDomElement defaultElem = defaultNodeList.at( i ).toElement();
    2259                 :            : 
    2260                 :          0 :         QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
    2261                 :          0 :         QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
    2262                 :          0 :         bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
    2263                 :          0 :         if ( field.isEmpty() || expression.isEmpty() )
    2264                 :          0 :           continue;
    2265                 :            : 
    2266                 :          0 :         mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
    2267                 :          0 :       }
    2268                 :          0 :     }
    2269                 :            : 
    2270                 :            :     // constraints
    2271                 :          0 :     mFieldConstraints.clear();
    2272                 :          0 :     mFieldConstraintStrength.clear();
    2273                 :          0 :     QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
    2274                 :          0 :     if ( !constraintsNode.isNull() )
    2275                 :            :     {
    2276                 :          0 :       QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
    2277                 :          0 :       for ( int i = 0; i < constraintNodeList.size(); ++i )
    2278                 :            :       {
    2279                 :          0 :         QDomElement constraintElem = constraintNodeList.at( i ).toElement();
    2280                 :            : 
    2281                 :          0 :         QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
    2282                 :          0 :         int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
    2283                 :          0 :         if ( field.isEmpty() || constraints == 0 )
    2284                 :          0 :           continue;
    2285                 :            : 
    2286                 :          0 :         mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
    2287                 :            : 
    2288                 :          0 :         int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
    2289                 :          0 :         int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
    2290                 :          0 :         int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
    2291                 :            : 
    2292                 :          0 :         mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
    2293                 :          0 :         mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
    2294                 :          0 :         mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
    2295                 :          0 :       }
    2296                 :          0 :     }
    2297                 :          0 :     mFieldConstraintExpressions.clear();
    2298                 :          0 :     QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
    2299                 :          0 :     if ( !constraintExpressionsNode.isNull() )
    2300                 :            :     {
    2301                 :          0 :       QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
    2302                 :          0 :       for ( int i = 0; i < constraintNodeList.size(); ++i )
    2303                 :            :       {
    2304                 :          0 :         QDomElement constraintElem = constraintNodeList.at( i ).toElement();
    2305                 :            : 
    2306                 :          0 :         QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
    2307                 :          0 :         QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
    2308                 :          0 :         QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
    2309                 :          0 :         if ( field.isEmpty() || exp.isEmpty() )
    2310                 :          0 :           continue;
    2311                 :            : 
    2312                 :          0 :         mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
    2313                 :          0 :       }
    2314                 :          0 :     }
    2315                 :            : 
    2316                 :          0 :     updateFields();
    2317                 :          0 :   }
    2318                 :            : 
    2319                 :            :   // load field configuration
    2320                 :          0 :   if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
    2321                 :            :   {
    2322                 :          0 :     QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
    2323                 :          0 :     QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
    2324                 :          0 :     for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
    2325                 :            :     {
    2326                 :          0 :       const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
    2327                 :          0 :       const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
    2328                 :            : 
    2329                 :          0 :       QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
    2330                 :            : 
    2331                 :          0 :       if ( categories.testFlag( Fields ) )
    2332                 :          0 :         mFieldConfigurationFlags[fieldName] = qgsFlagKeysToValue( fieldConfigElement.attribute( QStringLiteral( "configurationFlags" ) ), QgsField::ConfigurationFlag::None );
    2333                 :            : 
    2334                 :            :       // Load editor widget configuration
    2335                 :          0 :       if ( categories.testFlag( Forms ) )
    2336                 :            :       {
    2337                 :          0 :         const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
    2338                 :          0 :         const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
    2339                 :          0 :         const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
    2340                 :          0 :         QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
    2341                 :          0 :         if ( widgetType == QLatin1String( "ValueRelation" ) )
    2342                 :            :         {
    2343                 :          0 :           optionsMap[ QStringLiteral( "Value" ) ] = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fields:%2:valuerelationvalue" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text(), fieldName ), optionsMap[ QStringLiteral( "Value" ) ].toString() );
    2344                 :          0 :         }
    2345                 :          0 :         QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
    2346                 :          0 :         mFieldWidgetSetups[fieldName] = setup;
    2347                 :          0 :       }
    2348                 :          0 :     }
    2349                 :          0 :   }
    2350                 :            : 
    2351                 :            :   // Legacy reading for QGIS 3.14 and older projects
    2352                 :            :   // Attributes excluded from WMS and WFS
    2353                 :          0 :   if ( categories.testFlag( Fields ) )
    2354                 :            :   {
    2355                 :          0 :     const QList<QPair<QString, QgsField::ConfigurationFlag>> legacyConfig
    2356                 :          0 :     {
    2357                 :          0 :       qMakePair( QStringLiteral( "excludeAttributesWMS" ), QgsField::ConfigurationFlag::HideFromWms ),
    2358                 :          0 :       qMakePair( QStringLiteral( "excludeAttributesWFS" ), QgsField::ConfigurationFlag::HideFromWfs )
    2359                 :            :     };
    2360                 :          0 :     for ( const auto &config : legacyConfig )
    2361                 :            :     {
    2362                 :          0 :       QDomNode excludeNode = layerNode.namedItem( config.first );
    2363                 :          0 :       if ( !excludeNode.isNull() )
    2364                 :            :       {
    2365                 :          0 :         QDomNodeList attributeNodeList = excludeNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
    2366                 :          0 :         for ( int i = 0; i < attributeNodeList.size(); ++i )
    2367                 :            :         {
    2368                 :          0 :           QString fieldName = attributeNodeList.at( i ).toElement().text();
    2369                 :          0 :           if ( !mFieldConfigurationFlags.contains( fieldName ) )
    2370                 :          0 :             mFieldConfigurationFlags[fieldName] = config.second;
    2371                 :            :           else
    2372                 :          0 :             mFieldConfigurationFlags[fieldName].setFlag( config.second, true );
    2373                 :          0 :         }
    2374                 :          0 :       }
    2375                 :          0 :     }
    2376                 :          0 :   }
    2377                 :            : 
    2378                 :          0 :   if ( categories.testFlag( GeometryOptions ) )
    2379                 :          0 :     mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral( "geometryOptions" ) ) );
    2380                 :            : 
    2381                 :          0 :   if ( categories.testFlag( Forms ) )
    2382                 :          0 :     mEditFormConfig.readXml( layerNode, context );
    2383                 :            : 
    2384                 :          0 :   if ( categories.testFlag( AttributeTable ) )
    2385                 :            :   {
    2386                 :          0 :     mAttributeTableConfig.readXml( layerNode );
    2387                 :          0 :     mConditionalStyles->readXml( layerNode, context );
    2388                 :          0 :     mStoredExpressionManager->readXml( layerNode );
    2389                 :          0 :   }
    2390                 :            : 
    2391                 :          0 :   if ( categories.testFlag( CustomProperties ) )
    2392                 :          0 :     readCustomProperties( layerNode, QStringLiteral( "variable" ) );
    2393                 :            : 
    2394                 :          0 :   QDomElement mapLayerNode = layerNode.toElement();
    2395                 :          0 :   if ( categories.testFlag( LayerConfiguration )
    2396                 :          0 :        && mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
    2397                 :          0 :     mReadOnly = true;
    2398                 :            : 
    2399                 :          0 :   updateFields();
    2400                 :            : 
    2401                 :          0 :   if ( categories.testFlag( Legend ) )
    2402                 :            :   {
    2403                 :          0 :     const QDomElement legendElem = layerNode.firstChildElement( QStringLiteral( "legend" ) );
    2404                 :          0 :     if ( !legendElem.isNull() )
    2405                 :            :     {
    2406                 :          0 :       std::unique_ptr< QgsMapLayerLegend > legend( QgsMapLayerLegend::defaultVectorLegend( this ) );
    2407                 :          0 :       legend->readXml( legendElem, context );
    2408                 :          0 :       setLegend( legend.release() );
    2409                 :          0 :       mSetLegendFromStyle = true;
    2410                 :          0 :     }
    2411                 :          0 :   }
    2412                 :            : 
    2413                 :            :   return true;
    2414                 :          0 : }
    2415                 :            : 
    2416                 :          0 : bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage,
    2417                 :            :                                 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
    2418                 :            : {
    2419                 :          0 :   bool result = true;
    2420                 :          0 :   emit readCustomSymbology( node.toElement(), errorMessage );
    2421                 :            : 
    2422                 :            :   // we must try to restore a renderer if our geometry type is unknown
    2423                 :            :   // as this allows the renderer to be correctly restored even for layers
    2424                 :            :   // with broken sources
    2425                 :          0 :   if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
    2426                 :            :   {
    2427                 :            :     // try renderer v2 first
    2428                 :          0 :     if ( categories.testFlag( Symbology ) )
    2429                 :            :     {
    2430                 :          0 :       QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
    2431                 :          0 :       if ( !rendererElement.isNull() )
    2432                 :            :       {
    2433                 :          0 :         QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
    2434                 :          0 :         if ( r )
    2435                 :            :         {
    2436                 :          0 :           setRenderer( r );
    2437                 :          0 :         }
    2438                 :            :         else
    2439                 :            :         {
    2440                 :          0 :           result = false;
    2441                 :            :         }
    2442                 :          0 :       }
    2443                 :            :       // make sure layer has a renderer - if none exists, fallback to a default renderer
    2444                 :          0 :       if ( isSpatial() && !renderer() )
    2445                 :            :       {
    2446                 :          0 :         setRenderer( QgsFeatureRenderer::defaultRenderer( geometryType() ) );
    2447                 :          0 :       }
    2448                 :          0 :     }
    2449                 :            : 
    2450                 :            :     // read labeling definition
    2451                 :          0 :     if ( categories.testFlag( Labeling ) )
    2452                 :            :     {
    2453                 :          0 :       QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
    2454                 :          0 :       QgsAbstractVectorLayerLabeling *labeling = nullptr;
    2455                 :          0 :       if ( labelingElement.isNull() ||
    2456                 :          0 :            ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
    2457                 :            :       {
    2458                 :            :         // make sure we have custom properties for labeling for 2.x projects
    2459                 :            :         // (custom properties should be already loaded when reading the whole layer from XML,
    2460                 :            :         // but when reading style, custom properties are not read)
    2461                 :          0 :         readCustomProperties( node, QStringLiteral( "labeling" ) );
    2462                 :            : 
    2463                 :            :         // support for pre-QGIS 3 labeling configurations written in custom properties
    2464                 :          0 :         labeling = readLabelingFromCustomProperties();
    2465                 :          0 :       }
    2466                 :            :       else
    2467                 :            :       {
    2468                 :          0 :         labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
    2469                 :            :       }
    2470                 :          0 :       setLabeling( labeling );
    2471                 :            : 
    2472                 :          0 :       if ( node.toElement().hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
    2473                 :          0 :         mLabelsEnabled = node.toElement().attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
    2474                 :            :       else
    2475                 :          0 :         mLabelsEnabled = true;
    2476                 :          0 :     }
    2477                 :            : 
    2478                 :          0 :     if ( categories.testFlag( Symbology ) )
    2479                 :            :     {
    2480                 :            :       // get and set the blend mode if it exists
    2481                 :          0 :       QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
    2482                 :          0 :       if ( !blendModeNode.isNull() )
    2483                 :            :       {
    2484                 :          0 :         QDomElement e = blendModeNode.toElement();
    2485                 :          0 :         setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
    2486                 :          0 :       }
    2487                 :            : 
    2488                 :            :       // get and set the feature blend mode if it exists
    2489                 :          0 :       QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
    2490                 :          0 :       if ( !featureBlendModeNode.isNull() )
    2491                 :            :       {
    2492                 :          0 :         QDomElement e = featureBlendModeNode.toElement();
    2493                 :          0 :         setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
    2494                 :          0 :       }
    2495                 :          0 :     }
    2496                 :            : 
    2497                 :            :     // get and set the layer transparency and scale visibility if they exists
    2498                 :          0 :     if ( categories.testFlag( Rendering ) )
    2499                 :            :     {
    2500                 :          0 :       QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
    2501                 :          0 :       if ( !layerTransparencyNode.isNull() )
    2502                 :            :       {
    2503                 :          0 :         QDomElement e = layerTransparencyNode.toElement();
    2504                 :          0 :         setOpacity( 1.0 - e.text().toInt() / 100.0 );
    2505                 :          0 :       }
    2506                 :          0 :       QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
    2507                 :          0 :       if ( !layerOpacityNode.isNull() )
    2508                 :            :       {
    2509                 :          0 :         QDomElement e = layerOpacityNode.toElement();
    2510                 :          0 :         setOpacity( e.text().toDouble() );
    2511                 :          0 :       }
    2512                 :            : 
    2513                 :          0 :       const bool hasScaleBasedVisibiliy { node.attributes().namedItem( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).nodeValue() == '1' };
    2514                 :          0 :       setScaleBasedVisibility( hasScaleBasedVisibiliy );
    2515                 :            :       bool ok;
    2516                 :          0 :       const double maxScale { node.attributes().namedItem( QStringLiteral( "maxScale" ) ).nodeValue().toDouble( &ok ) };
    2517                 :          0 :       if ( ok )
    2518                 :            :       {
    2519                 :          0 :         setMaximumScale( maxScale );
    2520                 :          0 :       }
    2521                 :          0 :       const double minScale { node.attributes().namedItem( QStringLiteral( "minScale" ) ).nodeValue().toDouble( &ok ) };
    2522                 :          0 :       if ( ok )
    2523                 :            :       {
    2524                 :          0 :         setMinimumScale( minScale );
    2525                 :          0 :       }
    2526                 :          0 :     }
    2527                 :            : 
    2528                 :          0 :     if ( categories.testFlag( Rendering ) )
    2529                 :            :     {
    2530                 :          0 :       QDomElement e = node.toElement();
    2531                 :            : 
    2532                 :            :       // get the simplification drawing settings
    2533                 :          0 :       mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
    2534                 :          0 :       mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
    2535                 :          0 :       mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
    2536                 :          0 :       mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
    2537                 :          0 :       mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
    2538                 :          0 :     }
    2539                 :            : 
    2540                 :            :     //diagram renderer and diagram layer settings
    2541                 :          0 :     if ( categories.testFlag( Diagrams ) )
    2542                 :            :     {
    2543                 :          0 :       delete mDiagramRenderer;
    2544                 :          0 :       mDiagramRenderer = nullptr;
    2545                 :          0 :       QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
    2546                 :          0 :       if ( !singleCatDiagramElem.isNull() )
    2547                 :            :       {
    2548                 :          0 :         mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
    2549                 :          0 :         mDiagramRenderer->readXml( singleCatDiagramElem, context );
    2550                 :          0 :       }
    2551                 :          0 :       QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
    2552                 :          0 :       if ( !linearDiagramElem.isNull() )
    2553                 :            :       {
    2554                 :          0 :         if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
    2555                 :            :         {
    2556                 :            :           // fix project from before QGIS 3.0
    2557                 :          0 :           int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
    2558                 :          0 :           if ( idx >= 0 && idx < mFields.count() )
    2559                 :          0 :             linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
    2560                 :          0 :         }
    2561                 :            : 
    2562                 :          0 :         mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
    2563                 :          0 :         mDiagramRenderer->readXml( linearDiagramElem, context );
    2564                 :          0 :       }
    2565                 :            : 
    2566                 :          0 :       if ( mDiagramRenderer )
    2567                 :            :       {
    2568                 :          0 :         QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
    2569                 :          0 :         if ( !diagramSettingsElem.isNull() )
    2570                 :            :         {
    2571                 :          0 :           bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
    2572                 :          0 :           bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
    2573                 :          0 :           bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
    2574                 :          0 :           if ( oldXPos || oldYPos || oldShow )
    2575                 :            :           {
    2576                 :            :             // fix project from before QGIS 3.0
    2577                 :          0 :             QgsPropertyCollection ddp;
    2578                 :          0 :             if ( oldXPos )
    2579                 :            :             {
    2580                 :          0 :               int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
    2581                 :          0 :               if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
    2582                 :          0 :                 ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
    2583                 :          0 :             }
    2584                 :          0 :             if ( oldYPos )
    2585                 :            :             {
    2586                 :          0 :               int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
    2587                 :          0 :               if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
    2588                 :          0 :                 ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
    2589                 :          0 :             }
    2590                 :          0 :             if ( oldShow )
    2591                 :            :             {
    2592                 :          0 :               int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
    2593                 :          0 :               if ( showColumn >= 0 && showColumn < mFields.count() )
    2594                 :          0 :                 ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
    2595                 :          0 :             }
    2596                 :          0 :             QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
    2597                 :          0 :             QgsPropertiesDefinition defs = QgsPropertiesDefinition
    2598                 :          0 :             {
    2599                 :          0 :               { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
    2600                 :          0 :               { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
    2601                 :          0 :               { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
    2602                 :            :             };
    2603                 :          0 :             ddp.writeXml( propertiesElem, defs );
    2604                 :          0 :             diagramSettingsElem.appendChild( propertiesElem );
    2605                 :          0 :           }
    2606                 :            : 
    2607                 :          0 :           delete mDiagramLayerSettings;
    2608                 :          0 :           mDiagramLayerSettings = new QgsDiagramLayerSettings();
    2609                 :          0 :           mDiagramLayerSettings->readXml( diagramSettingsElem );
    2610                 :          0 :         }
    2611                 :          0 :       }
    2612                 :          0 :     }
    2613                 :            :     // end diagram
    2614                 :          0 :   }
    2615                 :          0 :   return result;
    2616                 :          0 : }
    2617                 :            : 
    2618                 :            : 
    2619                 :          0 : bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
    2620                 :            :                                      const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
    2621                 :            : {
    2622                 :          0 :   QDomElement layerElement = node.toElement();
    2623                 :          0 :   writeCommonStyle( layerElement, doc, context, categories );
    2624                 :            : 
    2625                 :          0 :   ( void )writeStyle( node, doc, errorMessage, context, categories );
    2626                 :            : 
    2627                 :          0 :   if ( categories.testFlag( GeometryOptions ) )
    2628                 :          0 :     mGeometryOptions->writeXml( node );
    2629                 :            : 
    2630                 :          0 :   if ( categories.testFlag( Legend ) && legend() )
    2631                 :            :   {
    2632                 :          0 :     QDomElement legendElement = legend()->writeXml( doc, context );
    2633                 :          0 :     if ( !legendElement.isNull() )
    2634                 :          0 :       node.appendChild( legendElement );
    2635                 :          0 :   }
    2636                 :            : 
    2637                 :            :   // Relation information for both referenced and referencing sides
    2638                 :          0 :   if ( categories.testFlag( Relations ) )
    2639                 :            :   {
    2640                 :            :     // Store referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
    2641                 :          0 :     QDomElement referencedLayersElement = doc.createElement( QStringLiteral( "referencedLayers" ) );
    2642                 :          0 :     node.appendChild( referencedLayersElement );
    2643                 :            : 
    2644                 :          0 :     const auto constReferencingRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
    2645                 :          0 :     for ( const auto &rel : constReferencingRelations )
    2646                 :            :     {
    2647                 :          0 :       if ( rel.type() == QgsRelation::Normal )
    2648                 :            :       {
    2649                 :          0 :         QgsWeakRelation::writeXml( this, QgsWeakRelation::Referencing, rel, referencedLayersElement, doc );
    2650                 :          0 :       }
    2651                 :            :     }
    2652                 :            : 
    2653                 :            :     // Store referencing layers: relations where "this" is the parent layer (the referenced part, that holds the FK)
    2654                 :          0 :     QDomElement referencingLayersElement = doc.createElement( QStringLiteral( "referencingLayers" ) );
    2655                 :          0 :     node.appendChild( referencedLayersElement );
    2656                 :            : 
    2657                 :          0 :     const auto constReferencedRelations { QgsProject::instance()->relationManager()->referencedRelations( this ) };
    2658                 :          0 :     for ( const auto &rel : constReferencedRelations )
    2659                 :            :     {
    2660                 :          0 :       if ( rel.type() == QgsRelation::Normal )
    2661                 :            :       {
    2662                 :          0 :         QgsWeakRelation::writeXml( this, QgsWeakRelation::Referenced, rel, referencingLayersElement, doc );
    2663                 :          0 :       }
    2664                 :            :     }
    2665                 :            : 
    2666                 :          0 :   }
    2667                 :            : 
    2668                 :            :   // write field configurations
    2669                 :          0 :   if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
    2670                 :            :   {
    2671                 :          0 :     QDomElement fieldConfigurationElement;
    2672                 :            :     // field configuration flag
    2673                 :          0 :     fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
    2674                 :          0 :     node.appendChild( fieldConfigurationElement );
    2675                 :            : 
    2676                 :          0 :     for ( const QgsField &field : std::as_const( mFields ) )
    2677                 :            :     {
    2678                 :          0 :       QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
    2679                 :          0 :       fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
    2680                 :          0 :       fieldConfigurationElement.appendChild( fieldElement );
    2681                 :            : 
    2682                 :          0 :       if ( categories.testFlag( Fields ) )
    2683                 :            :       {
    2684                 :          0 :         fieldElement.setAttribute( QStringLiteral( "configurationFlags" ), qgsFlagValueToKeys( field.configurationFlags() ) );
    2685                 :          0 :       }
    2686                 :            : 
    2687                 :          0 :       if ( categories.testFlag( Forms ) )
    2688                 :            :       {
    2689                 :          0 :         QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
    2690                 :            : 
    2691                 :            :         // TODO : wrap this part in an if to only save if it was user-modified
    2692                 :          0 :         QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
    2693                 :          0 :         fieldElement.appendChild( editWidgetElement );
    2694                 :          0 :         editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
    2695                 :          0 :         QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
    2696                 :            : 
    2697                 :          0 :         editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
    2698                 :          0 :         editWidgetElement.appendChild( editWidgetConfigElement );
    2699                 :            :         // END TODO : wrap this part in an if to only save if it was user-modified
    2700                 :          0 :       }
    2701                 :          0 :     }
    2702                 :          0 :   }
    2703                 :            : 
    2704                 :          0 :   if ( categories.testFlag( Fields ) )
    2705                 :            :   {
    2706                 :            :     //attribute aliases
    2707                 :          0 :     QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
    2708                 :          0 :     for ( const QgsField &field : std::as_const( mFields ) )
    2709                 :            :     {
    2710                 :          0 :       QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
    2711                 :          0 :       aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
    2712                 :          0 :       aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
    2713                 :          0 :       aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
    2714                 :          0 :       aliasElem.appendChild( aliasEntryElem );
    2715                 :          0 :     }
    2716                 :          0 :     node.appendChild( aliasElem );
    2717                 :            : 
    2718                 :            :     //default expressions
    2719                 :          0 :     QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
    2720                 :          0 :     for ( const QgsField &field : std::as_const( mFields ) )
    2721                 :            :     {
    2722                 :          0 :       QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
    2723                 :          0 :       defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
    2724                 :          0 :       defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
    2725                 :          0 :       defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
    2726                 :          0 :       defaultsElem.appendChild( defaultElem );
    2727                 :          0 :     }
    2728                 :          0 :     node.appendChild( defaultsElem );
    2729                 :            : 
    2730                 :            :     // constraints
    2731                 :          0 :     QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
    2732                 :          0 :     for ( const QgsField &field : std::as_const( mFields ) )
    2733                 :            :     {
    2734                 :          0 :       QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
    2735                 :          0 :       constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
    2736                 :          0 :       constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
    2737                 :          0 :       constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
    2738                 :          0 :       constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
    2739                 :          0 :       constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
    2740                 :          0 :       constraintsElem.appendChild( constraintElem );
    2741                 :          0 :     }
    2742                 :          0 :     node.appendChild( constraintsElem );
    2743                 :            : 
    2744                 :            :     // constraint expressions
    2745                 :          0 :     QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
    2746                 :          0 :     for ( const QgsField &field : std::as_const( mFields ) )
    2747                 :            :     {
    2748                 :          0 :       QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
    2749                 :          0 :       constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
    2750                 :          0 :       constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
    2751                 :          0 :       constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
    2752                 :          0 :       constraintExpressionsElem.appendChild( constraintExpressionElem );
    2753                 :          0 :     }
    2754                 :          0 :     node.appendChild( constraintExpressionsElem );
    2755                 :            : 
    2756                 :            :     // save expression fields
    2757                 :          0 :     if ( !mExpressionFieldBuffer )
    2758                 :            :     {
    2759                 :            :       // can happen when saving style on a invalid layer
    2760                 :          0 :       QgsExpressionFieldBuffer dummy;
    2761                 :          0 :       dummy.writeXml( node, doc );
    2762                 :          0 :     }
    2763                 :            :     else
    2764                 :            :     {
    2765                 :          0 :       mExpressionFieldBuffer->writeXml( node, doc );
    2766                 :            :     }
    2767                 :          0 :   }
    2768                 :            : 
    2769                 :            :   // add attribute actions
    2770                 :          0 :   if ( categories.testFlag( Actions ) )
    2771                 :          0 :     mActions->writeXml( node );
    2772                 :            : 
    2773                 :          0 :   if ( categories.testFlag( AttributeTable ) )
    2774                 :            :   {
    2775                 :          0 :     mAttributeTableConfig.writeXml( node );
    2776                 :          0 :     mConditionalStyles->writeXml( node, doc, context );
    2777                 :          0 :     mStoredExpressionManager->writeXml( node );
    2778                 :          0 :   }
    2779                 :            : 
    2780                 :          0 :   if ( categories.testFlag( Forms ) )
    2781                 :          0 :     mEditFormConfig.writeXml( node, context );
    2782                 :            : 
    2783                 :            :   // save readonly state
    2784                 :          0 :   if ( categories.testFlag( LayerConfiguration ) )
    2785                 :          0 :     node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
    2786                 :            : 
    2787                 :            :   // save preview expression
    2788                 :          0 :   if ( categories.testFlag( LayerConfiguration ) )
    2789                 :            :   {
    2790                 :          0 :     QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
    2791                 :          0 :     QDomText prevExpText = doc.createTextNode( mDisplayExpression );
    2792                 :          0 :     prevExpElem.appendChild( prevExpText );
    2793                 :          0 :     node.appendChild( prevExpElem );
    2794                 :          0 :   }
    2795                 :            : 
    2796                 :            :   // save map tip
    2797                 :          0 :   if ( categories.testFlag( MapTips ) )
    2798                 :            :   {
    2799                 :          0 :     QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
    2800                 :          0 :     QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
    2801                 :          0 :     mapTipElem.appendChild( mapTipText );
    2802                 :          0 :     node.toElement().appendChild( mapTipElem );
    2803                 :          0 :   }
    2804                 :            : 
    2805                 :            :   return true;
    2806                 :          0 : }
    2807                 :            : 
    2808                 :          0 : bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
    2809                 :            :                                  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
    2810                 :            : {
    2811                 :          0 :   QDomElement mapLayerNode = node.toElement();
    2812                 :            : 
    2813                 :          0 :   emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
    2814                 :            : 
    2815                 :            :   // we must try to write the renderer if our geometry type is unknown
    2816                 :            :   // as this allows the renderer to be correctly restored even for layers
    2817                 :            :   // with broken sources
    2818                 :          0 :   if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
    2819                 :            :   {
    2820                 :          0 :     if ( categories.testFlag( Symbology ) )
    2821                 :            :     {
    2822                 :          0 :       if ( mRenderer )
    2823                 :            :       {
    2824                 :          0 :         QDomElement rendererElement = mRenderer->save( doc, context );
    2825                 :          0 :         node.appendChild( rendererElement );
    2826                 :          0 :       }
    2827                 :          0 :     }
    2828                 :            : 
    2829                 :          0 :     if ( categories.testFlag( Labeling ) )
    2830                 :            :     {
    2831                 :          0 :       if ( mLabeling )
    2832                 :            :       {
    2833                 :          0 :         QDomElement labelingElement = mLabeling->save( doc, context );
    2834                 :          0 :         node.appendChild( labelingElement );
    2835                 :          0 :       }
    2836                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
    2837                 :          0 :     }
    2838                 :            : 
    2839                 :            :     // save the simplification drawing settings
    2840                 :          0 :     if ( categories.testFlag( Rendering ) )
    2841                 :            :     {
    2842                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
    2843                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
    2844                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
    2845                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
    2846                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
    2847                 :          0 :     }
    2848                 :            : 
    2849                 :            :     //save customproperties
    2850                 :          0 :     if ( categories.testFlag( CustomProperties ) )
    2851                 :            :     {
    2852                 :          0 :       writeCustomProperties( node, doc );
    2853                 :          0 :     }
    2854                 :            : 
    2855                 :          0 :     if ( categories.testFlag( Symbology ) )
    2856                 :            :     {
    2857                 :            :       // add the blend mode field
    2858                 :          0 :       QDomElement blendModeElem  = doc.createElement( QStringLiteral( "blendMode" ) );
    2859                 :          0 :       QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
    2860                 :          0 :       blendModeElem.appendChild( blendModeText );
    2861                 :          0 :       node.appendChild( blendModeElem );
    2862                 :            : 
    2863                 :            :       // add the feature blend mode field
    2864                 :          0 :       QDomElement featureBlendModeElem  = doc.createElement( QStringLiteral( "featureBlendMode" ) );
    2865                 :          0 :       QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
    2866                 :          0 :       featureBlendModeElem.appendChild( featureBlendModeText );
    2867                 :          0 :       node.appendChild( featureBlendModeElem );
    2868                 :          0 :     }
    2869                 :            : 
    2870                 :            :     // add the layer opacity and scale visibility
    2871                 :          0 :     if ( categories.testFlag( Rendering ) )
    2872                 :            :     {
    2873                 :          0 :       QDomElement layerOpacityElem  = doc.createElement( QStringLiteral( "layerOpacity" ) );
    2874                 :          0 :       QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
    2875                 :          0 :       layerOpacityElem.appendChild( layerOpacityText );
    2876                 :         78 :       node.appendChild( layerOpacityElem );
    2877                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
    2878                 :          0 :       mapLayerNode.setAttribute( QStringLiteral( "maxScale" ), maximumScale() );
    2879                 :         78 :       mapLayerNode.setAttribute( QStringLiteral( "minScale" ), minimumScale() );
    2880                 :          0 :     }
    2881                 :            : 
    2882                 :          0 :     if ( categories.testFlag( Diagrams ) && mDiagramRenderer )
    2883                 :            :     {
    2884                 :          0 :       mDiagramRenderer->writeXml( mapLayerNode, doc, context );
    2885                 :          0 :       if ( mDiagramLayerSettings )
    2886                 :          0 :         mDiagramLayerSettings->writeXml( mapLayerNode, doc );
    2887                 :          0 :     }
    2888                 :          0 :   }
    2889                 :            :   return true;
    2890                 :         78 : }
    2891                 :            : 
    2892                 :          0 : bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
    2893                 :         78 : {
    2894                 :            :   // get the Name element
    2895                 :          0 :   QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
    2896                 :          0 :   if ( nameElem.isNull() )
    2897                 :            :   {
    2898                 :          0 :     errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
    2899                 :          0 :   }
    2900                 :            : 
    2901                 :          0 :   if ( isSpatial() )
    2902                 :            :   {
    2903                 :          0 :     QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
    2904                 :          0 :     if ( !r )
    2905                 :          0 :       return false;
    2906                 :            : 
    2907                 :          0 :     setRenderer( r );
    2908                 :            : 
    2909                 :            :     // labeling
    2910                 :          0 :     readSldLabeling( node );
    2911                 :          0 :   }
    2912                 :          0 :   return true;
    2913                 :          0 : }
    2914                 :            : 
    2915                 :          0 : bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props ) const
    2916                 :            : {
    2917                 :          0 :   Q_UNUSED( errorMessage )
    2918                 :            : 
    2919                 :          0 :   QVariantMap localProps = QVariantMap( props );
    2920                 :          0 :   if ( hasScaleBasedVisibility() )
    2921                 :            :   {
    2922                 :          0 :     QgsSymbolLayerUtils::mergeScaleDependencies( maximumScale(), minimumScale(), localProps );
    2923                 :          0 :   }
    2924                 :            : 
    2925                 :          0 :   if ( isSpatial() )
    2926                 :            :   {
    2927                 :            :     // store the Name element
    2928                 :          0 :     QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
    2929                 :          0 :     nameNode.appendChild( doc.createTextNode( name() ) );
    2930                 :          0 :     node.appendChild( nameNode );
    2931                 :            : 
    2932                 :          0 :     QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
    2933                 :          0 :     node.appendChild( userStyleElem );
    2934                 :            : 
    2935                 :         78 :     QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
    2936                 :          0 :     nameElem.appendChild( doc.createTextNode( name() ) );
    2937                 :            : 
    2938                 :         78 :     userStyleElem.appendChild( nameElem );
    2939                 :            : 
    2940                 :          0 :     QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
    2941                 :          0 :     userStyleElem.appendChild( featureTypeStyleElem );
    2942                 :            : 
    2943                 :          0 :     mRenderer->toSld( doc, featureTypeStyleElem, localProps );
    2944                 :         78 :     if ( labelsEnabled() )
    2945                 :            :     {
    2946                 :          0 :       mLabeling->toSld( featureTypeStyleElem, localProps );
    2947                 :         78 :     }
    2948                 :          0 :   }
    2949                 :            :   return true;
    2950                 :         78 : }
    2951                 :            : 
    2952                 :            : 
    2953                 :         79 : bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
    2954                 :            : {
    2955                 :          1 :   if ( !mEditBuffer || !mDataProvider )
    2956                 :         78 :   {
    2957                 :          0 :     return false;
    2958                 :            :   }
    2959                 :            : 
    2960                 :          1 :   if ( mGeometryOptions->isActive() )
    2961                 :         78 :     mGeometryOptions->apply( geom );
    2962                 :            : 
    2963                 :          1 :   updateExtents();
    2964                 :            : 
    2965                 :          1 :   bool result = mEditBuffer->changeGeometry( fid, geom );
    2966                 :         78 : 
    2967                 :          1 :   if ( result )
    2968                 :            :   {
    2969                 :          1 :     updateExtents();
    2970                 :          1 :     if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
    2971                 :          0 :       updateDefaultValues( fid );
    2972                 :         79 :   }
    2973                 :          1 :   return result;
    2974                 :          1 : }
    2975                 :         78 : 
    2976                 :            : 
    2977                 :          0 : bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
    2978                 :         78 : {
    2979                 :          0 :   bool result = false;
    2980                 :         78 : 
    2981                 :         78 :   switch ( fields().fieldOrigin( field ) )
    2982                 :            :   {
    2983                 :            :     case QgsFields::OriginJoin:
    2984                 :          0 :       result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
    2985                 :          0 :       if ( result )
    2986                 :          0 :         emit attributeValueChanged( fid, field, newValue );
    2987                 :          0 :       break;
    2988                 :            : 
    2989                 :            :     case QgsFields::OriginProvider:
    2990                 :         78 :     case QgsFields::OriginEdit:
    2991                 :            :     case QgsFields::OriginExpression:
    2992                 :            :     {
    2993                 :          0 :       if ( mEditBuffer && mDataProvider )
    2994                 :          0 :         result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
    2995                 :          0 :       break;
    2996                 :            :     }
    2997                 :         78 : 
    2998                 :            :     case QgsFields::OriginUnknown:
    2999                 :          0 :       break;
    3000                 :            :   }
    3001                 :            : 
    3002                 :          0 :   if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
    3003                 :          0 :     updateDefaultValues( fid );
    3004                 :            : 
    3005                 :          0 :   return result;
    3006                 :          0 : }
    3007                 :            : 
    3008                 :         78 : bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
    3009                 :            : {
    3010                 :          0 :   bool result = true;
    3011                 :            : 
    3012                 :         78 :   QgsAttributeMap newValuesJoin;
    3013                 :          0 :   QgsAttributeMap oldValuesJoin;
    3014                 :            : 
    3015                 :         78 :   QgsAttributeMap newValuesNotJoin;
    3016                 :          0 :   QgsAttributeMap oldValuesNotJoin;
    3017                 :            : 
    3018                 :          0 :   for ( auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
    3019                 :            :   {
    3020                 :         78 :     const int field = it.key();
    3021                 :          0 :     const QVariant newValue = it.value();
    3022                 :          0 :     QVariant oldValue;
    3023                 :            : 
    3024                 :         78 :     if ( oldValues.contains( field ) )
    3025                 :          0 :       oldValue = oldValues[field];
    3026                 :            : 
    3027                 :          0 :     switch ( fields().fieldOrigin( field ) )
    3028                 :            :     {
    3029                 :            :       case QgsFields::OriginJoin:
    3030                 :          0 :         newValuesJoin[field] = newValue;
    3031                 :          0 :         oldValuesJoin[field] = oldValue;
    3032                 :          0 :         break;
    3033                 :            : 
    3034                 :            :       case QgsFields::OriginProvider:
    3035                 :            :       case QgsFields::OriginEdit:
    3036                 :            :       case QgsFields::OriginExpression:
    3037                 :            :       {
    3038                 :          0 :         newValuesNotJoin[field] = newValue;
    3039                 :          0 :         oldValuesNotJoin[field] = oldValue;
    3040                 :          0 :         break;
    3041                 :            :       }
    3042                 :            : 
    3043                 :            :       case QgsFields::OriginUnknown:
    3044                 :          0 :         break;
    3045                 :            :     }
    3046                 :          0 :   }
    3047                 :            : 
    3048                 :          0 :   if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
    3049                 :            :   {
    3050                 :          0 :     result = mJoinBuffer->changeAttributeValues( fid, newValuesJoin, oldValuesJoin );
    3051                 :          0 :   }
    3052                 :            : 
    3053                 :          0 :   if ( ! newValuesNotJoin.isEmpty() && mEditBuffer && mDataProvider )
    3054                 :            :   {
    3055                 :          0 :     result &= mEditBuffer->changeAttributeValues( fid, newValuesNotJoin, oldValues );
    3056                 :          0 :   }
    3057                 :            : 
    3058                 :          0 :   if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
    3059                 :            :   {
    3060                 :          0 :     updateDefaultValues( fid );
    3061                 :          0 :   }
    3062                 :            : 
    3063                 :          0 :   return result;
    3064                 :          0 : }
    3065                 :            : 
    3066                 :          0 : bool QgsVectorLayer::addAttribute( const QgsField &field )
    3067                 :            : {
    3068                 :          0 :   if ( !mEditBuffer || !mDataProvider )
    3069                 :          0 :     return false;
    3070                 :            : 
    3071                 :          0 :   return mEditBuffer->addAttribute( field );
    3072                 :          0 : }
    3073                 :            : 
    3074                 :          0 : void QgsVectorLayer::removeFieldAlias( int attIndex )
    3075                 :            : {
    3076                 :          0 :   if ( attIndex < 0 || attIndex >= fields().count() )
    3077                 :          0 :     return;
    3078                 :            : 
    3079                 :          0 :   QString name = fields().at( attIndex ).name();
    3080                 :          0 :   mFields[ attIndex ].setAlias( QString() );
    3081                 :          0 :   if ( mAttributeAliasMap.contains( name ) )
    3082                 :            :   {
    3083                 :          0 :     mAttributeAliasMap.remove( name );
    3084                 :          0 :     updateFields();
    3085                 :          0 :     mEditFormConfig.setFields( mFields );
    3086                 :          0 :     emit layerModified();
    3087                 :          0 :   }
    3088                 :          0 : }
    3089                 :            : 
    3090                 :          0 : bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
    3091                 :            : {
    3092                 :          0 :   if ( index < 0 || index >= fields().count() )
    3093                 :          0 :     return false;
    3094                 :            : 
    3095                 :          0 :   switch ( mFields.fieldOrigin( index ) )
    3096                 :            :   {
    3097                 :            :     case QgsFields::OriginExpression:
    3098                 :            :     {
    3099                 :          0 :       if ( mExpressionFieldBuffer )
    3100                 :            :       {
    3101                 :          0 :         int oi = mFields.fieldOriginIndex( index );
    3102                 :          0 :         mExpressionFieldBuffer->renameExpression( oi, newName );
    3103                 :          0 :         updateFields();
    3104                 :          0 :         return true;
    3105                 :            :       }
    3106                 :            :       else
    3107                 :            :       {
    3108                 :          0 :         return false;
    3109                 :            :       }
    3110                 :            :     }
    3111                 :            : 
    3112                 :            :     case QgsFields::OriginProvider:
    3113                 :            :     case QgsFields::OriginEdit:
    3114                 :            : 
    3115                 :          0 :       if ( !mEditBuffer || !mDataProvider )
    3116                 :          0 :         return false;
    3117                 :            : 
    3118                 :          0 :       return mEditBuffer->renameAttribute( index, newName );
    3119                 :            : 
    3120                 :            :     case QgsFields::OriginJoin:
    3121                 :            :     case QgsFields::OriginUnknown:
    3122                 :          0 :       return false;
    3123                 :            : 
    3124                 :            :   }
    3125                 :            : 
    3126                 :          0 :   return false; // avoid warning
    3127                 :          0 : }
    3128                 :            : 
    3129                 :          0 : void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
    3130                 :            : {
    3131                 :          0 :   if ( attIndex < 0 || attIndex >= fields().count() )
    3132                 :          0 :     return;
    3133                 :            : 
    3134                 :          0 :   QString name = fields().at( attIndex ).name();
    3135                 :            : 
    3136                 :          0 :   mAttributeAliasMap.insert( name, aliasString );
    3137                 :          0 :   mFields[ attIndex ].setAlias( aliasString );
    3138                 :          0 :   mEditFormConfig.setFields( mFields );
    3139                 :          0 :   emit layerModified(); // TODO[MD]: should have a different signal?
    3140                 :          0 : }
    3141                 :            : 
    3142                 :          0 : QString QgsVectorLayer::attributeAlias( int index ) const
    3143                 :            : {
    3144                 :          0 :   if ( index < 0 || index >= fields().count() )
    3145                 :          0 :     return QString();
    3146                 :            : 
    3147                 :          0 :   return fields().at( index ).alias();
    3148                 :          0 : }
    3149                 :            : 
    3150                 :          0 : QString QgsVectorLayer::attributeDisplayName( int index ) const
    3151                 :            : {
    3152                 :          0 :   if ( index >= 0 && index < mFields.count() )
    3153                 :          0 :     return mFields.at( index ).displayName();
    3154                 :            :   else
    3155                 :          0 :     return QString();
    3156                 :          0 : }
    3157                 :            : 
    3158                 :          0 : QgsStringMap QgsVectorLayer::attributeAliases() const
    3159                 :            : {
    3160                 :          0 :   return mAttributeAliasMap;
    3161                 :            : }
    3162                 :            : 
    3163                 :          0 : QSet<QString> QgsVectorLayer::excludeAttributesWms() const
    3164                 :            : {
    3165                 :          0 :   QSet<QString> excludeList;
    3166                 :          0 :   QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
    3167                 :          0 :   for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
    3168                 :            :   {
    3169                 :          0 :     if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWms ) )
    3170                 :            :     {
    3171                 :          0 :       excludeList << flagsIt.key();
    3172                 :          0 :     }
    3173                 :          0 :   }
    3174                 :          0 :   return excludeList;
    3175                 :          0 : }
    3176                 :            : 
    3177                 :          0 : void QgsVectorLayer::setExcludeAttributesWms( const QSet<QString> &att )
    3178                 :            : {
    3179                 :          0 :   QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
    3180                 :          0 :   for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
    3181                 :            :   {
    3182                 :          0 :     flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWms, att.contains( flagsIt.key() ) );
    3183                 :          0 :   }
    3184                 :          0 :   updateFields();
    3185                 :          0 : }
    3186                 :            : 
    3187                 :          0 : QSet<QString> QgsVectorLayer::excludeAttributesWfs() const
    3188                 :            : {
    3189                 :          0 :   QSet<QString> excludeList;
    3190                 :          0 :   QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
    3191                 :          0 :   for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
    3192                 :            :   {
    3193                 :          0 :     if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWfs ) )
    3194                 :            :     {
    3195                 :          0 :       excludeList << flagsIt.key();
    3196                 :          0 :     }
    3197                 :          0 :   }
    3198                 :          0 :   return excludeList;
    3199                 :          0 : }
    3200                 :            : 
    3201                 :          0 : void QgsVectorLayer::setExcludeAttributesWfs( const QSet<QString> &att )
    3202                 :            : {
    3203                 :          0 :   QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
    3204                 :          0 :   for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
    3205                 :            :   {
    3206                 :          0 :     flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWfs, att.contains( flagsIt.key() ) );
    3207                 :          0 :   }
    3208                 :          0 :   updateFields();
    3209                 :          0 : }
    3210                 :            : 
    3211                 :          0 : bool QgsVectorLayer::deleteAttribute( int index )
    3212                 :            : {
    3213                 :          0 :   if ( index < 0 || index >= fields().count() )
    3214                 :          0 :     return false;
    3215                 :            : 
    3216                 :          0 :   if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
    3217                 :            :   {
    3218                 :          0 :     removeExpressionField( index );
    3219                 :          0 :     return true;
    3220                 :            :   }
    3221                 :            : 
    3222                 :          0 :   if ( !mEditBuffer || !mDataProvider )
    3223                 :          0 :     return false;
    3224                 :            : 
    3225                 :          0 :   return mEditBuffer->deleteAttribute( index );
    3226                 :          0 : }
    3227                 :            : 
    3228                 :          0 : bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
    3229                 :            : {
    3230                 :          0 :   bool deleted = false;
    3231                 :            : 
    3232                 :            :   // Remove multiple occurrences of same attribute
    3233                 :          0 :   QList<int> attrList = qgis::setToList( qgis::listToSet( attrs ) );
    3234                 :            : 
    3235                 :          0 :   std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
    3236                 :            : 
    3237                 :          0 :   for ( int attr : std::as_const( attrList ) )
    3238                 :            :   {
    3239                 :          0 :     if ( deleteAttribute( attr ) )
    3240                 :            :     {
    3241                 :          0 :       deleted = true;
    3242                 :          0 :     }
    3243                 :            :   }
    3244                 :            : 
    3245                 :          0 :   return deleted;
    3246                 :          0 : }
    3247                 :            : 
    3248                 :          0 : bool QgsVectorLayer::deleteFeatureCascade( QgsFeatureId fid, QgsVectorLayer::DeleteContext *context )
    3249                 :            : {
    3250                 :          0 :   if ( !mEditBuffer )
    3251                 :          0 :     return false;
    3252                 :            : 
    3253                 :          0 :   if ( context && context->cascade )
    3254                 :            :   {
    3255                 :          0 :     const QList<QgsRelation> relations = context->project->relationManager()->referencedRelations( this );
    3256                 :          0 :     const bool hasRelationsOrJoins = !relations.empty() || mJoinBuffer->containsJoins();
    3257                 :          0 :     if ( hasRelationsOrJoins )
    3258                 :            :     {
    3259                 :          0 :       if ( context->mHandledFeatures.contains( this ) )
    3260                 :            :       {
    3261                 :          0 :         QgsFeatureIds &handledFeatureIds = context->mHandledFeatures[ this  ];
    3262                 :          0 :         if ( handledFeatureIds.contains( fid ) )
    3263                 :            :         {
    3264                 :            :           // avoid endless recursion
    3265                 :          0 :           return false;
    3266                 :            :         }
    3267                 :            :         else
    3268                 :            :         {
    3269                 :            :           // add feature id
    3270                 :          0 :           handledFeatureIds << fid;
    3271                 :            :         }
    3272                 :          0 :       }
    3273                 :            :       else
    3274                 :            :       {
    3275                 :            :         // add layer and feature id
    3276                 :          0 :         context->mHandledFeatures.insert( this, QgsFeatureIds() << fid );
    3277                 :            :       }
    3278                 :            : 
    3279                 :          0 :       for ( const QgsRelation &relation : relations )
    3280                 :            :       {
    3281                 :            :         //check if composition (and not association)
    3282                 :          0 :         if ( relation.strength() == QgsRelation::Composition )
    3283                 :            :         {
    3284                 :            :           //get features connected over this relation
    3285                 :          0 :           QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( getFeature( fid ) );
    3286                 :          0 :           QgsFeatureIds childFeatureIds;
    3287                 :          0 :           QgsFeature childFeature;
    3288                 :          0 :           while ( relatedFeaturesIt.nextFeature( childFeature ) )
    3289                 :            :           {
    3290                 :          0 :             childFeatureIds.insert( childFeature.id() );
    3291                 :            :           }
    3292                 :          0 :           if ( childFeatureIds.count() > 0 )
    3293                 :            :           {
    3294                 :          0 :             relation.referencingLayer()->startEditing();
    3295                 :          0 :             relation.referencingLayer()->deleteFeatures( childFeatureIds, context );
    3296                 :          0 :           }
    3297                 :          0 :         }
    3298                 :            :       }
    3299                 :          0 :     }
    3300                 :          0 :   }
    3301                 :            : 
    3302                 :          0 :   if ( mJoinBuffer->containsJoins() )
    3303                 :          0 :     mJoinBuffer->deleteFeature( fid, context );
    3304                 :            : 
    3305                 :          0 :   bool res = mEditBuffer->deleteFeature( fid );
    3306                 :            : 
    3307                 :          0 :   return res;
    3308                 :          0 : }
    3309                 :            : 
    3310                 :          0 : bool QgsVectorLayer::deleteFeature( QgsFeatureId fid, QgsVectorLayer::DeleteContext *context )
    3311                 :            : {
    3312                 :          0 :   if ( !mEditBuffer )
    3313                 :          0 :     return false;
    3314                 :            : 
    3315                 :          0 :   bool res = deleteFeatureCascade( fid, context );
    3316                 :            : 
    3317                 :          0 :   if ( res )
    3318                 :            :   {
    3319                 :          0 :     mSelectedFeatureIds.remove( fid ); // remove it from selection
    3320                 :          0 :     updateExtents();
    3321                 :          0 :   }
    3322                 :            : 
    3323                 :          0 :   return res;
    3324                 :          0 : }
    3325                 :            : 
    3326                 :          0 : bool QgsVectorLayer::deleteFeatures( const QgsFeatureIds &fids, QgsVectorLayer::DeleteContext *context )
    3327                 :            : {
    3328                 :          0 :   bool res = true;
    3329                 :          0 :   const auto constFids = fids;
    3330                 :          0 :   for ( QgsFeatureId fid : constFids )
    3331                 :          0 :     res = deleteFeatureCascade( fid, context ) && res;
    3332                 :            : 
    3333                 :          0 :   if ( res )
    3334                 :            :   {
    3335                 :          0 :     mSelectedFeatureIds.subtract( fids ); // remove it from selection
    3336                 :          0 :     updateExtents();
    3337                 :          0 :   }
    3338                 :            : 
    3339                 :          0 :   return res;
    3340                 :          0 : }
    3341                 :            : 
    3342                 :        401 : QgsFields QgsVectorLayer::fields() const
    3343                 :            : {
    3344                 :        401 :   return mFields;
    3345                 :            : }
    3346                 :            : 
    3347                 :          0 : QgsAttributeList QgsVectorLayer::primaryKeyAttributes() const
    3348                 :            : {
    3349                 :          0 :   QgsAttributeList pkAttributesList;
    3350                 :          0 :   if ( !mDataProvider )
    3351                 :          0 :     return pkAttributesList;
    3352                 :            : 
    3353                 :          0 :   QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
    3354                 :          0 :   for ( int i = 0; i < mFields.count(); ++i )
    3355                 :            :   {
    3356                 :          0 :     if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
    3357                 :          0 :          providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
    3358                 :          0 :       pkAttributesList << i;
    3359                 :          0 :   }
    3360                 :            : 
    3361                 :          0 :   return pkAttributesList;
    3362                 :          0 : }
    3363                 :            : 
    3364                 :          2 : long QgsVectorLayer::featureCount() const
    3365                 :            : {
    3366                 :          2 :   if ( ! mDataProvider )
    3367                 :          0 :     return -1;
    3368                 :          4 :   return mDataProvider->featureCount() +
    3369                 :          2 :          ( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures().size() - mEditBuffer->deletedFeatureIds().size() : 0 );
    3370                 :          2 : }
    3371                 :            : 
    3372                 :          0 : QgsFeatureSource::FeatureAvailability QgsVectorLayer::hasFeatures() const
    3373                 :            : {
    3374                 :          0 :   const QgsFeatureIds deletedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->deletedFeatureIds() : QgsFeatureIds() );
    3375                 :          0 :   const QgsFeatureMap addedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures() : QgsFeatureMap() );
    3376                 :            : 
    3377                 :          0 :   if ( mEditBuffer && !deletedFeatures.empty() )
    3378                 :            :   {
    3379                 :          0 :     if ( addedFeatures.size() > deletedFeatures.size() )
    3380                 :          0 :       return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
    3381                 :            :     else
    3382                 :          0 :       return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
    3383                 :            :   }
    3384                 :            : 
    3385                 :          0 :   if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider && mDataProvider->empty() )
    3386                 :          0 :     return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
    3387                 :            :   else
    3388                 :          0 :     return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
    3389                 :          0 : }
    3390                 :            : 
    3391                 :          0 : bool QgsVectorLayer::commitChanges( bool stopEditing )
    3392                 :            : {
    3393                 :          0 :   mCommitErrors.clear();
    3394                 :            : 
    3395                 :          0 :   if ( !mDataProvider )
    3396                 :            :   {
    3397                 :          0 :     mCommitErrors << tr( "ERROR: no provider" );
    3398                 :          0 :     return false;
    3399                 :            :   }
    3400                 :            : 
    3401                 :          0 :   if ( !mEditBuffer )
    3402                 :            :   {
    3403                 :          0 :     mCommitErrors << tr( "ERROR: layer not editable" );
    3404                 :          0 :     return false;
    3405                 :            :   }
    3406                 :            : 
    3407                 :          0 :   emit beforeCommitChanges( stopEditing );
    3408                 :            : 
    3409                 :          0 :   if ( !mAllowCommit )
    3410                 :          0 :     return false;
    3411                 :            : 
    3412                 :          0 :   bool success = mEditBuffer->commitChanges( mCommitErrors );
    3413                 :            : 
    3414                 :          0 :   if ( success )
    3415                 :            :   {
    3416                 :          0 :     if ( stopEditing )
    3417                 :            :     {
    3418                 :          0 :       delete mEditBuffer;
    3419                 :          0 :       mEditBuffer = nullptr;
    3420                 :          0 :     }
    3421                 :          0 :     undoStack()->clear();
    3422                 :          0 :     emit afterCommitChanges();
    3423                 :          0 :     if ( stopEditing )
    3424                 :          0 :       emit editingStopped();
    3425                 :          0 :   }
    3426                 :            :   else
    3427                 :            :   {
    3428                 :          0 :     QgsMessageLog::logMessage( tr( "Commit errors:\n  %1" ).arg( mCommitErrors.join( QLatin1String( "\n  " ) ) ) );
    3429                 :            :   }
    3430                 :            : 
    3431                 :          0 :   updateFields();
    3432                 :          0 :   mDataProvider->updateExtents();
    3433                 :            : 
    3434                 :          0 :   mDataProvider->leaveUpdateMode();
    3435                 :            : 
    3436                 :          0 :   triggerRepaint();
    3437                 :            : 
    3438                 :          0 :   return success;
    3439                 :          0 : }
    3440                 :            : 
    3441                 :          0 : QStringList QgsVectorLayer::commitErrors() const
    3442                 :            : {
    3443                 :          0 :   return mCommitErrors;
    3444                 :            : }
    3445                 :            : 
    3446                 :          0 : bool QgsVectorLayer::rollBack( bool deleteBuffer )
    3447                 :            : {
    3448                 :          0 :   if ( !mEditBuffer )
    3449                 :            :   {
    3450                 :          0 :     return false;
    3451                 :            :   }
    3452                 :            : 
    3453                 :          0 :   if ( !mDataProvider )
    3454                 :            :   {
    3455                 :          0 :     mCommitErrors << tr( "ERROR: no provider" );
    3456                 :          0 :     return false;
    3457                 :            :   }
    3458                 :            : 
    3459                 :          0 :   bool rollbackExtent = !mDataProvider->transaction() && ( !mEditBuffer->deletedFeatureIds().isEmpty() ||
    3460                 :          0 :                         !mEditBuffer->addedFeatures().isEmpty() ||
    3461                 :          0 :                         !mEditBuffer->changedGeometries().isEmpty() );
    3462                 :            : 
    3463                 :          0 :   emit beforeRollBack();
    3464                 :            : 
    3465                 :          0 :   mEditBuffer->rollBack();
    3466                 :            : 
    3467                 :          0 :   emit afterRollBack();
    3468                 :            : 
    3469                 :          0 :   if ( isModified() )
    3470                 :            :   {
    3471                 :            :     // new undo stack roll back method
    3472                 :            :     // old method of calling every undo could cause many canvas refreshes
    3473                 :          0 :     undoStack()->setIndex( 0 );
    3474                 :          0 :   }
    3475                 :            : 
    3476                 :          0 :   updateFields();
    3477                 :            : 
    3478                 :          0 :   if ( deleteBuffer )
    3479                 :            :   {
    3480                 :          0 :     delete mEditBuffer;
    3481                 :          0 :     mEditBuffer = nullptr;
    3482                 :          0 :     undoStack()->clear();
    3483                 :          0 :   }
    3484                 :          0 :   emit editingStopped();
    3485                 :            : 
    3486                 :          0 :   if ( rollbackExtent )
    3487                 :          0 :     updateExtents();
    3488                 :            : 
    3489                 :          0 :   mDataProvider->leaveUpdateMode();
    3490                 :            : 
    3491                 :          0 :   triggerRepaint();
    3492                 :          0 :   return true;
    3493                 :          0 : }
    3494                 :            : 
    3495                 :          0 : int QgsVectorLayer::selectedFeatureCount() const
    3496                 :            : {
    3497                 :          0 :   return mSelectedFeatureIds.size();
    3498                 :            : }
    3499                 :            : 
    3500                 :          0 : const QgsFeatureIds &QgsVectorLayer::selectedFeatureIds() const
    3501                 :            : {
    3502                 :          0 :   return mSelectedFeatureIds;
    3503                 :            : }
    3504                 :            : 
    3505                 :          0 : QgsFeatureList QgsVectorLayer::selectedFeatures() const
    3506                 :            : {
    3507                 :          0 :   QgsFeatureList features;
    3508                 :          0 :   features.reserve( mSelectedFeatureIds.count() );
    3509                 :          0 :   QgsFeature f;
    3510                 :            : 
    3511                 :          0 :   if ( mSelectedFeatureIds.count() <= 8 )
    3512                 :            :   {
    3513                 :            :     // for small amount of selected features, fetch them directly
    3514                 :            :     // because request with FilterFids would go iterate over the whole layer
    3515                 :          0 :     const auto constMSelectedFeatureIds = mSelectedFeatureIds;
    3516                 :          0 :     for ( QgsFeatureId fid : constMSelectedFeatureIds )
    3517                 :            :     {
    3518                 :          0 :       getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
    3519                 :          0 :       features << f;
    3520                 :            :     }
    3521                 :          0 :   }
    3522                 :            :   else
    3523                 :            :   {
    3524                 :          0 :     QgsFeatureIterator it = getSelectedFeatures();
    3525                 :            : 
    3526                 :          0 :     while ( it.nextFeature( f ) )
    3527                 :            :     {
    3528                 :          0 :       features.push_back( f );
    3529                 :            :     }
    3530                 :          0 :   }
    3531                 :            : 
    3532                 :          0 :   return features;
    3533                 :          0 : }
    3534                 :            : 
    3535                 :          0 : QgsFeatureIterator QgsVectorLayer::getSelectedFeatures( QgsFeatureRequest request ) const
    3536                 :            : {
    3537                 :          0 :   if ( mSelectedFeatureIds.isEmpty() )
    3538                 :          0 :     return QgsFeatureIterator();
    3539                 :            : 
    3540                 :          0 :   if ( geometryType() == QgsWkbTypes::NullGeometry )
    3541                 :          0 :     request.setFlags( QgsFeatureRequest::NoGeometry );
    3542                 :            : 
    3543                 :          0 :   if ( mSelectedFeatureIds.count() == 1 )
    3544                 :          0 :     request.setFilterFid( *mSelectedFeatureIds.constBegin() );
    3545                 :            :   else
    3546                 :          0 :     request.setFilterFids( mSelectedFeatureIds );
    3547                 :            : 
    3548                 :          0 :   return getFeatures( request );
    3549                 :          0 : }
    3550                 :            : 
    3551                 :          1 : bool QgsVectorLayer::addFeatures( QgsFeatureList &features, Flags )
    3552                 :            : {
    3553                 :          1 :   if ( !mEditBuffer || !mDataProvider )
    3554                 :          0 :     return false;
    3555                 :            : 
    3556                 :          1 :   if ( mGeometryOptions->isActive() )
    3557                 :            :   {
    3558                 :          0 :     for ( auto feature = features.begin(); feature != features.end(); ++feature )
    3559                 :            :     {
    3560                 :          0 :       QgsGeometry geom = feature->geometry();
    3561                 :          0 :       mGeometryOptions->apply( geom );
    3562                 :          0 :       feature->setGeometry( geom );
    3563                 :          0 :     }
    3564                 :          0 :   }
    3565                 :            : 
    3566                 :          1 :   bool res = mEditBuffer->addFeatures( features );
    3567                 :          1 :   updateExtents();
    3568                 :            : 
    3569                 :          1 :   if ( res && mJoinBuffer->containsJoins() )
    3570                 :          0 :     res = mJoinBuffer->addFeatures( features );
    3571                 :            : 
    3572                 :          1 :   return res;
    3573                 :          1 : }
    3574                 :            : 
    3575                 :         78 : void QgsVectorLayer::setCoordinateSystem()
    3576                 :            : {
    3577                 :            :   // if layer is not spatial, it has not CRS!
    3578                 :         78 :   setCrs( ( isSpatial() && mDataProvider ) ? mDataProvider->crs() : QgsCoordinateReferenceSystem() );
    3579                 :         78 : }
    3580                 :            : 
    3581                 :          0 : QString QgsVectorLayer::displayField() const
    3582                 :            : {
    3583                 :          0 :   QgsExpression exp( displayExpression() );
    3584                 :          0 :   if ( exp.isField() )
    3585                 :            :   {
    3586                 :          0 :     return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
    3587                 :            :   }
    3588                 :            : 
    3589                 :          0 :   return QString();
    3590                 :          0 : }
    3591                 :            : 
    3592                 :          0 : void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
    3593                 :            : {
    3594                 :          0 :   if ( mDisplayExpression == displayExpression )
    3595                 :          0 :     return;
    3596                 :            : 
    3597                 :          0 :   mDisplayExpression = displayExpression;
    3598                 :          0 :   emit displayExpressionChanged();
    3599                 :          0 : }
    3600                 :            : 
    3601                 :          0 : QString QgsVectorLayer::displayExpression() const
    3602                 :            : {
    3603                 :          0 :   if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
    3604                 :            :   {
    3605                 :          0 :     return mDisplayExpression;
    3606                 :            :   }
    3607                 :            :   else
    3608                 :            :   {
    3609                 :          0 :     const QString candidateName = QgsVectorLayerUtils::guessFriendlyIdentifierField( mFields );
    3610                 :          0 :     if ( !candidateName.isEmpty() )
    3611                 :            :     {
    3612                 :          0 :       return QgsExpression::quotedColumnRef( candidateName );
    3613                 :            :     }
    3614                 :            :     else
    3615                 :            :     {
    3616                 :          0 :       return QString();
    3617                 :            :     }
    3618                 :          0 :   }
    3619                 :          0 : }
    3620                 :            : 
    3621                 :          1 : bool QgsVectorLayer::isEditable() const
    3622                 :            : {
    3623                 :          1 :   return ( mEditBuffer && mDataProvider );
    3624                 :            : }
    3625                 :            : 
    3626                 :        558 : bool QgsVectorLayer::isSpatial() const
    3627                 :            : {
    3628                 :        558 :   QgsWkbTypes::GeometryType t = geometryType();
    3629                 :        558 :   return t != QgsWkbTypes::NullGeometry && t != QgsWkbTypes::UnknownGeometry;
    3630                 :            : }
    3631                 :            : 
    3632                 :          0 : bool QgsVectorLayer::isReadOnly() const
    3633                 :            : {
    3634                 :          0 :   return mReadOnly;
    3635                 :            : }
    3636                 :            : 
    3637                 :          0 : bool QgsVectorLayer::setReadOnly( bool readonly )
    3638                 :            : {
    3639                 :            :   // exit if the layer is in editing mode
    3640                 :          0 :   if ( readonly && mEditBuffer )
    3641                 :          0 :     return false;
    3642                 :            : 
    3643                 :          0 :   mReadOnly = readonly;
    3644                 :          0 :   emit readOnlyChanged();
    3645                 :          0 :   return true;
    3646                 :          0 : }
    3647                 :            : 
    3648                 :          2 : bool QgsVectorLayer::supportsEditing()
    3649                 :            : {
    3650                 :          2 :   if ( ! mDataProvider )
    3651                 :          0 :     return false;
    3652                 :            : 
    3653                 :          2 :   return mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities && ! mReadOnly;
    3654                 :          2 : }
    3655                 :            : 
    3656                 :          0 : bool QgsVectorLayer::isModified() const
    3657                 :            : {
    3658                 :          0 :   emit beforeModifiedCheck();
    3659                 :          0 :   return mEditBuffer && mEditBuffer->isModified();
    3660                 :            : }
    3661                 :            : 
    3662                 :          0 : bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
    3663                 :            : {
    3664                 :          0 :   bool auxiliaryField = false;
    3665                 :          0 :   srcIndex = -1;
    3666                 :            : 
    3667                 :          0 :   if ( !auxiliaryLayer() )
    3668                 :          0 :     return auxiliaryField;
    3669                 :            : 
    3670                 :          0 :   if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
    3671                 :            :   {
    3672                 :          0 :     const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
    3673                 :            : 
    3674                 :          0 :     if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
    3675                 :          0 :       auxiliaryField = true;
    3676                 :          0 :   }
    3677                 :            : 
    3678                 :          0 :   return auxiliaryField;
    3679                 :          0 : }
    3680                 :            : 
    3681                 :         78 : void QgsVectorLayer::setRenderer( QgsFeatureRenderer *r )
    3682                 :            : {
    3683                 :            :   // we must allow setting a renderer if our geometry type is unknown
    3684                 :            :   // as this allows the renderer to be correctly set even for layers
    3685                 :            :   // with broken sources
    3686                 :         78 :   if ( !isSpatial() && mWkbType != QgsWkbTypes::Unknown )
    3687                 :          0 :     return;
    3688                 :            : 
    3689                 :         78 :   if ( r != mRenderer )
    3690                 :            :   {
    3691                 :         78 :     delete mRenderer;
    3692                 :         78 :     mRenderer = r;
    3693                 :         78 :     mSymbolFeatureCounted = false;
    3694                 :         78 :     mSymbolFeatureCountMap.clear();
    3695                 :         78 :     mSymbolFeatureIdMap.clear();
    3696                 :            : 
    3697                 :         78 :     emit rendererChanged();
    3698                 :         78 :     emit styleChanged();
    3699                 :         78 :   }
    3700                 :         78 : }
    3701                 :            : 
    3702                 :          0 : void QgsVectorLayer::addFeatureRendererGenerator( QgsFeatureRendererGenerator *generator )
    3703                 :            : {
    3704                 :          0 :   mRendererGenerators << generator;
    3705                 :          0 : }
    3706                 :            : 
    3707                 :          0 : void QgsVectorLayer::removeFeatureRendererGenerator( const QString &id )
    3708                 :            : {
    3709                 :          0 :   for ( int i = mRendererGenerators.count() - 1; i >= 0; --i )
    3710                 :            :   {
    3711                 :          0 :     if ( mRendererGenerators.at( i )->id() == id )
    3712                 :            :     {
    3713                 :          0 :       delete mRendererGenerators.at( i );
    3714                 :          0 :       mRendererGenerators.removeAt( i );
    3715                 :          0 :     }
    3716                 :          0 :   }
    3717                 :          0 : }
    3718                 :            : 
    3719                 :          0 : QList<const QgsFeatureRendererGenerator *> QgsVectorLayer::featureRendererGenerators() const
    3720                 :            : {
    3721                 :          0 :   QList< const QgsFeatureRendererGenerator * > res;
    3722                 :          0 :   for ( const QgsFeatureRendererGenerator *generator : mRendererGenerators )
    3723                 :          0 :     res << generator;
    3724                 :          0 :   return res;
    3725                 :          0 : }
    3726                 :            : 
    3727                 :          0 : void QgsVectorLayer::beginEditCommand( const QString &text )
    3728                 :            : {
    3729                 :          0 :   if ( !mDataProvider )
    3730                 :            :   {
    3731                 :          0 :     return;
    3732                 :            :   }
    3733                 :          0 :   if ( mDataProvider->transaction() )
    3734                 :            :   {
    3735                 :          0 :     QString ignoredError;
    3736                 :          0 :     mDataProvider->transaction()->createSavepoint( ignoredError );
    3737                 :          0 :   }
    3738                 :          0 :   undoStack()->beginMacro( text );
    3739                 :          0 :   mEditCommandActive = true;
    3740                 :          0 :   emit editCommandStarted( text );
    3741                 :          0 : }
    3742                 :            : 
    3743                 :          0 : void QgsVectorLayer::endEditCommand()
    3744                 :            : {
    3745                 :          0 :   if ( !mDataProvider )
    3746                 :            :   {
    3747                 :          0 :     return;
    3748                 :            :   }
    3749                 :          0 :   undoStack()->endMacro();
    3750                 :          0 :   mEditCommandActive = false;
    3751                 :          0 :   if ( !mDeletedFids.isEmpty() )
    3752                 :            :   {
    3753                 :          0 :     emit featuresDeleted( mDeletedFids );
    3754                 :          0 :     mDeletedFids.clear();
    3755                 :          0 :   }
    3756                 :          0 :   emit editCommandEnded();
    3757                 :          0 : }
    3758                 :            : 
    3759                 :          0 : void QgsVectorLayer::destroyEditCommand()
    3760                 :            : {
    3761                 :          0 :   if ( !mDataProvider )
    3762                 :            :   {
    3763                 :          0 :     return;
    3764                 :            :   }
    3765                 :          0 :   undoStack()->endMacro();
    3766                 :          0 :   undoStack()->undo();
    3767                 :            : 
    3768                 :            :   // it's not directly possible to pop the last command off the stack (the destroyed one)
    3769                 :            :   // and delete, so we add a dummy obsolete command to force this to occur.
    3770                 :            :   // Pushing the new command deletes the destroyed one, and since the new
    3771                 :            :   // command is obsolete it's automatically deleted by the undo stack.
    3772                 :          0 :   std::unique_ptr< QUndoCommand > command = std::make_unique< QUndoCommand >();
    3773                 :          0 :   command->setObsolete( true );
    3774                 :          0 :   undoStack()->push( command.release() );
    3775                 :            : 
    3776                 :          0 :   mEditCommandActive = false;
    3777                 :          0 :   mDeletedFids.clear();
    3778                 :          0 :   emit editCommandDestroyed();
    3779                 :          0 : }
    3780                 :            : 
    3781                 :          0 : bool QgsVectorLayer::addJoin( const QgsVectorLayerJoinInfo &joinInfo )
    3782                 :            : {
    3783                 :          0 :   return mJoinBuffer->addJoin( joinInfo );
    3784                 :            : }
    3785                 :            : 
    3786                 :            : 
    3787                 :          0 : bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
    3788                 :            : {
    3789                 :          0 :   return mJoinBuffer->removeJoin( joinLayerId );
    3790                 :            : }
    3791                 :            : 
    3792                 :          0 : const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
    3793                 :            : {
    3794                 :          0 :   return mJoinBuffer->vectorJoins();
    3795                 :            : }
    3796                 :            : 
    3797                 :          0 : int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
    3798                 :            : {
    3799                 :          0 :   emit beforeAddingExpressionField( fld.name() );
    3800                 :          0 :   mExpressionFieldBuffer->addExpression( exp, fld );
    3801                 :          0 :   updateFields();
    3802                 :          0 :   int idx = mFields.indexFromName( fld.name() );
    3803                 :          0 :   emit attributeAdded( idx );
    3804                 :          0 :   return idx;
    3805                 :          0 : }
    3806                 :            : 
    3807                 :          0 : void QgsVectorLayer::removeExpressionField( int index )
    3808                 :            : {
    3809                 :          0 :   emit beforeRemovingExpressionField( index );
    3810                 :          0 :   int oi = mFields.fieldOriginIndex( index );
    3811                 :          0 :   mExpressionFieldBuffer->removeExpression( oi );
    3812                 :          0 :   updateFields();
    3813                 :          0 :   emit attributeDeleted( index );
    3814                 :          0 : }
    3815                 :            : 
    3816                 :          0 : QString QgsVectorLayer::expressionField( int index ) const
    3817                 :            : {
    3818                 :          0 :   int oi = mFields.fieldOriginIndex( index );
    3819                 :          0 :   if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
    3820                 :          0 :     return QString();
    3821                 :            : 
    3822                 :          0 :   return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
    3823                 :          0 : }
    3824                 :            : 
    3825                 :          0 : void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
    3826                 :            : {
    3827                 :          0 :   int oi = mFields.fieldOriginIndex( index );
    3828                 :          0 :   mExpressionFieldBuffer->updateExpression( oi, exp );
    3829                 :          0 : }
    3830                 :            : 
    3831                 :         79 : void QgsVectorLayer::updateFields()
    3832                 :            : {
    3833                 :         79 :   if ( !mDataProvider )
    3834                 :          0 :     return;
    3835                 :            : 
    3836                 :         79 :   QgsFields oldFields = mFields;
    3837                 :            : 
    3838                 :         79 :   mFields = mDataProvider->fields();
    3839                 :            : 
    3840                 :            :   // added / removed fields
    3841                 :         79 :   if ( mEditBuffer )
    3842                 :          1 :     mEditBuffer->updateFields( mFields );
    3843                 :            : 
    3844                 :            :   // joined fields
    3845                 :         79 :   if ( mJoinBuffer->containsJoins() )
    3846                 :          0 :     mJoinBuffer->updateFields( mFields );
    3847                 :            : 
    3848                 :         79 :   if ( mExpressionFieldBuffer )
    3849                 :         79 :     mExpressionFieldBuffer->updateFields( mFields );
    3850                 :            : 
    3851                 :            :   // set aliases and default values
    3852                 :         79 :   QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
    3853                 :         79 :   for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
    3854                 :            :   {
    3855                 :          0 :     int index = mFields.lookupField( aliasIt.key() );
    3856                 :          0 :     if ( index < 0 )
    3857                 :          0 :       continue;
    3858                 :            : 
    3859                 :          0 :     mFields[ index ].setAlias( aliasIt.value() );
    3860                 :          0 :   }
    3861                 :            : 
    3862                 :            :   // Update configuration flags
    3863                 :         79 :   QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
    3864                 :         79 :   for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
    3865                 :            :   {
    3866                 :          0 :     int index = mFields.lookupField( flagsIt.key() );
    3867                 :          0 :     if ( index < 0 )
    3868                 :          0 :       continue;
    3869                 :            : 
    3870                 :          0 :     mFields[index].setConfigurationFlags( flagsIt.value() );
    3871                 :          0 :   }
    3872                 :            : 
    3873                 :            :   // Update default values
    3874                 :         79 :   mDefaultValueOnUpdateFields.clear();
    3875                 :         79 :   QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
    3876                 :         79 :   for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
    3877                 :            :   {
    3878                 :          0 :     int index = mFields.lookupField( defaultIt.key() );
    3879                 :          0 :     if ( index < 0 )
    3880                 :          0 :       continue;
    3881                 :            : 
    3882                 :          0 :     mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
    3883                 :          0 :     if ( defaultIt.value().applyOnUpdate() )
    3884                 :          0 :       mDefaultValueOnUpdateFields.insert( index );
    3885                 :          0 :   }
    3886                 :            : 
    3887                 :         79 :   QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
    3888                 :         79 :   for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
    3889                 :            :   {
    3890                 :          0 :     int index = mFields.lookupField( constraintIt.key() );
    3891                 :          0 :     if ( index < 0 )
    3892                 :          0 :       continue;
    3893                 :            : 
    3894                 :          0 :     QgsFieldConstraints constraints = mFields.at( index ).constraints();
    3895                 :            : 
    3896                 :            :     // always keep provider constraints intact
    3897                 :          0 :     if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
    3898                 :          0 :       constraints.setConstraint( QgsFieldConstraints::ConstraintNotNull, QgsFieldConstraints::ConstraintOriginLayer );
    3899                 :          0 :     if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
    3900                 :          0 :       constraints.setConstraint( QgsFieldConstraints::ConstraintUnique, QgsFieldConstraints::ConstraintOriginLayer );
    3901                 :          0 :     if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
    3902                 :          0 :       constraints.setConstraint( QgsFieldConstraints::ConstraintExpression, QgsFieldConstraints::ConstraintOriginLayer );
    3903                 :          0 :     mFields[ index ].setConstraints( constraints );
    3904                 :          0 :   }
    3905                 :            : 
    3906                 :         79 :   QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
    3907                 :         79 :   for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
    3908                 :            :   {
    3909                 :          0 :     int index = mFields.lookupField( constraintExpIt.key() );
    3910                 :          0 :     if ( index < 0 )
    3911                 :          0 :       continue;
    3912                 :            : 
    3913                 :          0 :     QgsFieldConstraints constraints = mFields.at( index ).constraints();
    3914                 :            : 
    3915                 :            :     // always keep provider constraints intact
    3916                 :          0 :     if ( constraints.constraintOrigin( QgsFieldConstraints::ConstraintExpression ) == QgsFieldConstraints::ConstraintOriginProvider )
    3917                 :          0 :       continue;
    3918                 :            : 
    3919                 :          0 :     constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
    3920                 :          0 :     mFields[ index ].setConstraints( constraints );
    3921                 :          0 :   }
    3922                 :            : 
    3923                 :         79 :   QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
    3924                 :         79 :   for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
    3925                 :            :   {
    3926                 :          0 :     int index = mFields.lookupField( constraintStrengthIt.key().first );
    3927                 :          0 :     if ( index < 0 )
    3928                 :          0 :       continue;
    3929                 :            : 
    3930                 :          0 :     QgsFieldConstraints constraints = mFields.at( index ).constraints();
    3931                 :            : 
    3932                 :            :     // always keep provider constraints intact
    3933                 :          0 :     if ( constraints.constraintOrigin( QgsFieldConstraints::ConstraintExpression ) == QgsFieldConstraints::ConstraintOriginProvider )
    3934                 :          0 :       continue;
    3935                 :            : 
    3936                 :          0 :     constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
    3937                 :          0 :     mFields[ index ].setConstraints( constraints );
    3938                 :          0 :   }
    3939                 :            : 
    3940                 :         79 :   auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
    3941                 :         79 :   for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
    3942                 :            :   {
    3943                 :          0 :     int index = mFields.indexOf( fieldWidgetIterator.key() );
    3944                 :          0 :     if ( index < 0 )
    3945                 :          0 :       continue;
    3946                 :            : 
    3947                 :          0 :     mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
    3948                 :          0 :   }
    3949                 :            : 
    3950                 :         79 :   if ( oldFields != mFields )
    3951                 :            :   {
    3952                 :         64 :     emit updatedFields();
    3953                 :         64 :     mEditFormConfig.setFields( mFields );
    3954                 :         64 :   }
    3955                 :         79 : }
    3956                 :            : 
    3957                 :            : 
    3958                 :          0 : QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
    3959                 :            : {
    3960                 :          0 :   if ( index < 0 || index >= mFields.count() || !mDataProvider )
    3961                 :          0 :     return QVariant();
    3962                 :            : 
    3963                 :          0 :   QString expression = mFields.at( index ).defaultValueDefinition().expression();
    3964                 :          0 :   if ( expression.isEmpty() )
    3965                 :          0 :     return mDataProvider->defaultValue( index );
    3966                 :            : 
    3967                 :          0 :   QgsExpressionContext *evalContext = context;
    3968                 :          0 :   std::unique_ptr< QgsExpressionContext > tempContext;
    3969                 :          0 :   if ( !evalContext )
    3970                 :            :   {
    3971                 :            :     // no context passed, so we create a default one
    3972                 :          0 :     tempContext.reset( new QgsExpressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( this ) ) );
    3973                 :          0 :     evalContext = tempContext.get();
    3974                 :          0 :   }
    3975                 :            : 
    3976                 :          0 :   if ( feature.isValid() )
    3977                 :            :   {
    3978                 :          0 :     QgsExpressionContextScope *featScope = new QgsExpressionContextScope();
    3979                 :          0 :     featScope->setFeature( feature );
    3980                 :          0 :     featScope->setFields( feature.fields() );
    3981                 :          0 :     evalContext->appendScope( featScope );
    3982                 :          0 :   }
    3983                 :            : 
    3984                 :          0 :   QVariant val;
    3985                 :          0 :   QgsExpression exp( expression );
    3986                 :          0 :   exp.prepare( evalContext );
    3987                 :          0 :   if ( exp.hasEvalError() )
    3988                 :            :   {
    3989                 :          0 :     QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
    3990                 :          0 :   }
    3991                 :            :   else
    3992                 :            :   {
    3993                 :          0 :     val = exp.evaluate( evalContext );
    3994                 :            :   }
    3995                 :            : 
    3996                 :          0 :   if ( feature.isValid() )
    3997                 :            :   {
    3998                 :          0 :     delete evalContext->popScope();
    3999                 :          0 :   }
    4000                 :            : 
    4001                 :          0 :   return val;
    4002                 :          0 : }
    4003                 :            : 
    4004                 :          0 : void QgsVectorLayer::setDefaultValueDefinition( int index, const QgsDefaultValue &definition )
    4005                 :            : {
    4006                 :          0 :   if ( index < 0 || index >= mFields.count() )
    4007                 :          0 :     return;
    4008                 :            : 
    4009                 :          0 :   if ( definition.isValid() )
    4010                 :            :   {
    4011                 :          0 :     mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
    4012                 :          0 :   }
    4013                 :            :   else
    4014                 :            :   {
    4015                 :          0 :     mDefaultExpressionMap.remove( mFields.at( index ).name() );
    4016                 :            :   }
    4017                 :          0 :   updateFields();
    4018                 :          0 : }
    4019                 :            : 
    4020                 :          0 : QgsDefaultValue QgsVectorLayer::defaultValueDefinition( int index ) const
    4021                 :            : {
    4022                 :          0 :   if ( index < 0 || index >= mFields.count() )
    4023                 :          0 :     return QgsDefaultValue();
    4024                 :            :   else
    4025                 :          0 :     return mFields.at( index ).defaultValueDefinition();
    4026                 :          0 : }
    4027                 :            : 
    4028                 :          0 : QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
    4029                 :            : {
    4030                 :          0 :   QSet<QVariant> uniqueValues;
    4031                 :          0 :   if ( !mDataProvider )
    4032                 :            :   {
    4033                 :          0 :     return uniqueValues;
    4034                 :            :   }
    4035                 :            : 
    4036                 :          0 :   QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
    4037                 :          0 :   switch ( origin )
    4038                 :            :   {
    4039                 :            :     case QgsFields::OriginUnknown:
    4040                 :          0 :       return uniqueValues;
    4041                 :            : 
    4042                 :            :     case QgsFields::OriginProvider: //a provider field
    4043                 :            :     {
    4044                 :          0 :       uniqueValues = mDataProvider->uniqueValues( index, limit );
    4045                 :            : 
    4046                 :          0 :       if ( mEditBuffer && ! mDataProvider->transaction() )
    4047                 :            :       {
    4048                 :          0 :         QSet<QString> vals;
    4049                 :          0 :         const auto constUniqueValues = uniqueValues;
    4050                 :          0 :         for ( const QVariant &v : constUniqueValues )
    4051                 :            :         {
    4052                 :          0 :           vals << v.toString();
    4053                 :            :         }
    4054                 :            : 
    4055                 :          0 :         QgsFeatureMap added = mEditBuffer->addedFeatures();
    4056                 :          0 :         QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
    4057                 :          0 :         while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
    4058                 :            :         {
    4059                 :          0 :           addedIt.next();
    4060                 :          0 :           QVariant v = addedIt.value().attribute( index );
    4061                 :          0 :           if ( v.isValid() )
    4062                 :            :           {
    4063                 :          0 :             QString vs = v.toString();
    4064                 :          0 :             if ( !vals.contains( vs ) )
    4065                 :            :             {
    4066                 :          0 :               vals << vs;
    4067                 :          0 :               uniqueValues << v;
    4068                 :          0 :             }
    4069                 :          0 :           }
    4070                 :          0 :         }
    4071                 :            : 
    4072                 :          0 :         QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
    4073                 :          0 :         while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
    4074                 :            :         {
    4075                 :          0 :           it.next();
    4076                 :          0 :           QVariant v = it.value().value( index );
    4077                 :          0 :           if ( v.isValid() )
    4078                 :            :           {
    4079                 :          0 :             QString vs = v.toString();
    4080                 :          0 :             if ( !vals.contains( vs ) )
    4081                 :            :             {
    4082                 :          0 :               vals << vs;
    4083                 :          0 :               uniqueValues << v;
    4084                 :          0 :             }
    4085                 :          0 :           }
    4086                 :          0 :         }
    4087                 :          0 :       }
    4088                 :            : 
    4089                 :          0 :       return uniqueValues;
    4090                 :            :     }
    4091                 :            : 
    4092                 :            :     case QgsFields::OriginEdit:
    4093                 :            :       // the layer is editable, but in certain cases it can still be avoided going through all features
    4094                 :          0 :       if ( mDataProvider->transaction() || (
    4095                 :          0 :              mEditBuffer->deletedFeatureIds().isEmpty() &&
    4096                 :          0 :              mEditBuffer->addedFeatures().isEmpty() &&
    4097                 :          0 :              !mEditBuffer->deletedAttributeIds().contains( index ) &&
    4098                 :          0 :              mEditBuffer->changedAttributeValues().isEmpty() ) )
    4099                 :            :       {
    4100                 :          0 :         uniqueValues = mDataProvider->uniqueValues( index, limit );
    4101                 :          0 :         return uniqueValues;
    4102                 :            :       }
    4103                 :            :       FALLTHROUGH
    4104                 :            :     //we need to go through each feature
    4105                 :            :     case QgsFields::OriginJoin:
    4106                 :            :     case QgsFields::OriginExpression:
    4107                 :            :     {
    4108                 :          0 :       QgsAttributeList attList;
    4109                 :          0 :       attList << index;
    4110                 :            : 
    4111                 :          0 :       QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
    4112                 :          0 :                                             .setFlags( QgsFeatureRequest::NoGeometry )
    4113                 :          0 :                                             .setSubsetOfAttributes( attList ) );
    4114                 :            : 
    4115                 :          0 :       QgsFeature f;
    4116                 :          0 :       QVariant currentValue;
    4117                 :          0 :       QHash<QString, QVariant> val;
    4118                 :          0 :       while ( fit.nextFeature( f ) )
    4119                 :            :       {
    4120                 :          0 :         currentValue = f.attribute( index );
    4121                 :          0 :         val.insert( currentValue.toString(), currentValue );
    4122                 :          0 :         if ( limit >= 0 && val.size() >= limit )
    4123                 :            :         {
    4124                 :          0 :           break;
    4125                 :            :         }
    4126                 :            :       }
    4127                 :            : 
    4128                 :          0 :       return qgis::listToSet( val.values() );
    4129                 :          0 :     }
    4130                 :            :   }
    4131                 :            : 
    4132                 :            :   Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
    4133                 :          0 :   return uniqueValues;
    4134                 :          0 : }
    4135                 :            : 
    4136                 :          0 : QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
    4137                 :            : {
    4138                 :          0 :   QStringList results;
    4139                 :          0 :   if ( !mDataProvider )
    4140                 :            :   {
    4141                 :          0 :     return results;
    4142                 :            :   }
    4143                 :            : 
    4144                 :          0 :   QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
    4145                 :          0 :   switch ( origin )
    4146                 :            :   {
    4147                 :            :     case QgsFields::OriginUnknown:
    4148                 :          0 :       return results;
    4149                 :            : 
    4150                 :            :     case QgsFields::OriginProvider: //a provider field
    4151                 :            :     {
    4152                 :          0 :       results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
    4153                 :            : 
    4154                 :          0 :       if ( mEditBuffer && ! mDataProvider->transaction() )
    4155                 :            :       {
    4156                 :          0 :         QgsFeatureMap added = mEditBuffer->addedFeatures();
    4157                 :          0 :         QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
    4158                 :          0 :         while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
    4159                 :            :         {
    4160                 :          0 :           addedIt.next();
    4161                 :          0 :           QVariant v = addedIt.value().attribute( index );
    4162                 :          0 :           if ( v.isValid() )
    4163                 :            :           {
    4164                 :          0 :             QString vs = v.toString();
    4165                 :          0 :             if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
    4166                 :            :             {
    4167                 :          0 :               results << vs;
    4168                 :          0 :             }
    4169                 :          0 :           }
    4170                 :          0 :         }
    4171                 :            : 
    4172                 :          0 :         QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
    4173                 :          0 :         while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
    4174                 :            :         {
    4175                 :          0 :           it.next();
    4176                 :          0 :           QVariant v = it.value().value( index );
    4177                 :          0 :           if ( v.isValid() )
    4178                 :            :           {
    4179                 :          0 :             QString vs = v.toString();
    4180                 :          0 :             if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
    4181                 :            :             {
    4182                 :          0 :               results << vs;
    4183                 :          0 :             }
    4184                 :          0 :           }
    4185                 :          0 :         }
    4186                 :          0 :       }
    4187                 :            : 
    4188                 :          0 :       return results;
    4189                 :            :     }
    4190                 :            : 
    4191                 :            :     case QgsFields::OriginEdit:
    4192                 :            :       // the layer is editable, but in certain cases it can still be avoided going through all features
    4193                 :          0 :       if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
    4194                 :          0 :                                              mEditBuffer->addedFeatures().isEmpty() &&
    4195                 :          0 :                                              !mEditBuffer->deletedAttributeIds().contains( index ) &&
    4196                 :          0 :                                              mEditBuffer->changedAttributeValues().isEmpty() ) )
    4197                 :            :       {
    4198                 :          0 :         return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
    4199                 :            :       }
    4200                 :            :       FALLTHROUGH
    4201                 :            :     //we need to go through each feature
    4202                 :            :     case QgsFields::OriginJoin:
    4203                 :            :     case QgsFields::OriginExpression:
    4204                 :            :     {
    4205                 :          0 :       QgsAttributeList attList;
    4206                 :          0 :       attList << index;
    4207                 :            : 
    4208                 :          0 :       QgsFeatureRequest request;
    4209                 :          0 :       request.setSubsetOfAttributes( attList );
    4210                 :          0 :       request.setFlags( QgsFeatureRequest::NoGeometry );
    4211                 :          0 :       QString fieldName = mFields.at( index ).name();
    4212                 :          0 :       request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
    4213                 :          0 :       QgsFeatureIterator fit = getFeatures( request );
    4214                 :            : 
    4215                 :          0 :       QgsFeature f;
    4216                 :          0 :       QString currentValue;
    4217                 :          0 :       while ( fit.nextFeature( f ) )
    4218                 :            :       {
    4219                 :          0 :         currentValue = f.attribute( index ).toString();
    4220                 :          0 :         if ( !results.contains( currentValue ) )
    4221                 :          0 :           results << currentValue;
    4222                 :            : 
    4223                 :          0 :         if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
    4224                 :            :         {
    4225                 :          0 :           break;
    4226                 :            :         }
    4227                 :            :       }
    4228                 :            : 
    4229                 :          0 :       return results;
    4230                 :          0 :     }
    4231                 :            :   }
    4232                 :            : 
    4233                 :            :   Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
    4234                 :          0 :   return results;
    4235                 :          0 : }
    4236                 :            : 
    4237                 :          0 : QVariant QgsVectorLayer::minimumValue( int index ) const
    4238                 :            : {
    4239                 :          0 :   QVariant minimum;
    4240                 :          0 :   minimumOrMaximumValue( index, &minimum, nullptr );
    4241                 :          0 :   return minimum;
    4242                 :          0 : }
    4243                 :            : 
    4244                 :          0 : QVariant QgsVectorLayer::maximumValue( int index ) const
    4245                 :            : {
    4246                 :          0 :   QVariant maximum;
    4247                 :          0 :   minimumOrMaximumValue( index, nullptr, &maximum );
    4248                 :          0 :   return maximum;
    4249                 :          0 : }
    4250                 :            : 
    4251                 :          0 : void QgsVectorLayer::minimumAndMaximumValue( int index, QVariant &minimum, QVariant &maximum ) const
    4252                 :            : {
    4253                 :          0 :   minimumOrMaximumValue( index, &minimum, &maximum );
    4254                 :          0 : }
    4255                 :            : 
    4256                 :          0 : void QgsVectorLayer::minimumOrMaximumValue( int index, QVariant *minimum, QVariant *maximum ) const
    4257                 :            : {
    4258                 :          0 :   if ( minimum )
    4259                 :          0 :     *minimum = QVariant();
    4260                 :          0 :   if ( maximum )
    4261                 :          0 :     *maximum = QVariant();
    4262                 :            : 
    4263                 :          0 :   if ( !mDataProvider )
    4264                 :            :   {
    4265                 :          0 :     return;
    4266                 :            :   }
    4267                 :            : 
    4268                 :          0 :   QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
    4269                 :            : 
    4270                 :          0 :   switch ( origin )
    4271                 :            :   {
    4272                 :            :     case QgsFields::OriginUnknown:
    4273                 :            :     {
    4274                 :          0 :       return;
    4275                 :            :     }
    4276                 :            : 
    4277                 :            :     case QgsFields::OriginProvider: //a provider field
    4278                 :            :     {
    4279                 :          0 :       if ( minimum )
    4280                 :          0 :         *minimum = mDataProvider->minimumValue( index );
    4281                 :          0 :       if ( maximum )
    4282                 :          0 :         *maximum = mDataProvider->maximumValue( index );
    4283                 :          0 :       if ( mEditBuffer && ! mDataProvider->transaction() )
    4284                 :            :       {
    4285                 :          0 :         const QgsFeatureMap added = mEditBuffer->addedFeatures();
    4286                 :          0 :         QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
    4287                 :          0 :         while ( addedIt.hasNext() )
    4288                 :            :         {
    4289                 :          0 :           addedIt.next();
    4290                 :          0 :           const QVariant v = addedIt.value().attribute( index );
    4291                 :          0 :           if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
    4292                 :          0 :             *minimum = v;
    4293                 :          0 :           if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
    4294                 :          0 :             *maximum = v;
    4295                 :          0 :         }
    4296                 :            : 
    4297                 :          0 :         QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
    4298                 :          0 :         while ( it.hasNext() )
    4299                 :            :         {
    4300                 :          0 :           it.next();
    4301                 :          0 :           const QVariant v = it.value().value( index );
    4302                 :          0 :           if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
    4303                 :          0 :             *minimum = v;
    4304                 :          0 :           if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
    4305                 :          0 :             *maximum = v;
    4306                 :          0 :         }
    4307                 :          0 :       }
    4308                 :          0 :       return;
    4309                 :            :     }
    4310                 :            : 
    4311                 :            :     case QgsFields::OriginEdit:
    4312                 :            :     {
    4313                 :            :       // the layer is editable, but in certain cases it can still be avoided going through all features
    4314                 :          0 :       if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
    4315                 :          0 :                                              mEditBuffer->addedFeatures().isEmpty() &&
    4316                 :          0 :                                              !mEditBuffer->deletedAttributeIds().contains( index ) &&
    4317                 :          0 :                                              mEditBuffer->changedAttributeValues().isEmpty() ) )
    4318                 :            :       {
    4319                 :          0 :         if ( minimum )
    4320                 :          0 :           *minimum = mDataProvider->minimumValue( index );
    4321                 :          0 :         if ( maximum )
    4322                 :          0 :           *maximum = mDataProvider->maximumValue( index );
    4323                 :          0 :         return;
    4324                 :            :       }
    4325                 :          0 :     }
    4326                 :            :     FALLTHROUGH
    4327                 :            :     // no choice but to go through all features
    4328                 :            :     case QgsFields::OriginExpression:
    4329                 :            :     case QgsFields::OriginJoin:
    4330                 :            :     {
    4331                 :            :       // we need to go through each feature
    4332                 :          0 :       QgsAttributeList attList;
    4333                 :          0 :       attList << index;
    4334                 :            : 
    4335                 :          0 :       QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
    4336                 :          0 :                                             .setFlags( QgsFeatureRequest::NoGeometry )
    4337                 :          0 :                                             .setSubsetOfAttributes( attList ) );
    4338                 :            : 
    4339                 :          0 :       QgsFeature f;
    4340                 :          0 :       bool firstValue = true;
    4341                 :          0 :       while ( fit.nextFeature( f ) )
    4342                 :            :       {
    4343                 :          0 :         const QVariant currentValue = f.attribute( index );
    4344                 :          0 :         if ( currentValue.isNull() )
    4345                 :          0 :           continue;
    4346                 :            : 
    4347                 :          0 :         if ( firstValue )
    4348                 :            :         {
    4349                 :          0 :           if ( minimum )
    4350                 :          0 :             *minimum = currentValue;
    4351                 :          0 :           if ( maximum )
    4352                 :          0 :             *maximum = currentValue;
    4353                 :          0 :           firstValue = false;
    4354                 :          0 :         }
    4355                 :            :         else
    4356                 :            :         {
    4357                 :          0 :           if ( minimum && currentValue.isValid() && qgsVariantLessThan( currentValue, *minimum ) )
    4358                 :          0 :             *minimum = currentValue;
    4359                 :          0 :           if ( maximum && currentValue.isValid() && qgsVariantGreaterThan( currentValue, *maximum ) )
    4360                 :          0 :             *maximum = currentValue;
    4361                 :            :         }
    4362                 :          0 :       }
    4363                 :            :       return;
    4364                 :          0 :     }
    4365                 :            :   }
    4366                 :            : 
    4367                 :            :   Q_ASSERT_X( false, "QgsVectorLayer::minimumOrMaximumValue()", "Unknown source of the field!" );
    4368                 :          0 : }
    4369                 :            : 
    4370                 :          0 : QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
    4371                 :            :                                     const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context,
    4372                 :            :                                     bool *ok, QgsFeatureIds *fids ) const
    4373                 :            : {
    4374                 :          0 :   if ( ok )
    4375                 :          0 :     *ok = false;
    4376                 :            : 
    4377                 :          0 :   if ( !mDataProvider )
    4378                 :            :   {
    4379                 :          0 :     return QVariant();
    4380                 :            :   }
    4381                 :            : 
    4382                 :            :   // test if we are calculating based on a field
    4383                 :          0 :   int attrIndex = mFields.lookupField( fieldOrExpression );
    4384                 :          0 :   if ( attrIndex >= 0 )
    4385                 :            :   {
    4386                 :            :     // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
    4387                 :            :     // to the provider itself
    4388                 :          0 :     QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
    4389                 :          0 :     if ( origin == QgsFields::OriginProvider )
    4390                 :            :     {
    4391                 :          0 :       bool providerOk = false;
    4392                 :          0 :       QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk, fids );
    4393                 :          0 :       if ( providerOk )
    4394                 :            :       {
    4395                 :            :         // provider handled calculation
    4396                 :          0 :         if ( ok )
    4397                 :          0 :           *ok = true;
    4398                 :          0 :         return val;
    4399                 :            :       }
    4400                 :          0 :     }
    4401                 :          0 :   }
    4402                 :            : 
    4403                 :            :   // fallback to using aggregate calculator to determine aggregate
    4404                 :          0 :   QgsAggregateCalculator c( this );
    4405                 :          0 :   if ( fids )
    4406                 :          0 :     c.setFidsFilter( *fids );
    4407                 :          0 :   c.setParameters( parameters );
    4408                 :          0 :   return c.calculate( aggregate, fieldOrExpression, context, ok );
    4409                 :          0 : }
    4410                 :            : 
    4411                 :          0 : void QgsVectorLayer::setFeatureBlendMode( QPainter::CompositionMode featureBlendMode )
    4412                 :            : {
    4413                 :          0 :   if ( mFeatureBlendMode == featureBlendMode )
    4414                 :          0 :     return;
    4415                 :            : 
    4416                 :          0 :   mFeatureBlendMode = featureBlendMode;
    4417                 :          0 :   emit featureBlendModeChanged( featureBlendMode );
    4418                 :          0 :   emit styleChanged();
    4419                 :          0 : }
    4420                 :            : 
    4421                 :          0 : QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
    4422                 :            : {
    4423                 :          0 :   return mFeatureBlendMode;
    4424                 :            : }
    4425                 :            : 
    4426                 :          0 : void QgsVectorLayer::readSldLabeling( const QDomNode &node )
    4427                 :            : {
    4428                 :          0 :   setLabeling( nullptr ); // start with no labeling
    4429                 :          0 :   setLabelsEnabled( false );
    4430                 :            : 
    4431                 :          0 :   QDomElement element = node.toElement();
    4432                 :          0 :   if ( element.isNull() )
    4433                 :          0 :     return;
    4434                 :            : 
    4435                 :          0 :   QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
    4436                 :          0 :   if ( userStyleElem.isNull() )
    4437                 :            :   {
    4438                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: UserStyle element not found." ), 4 );
    4439                 :          0 :     return;
    4440                 :            :   }
    4441                 :            : 
    4442                 :          0 :   QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
    4443                 :          0 :   if ( featTypeStyleElem.isNull() )
    4444                 :            :   {
    4445                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: FeatureTypeStyle element not found." ), 4 );
    4446                 :          0 :     return;
    4447                 :            :   }
    4448                 :            : 
    4449                 :            :   // create empty FeatureTypeStyle element to merge TextSymbolizer's Rule's from all FeatureTypeStyle's
    4450                 :          0 :   QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode( false ).toElement();
    4451                 :            : 
    4452                 :            :   // use the RuleRenderer when more rules are present or the rule
    4453                 :            :   // has filters or min/max scale denominators set,
    4454                 :            :   // otherwise use the Simple labeling
    4455                 :          0 :   bool needRuleBasedLabeling = false;
    4456                 :          0 :   int ruleCount = 0;
    4457                 :            : 
    4458                 :          0 :   while ( !featTypeStyleElem.isNull() )
    4459                 :            :   {
    4460                 :          0 :     QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
    4461                 :          0 :     while ( !ruleElem.isNull() )
    4462                 :            :     {
    4463                 :            :       // test rule children element to check if we need to create RuleRenderer
    4464                 :            :       // and if the rule has a symbolizer
    4465                 :          0 :       bool hasTextSymbolizer = false;
    4466                 :          0 :       bool hasRuleBased = false;
    4467                 :          0 :       QDomElement ruleChildElem = ruleElem.firstChildElement();
    4468                 :          0 :       while ( !ruleChildElem.isNull() )
    4469                 :            :       {
    4470                 :            :         // rule has filter or min/max scale denominator, use the RuleRenderer
    4471                 :          0 :         if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
    4472                 :          0 :              ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
    4473                 :          0 :              ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
    4474                 :            :         {
    4475                 :          0 :           hasRuleBased = true;
    4476                 :          0 :         }
    4477                 :            :         // rule has a renderer symbolizer, not a text symbolizer
    4478                 :          0 :         else if ( ruleChildElem.localName() == QLatin1String( "TextSymbolizer" ) )
    4479                 :            :         {
    4480                 :          0 :           QgsDebugMsgLevel( QStringLiteral( "Info: TextSymbolizer element found" ), 4 );
    4481                 :          0 :           hasTextSymbolizer = true;
    4482                 :          0 :         }
    4483                 :            : 
    4484                 :          0 :         ruleChildElem = ruleChildElem.nextSiblingElement();
    4485                 :            :       }
    4486                 :            : 
    4487                 :          0 :       if ( hasTextSymbolizer )
    4488                 :            :       {
    4489                 :          0 :         ruleCount++;
    4490                 :            : 
    4491                 :            :         // append a clone of all Rules to the merged FeatureTypeStyle element
    4492                 :          0 :         mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
    4493                 :            : 
    4494                 :          0 :         if ( hasRuleBased )
    4495                 :            :         {
    4496                 :          0 :           QgsDebugMsgLevel( QStringLiteral( "Info: Filter or Min/MaxScaleDenominator element found: need a RuleBasedLabeling" ), 4 );
    4497                 :          0 :           needRuleBasedLabeling = true;
    4498                 :          0 :         }
    4499                 :          0 :       }
    4500                 :            : 
    4501                 :            :       // more rules present, use the RuleRenderer
    4502                 :          0 :       if ( ruleCount > 1 )
    4503                 :            :       {
    4504                 :          0 :         QgsDebugMsgLevel( QStringLiteral( "Info: More Rule elements found: need a RuleBasedLabeling" ), 4 );
    4505                 :          0 :         needRuleBasedLabeling = true;
    4506                 :          0 :       }
    4507                 :            : 
    4508                 :            :       // not use the rule based labeling if no rules with textSymbolizer
    4509                 :          0 :       if ( ruleCount == 0 )
    4510                 :            :       {
    4511                 :          0 :         needRuleBasedLabeling = false;
    4512                 :          0 :       }
    4513                 :            : 
    4514                 :          0 :       ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
    4515                 :          0 :     }
    4516                 :          0 :     featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral( "FeatureTypeStyle" ) );
    4517                 :          0 :   }
    4518                 :            : 
    4519                 :          0 :   if ( ruleCount == 0 )
    4520                 :            :   {
    4521                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: No TextSymbolizer element." ), 4 );
    4522                 :          0 :     return;
    4523                 :            :   }
    4524                 :            : 
    4525                 :          0 :   QDomElement ruleElem = mergedFeatTypeStyle.firstChildElement( QStringLiteral( "Rule" ) );
    4526                 :            : 
    4527                 :          0 :   if ( needRuleBasedLabeling )
    4528                 :            :   {
    4529                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: rule based labeling" ), 4 );
    4530                 :          0 :     QgsRuleBasedLabeling::Rule *rootRule = new QgsRuleBasedLabeling::Rule( nullptr );
    4531                 :          0 :     while ( !ruleElem.isNull() )
    4532                 :            :     {
    4533                 :            : 
    4534                 :          0 :       QString label, description, filterExp;
    4535                 :          0 :       int scaleMinDenom = 0, scaleMaxDenom = 0;
    4536                 :          0 :       QgsPalLayerSettings settings;
    4537                 :            : 
    4538                 :            :       // retrieve the Rule element child nodes
    4539                 :          0 :       QDomElement childElem = ruleElem.firstChildElement();
    4540                 :          0 :       while ( !childElem.isNull() )
    4541                 :            :       {
    4542                 :          0 :         if ( childElem.localName() == QLatin1String( "Name" ) )
    4543                 :            :         {
    4544                 :            :           // <se:Name> tag contains the rule identifier,
    4545                 :            :           // so prefer title tag for the label property value
    4546                 :          0 :           if ( label.isEmpty() )
    4547                 :          0 :             label = childElem.firstChild().nodeValue();
    4548                 :          0 :         }
    4549                 :          0 :         else if ( childElem.localName() == QLatin1String( "Description" ) )
    4550                 :            :         {
    4551                 :            :           // <se:Description> can contains a title and an abstract
    4552                 :          0 :           QDomElement titleElem = childElem.firstChildElement( QStringLiteral( "Title" ) );
    4553                 :          0 :           if ( !titleElem.isNull() )
    4554                 :            :           {
    4555                 :          0 :             label = titleElem.firstChild().nodeValue();
    4556                 :          0 :           }
    4557                 :            : 
    4558                 :          0 :           QDomElement abstractElem = childElem.firstChildElement( QStringLiteral( "Abstract" ) );
    4559                 :          0 :           if ( !abstractElem.isNull() )
    4560                 :            :           {
    4561                 :          0 :             description = abstractElem.firstChild().nodeValue();
    4562                 :          0 :           }
    4563                 :          0 :         }
    4564                 :          0 :         else if ( childElem.localName() == QLatin1String( "Abstract" ) )
    4565                 :            :         {
    4566                 :            :           // <sld:Abstract> (v1.0)
    4567                 :          0 :           description = childElem.firstChild().nodeValue();
    4568                 :          0 :         }
    4569                 :          0 :         else if ( childElem.localName() == QLatin1String( "Title" ) )
    4570                 :            :         {
    4571                 :            :           // <sld:Title> (v1.0)
    4572                 :          0 :           label = childElem.firstChild().nodeValue();
    4573                 :          0 :         }
    4574                 :          0 :         else if ( childElem.localName() == QLatin1String( "Filter" ) )
    4575                 :            :         {
    4576                 :          0 :           QgsExpression *filter = QgsOgcUtils::expressionFromOgcFilter( childElem );
    4577                 :          0 :           if ( filter )
    4578                 :            :           {
    4579                 :          0 :             if ( filter->hasParserError() )
    4580                 :            :             {
    4581                 :          0 :               QgsDebugMsgLevel( QStringLiteral( "SLD Filter parsing error: %1" ).arg( filter->parserErrorString() ), 3 );
    4582                 :          0 :             }
    4583                 :            :             else
    4584                 :            :             {
    4585                 :          0 :               filterExp = filter->expression();
    4586                 :            :             }
    4587                 :          0 :             delete filter;
    4588                 :          0 :           }
    4589                 :          0 :         }
    4590                 :          0 :         else if ( childElem.localName() == QLatin1String( "MinScaleDenominator" ) )
    4591                 :            :         {
    4592                 :            :           bool ok;
    4593                 :          0 :           int v = childElem.firstChild().nodeValue().toInt( &ok );
    4594                 :          0 :           if ( ok )
    4595                 :          0 :             scaleMinDenom = v;
    4596                 :          0 :         }
    4597                 :          0 :         else if ( childElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
    4598                 :            :         {
    4599                 :            :           bool ok;
    4600                 :          0 :           int v = childElem.firstChild().nodeValue().toInt( &ok );
    4601                 :          0 :           if ( ok )
    4602                 :          0 :             scaleMaxDenom = v;
    4603                 :          0 :         }
    4604                 :          0 :         else if ( childElem.localName() == QLatin1String( "TextSymbolizer" ) )
    4605                 :            :         {
    4606                 :          0 :           readSldTextSymbolizer( childElem, settings );
    4607                 :          0 :         }
    4608                 :            : 
    4609                 :          0 :         childElem = childElem.nextSiblingElement();
    4610                 :            :       }
    4611                 :            : 
    4612                 :          0 :       QgsRuleBasedLabeling::Rule *ruleLabeling = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings( settings ), scaleMinDenom, scaleMaxDenom, filterExp, label );
    4613                 :          0 :       rootRule->appendChild( ruleLabeling );
    4614                 :            : 
    4615                 :          0 :       ruleElem = ruleElem.nextSiblingElement();
    4616                 :          0 :     }
    4617                 :            : 
    4618                 :          0 :     setLabeling( new QgsRuleBasedLabeling( rootRule ) );
    4619                 :          0 :     setLabelsEnabled( true );
    4620                 :          0 :   }
    4621                 :            :   else
    4622                 :            :   {
    4623                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: simple labeling" ), 4 );
    4624                 :            :     // retrieve the TextSymbolizer element child node
    4625                 :          0 :     QDomElement textSymbolizerElem = ruleElem.firstChildElement( QStringLiteral( "TextSymbolizer" ) );
    4626                 :          0 :     QgsPalLayerSettings s;
    4627                 :          0 :     if ( readSldTextSymbolizer( textSymbolizerElem, s ) )
    4628                 :            :     {
    4629                 :          0 :       setLabeling( new QgsVectorLayerSimpleLabeling( s ) );
    4630                 :          0 :       setLabelsEnabled( true );
    4631                 :          0 :     }
    4632                 :          0 :   }
    4633                 :          0 : }
    4634                 :            : 
    4635                 :          0 : bool QgsVectorLayer::readSldTextSymbolizer( const QDomNode &node, QgsPalLayerSettings &settings ) const
    4636                 :            : {
    4637                 :          0 :   if ( node.localName() != QLatin1String( "TextSymbolizer" ) )
    4638                 :            :   {
    4639                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Not a TextSymbolizer element: %1" ).arg( node.localName() ), 3 );
    4640                 :          0 :     return false;
    4641                 :            :   }
    4642                 :          0 :   QDomElement textSymbolizerElem = node.toElement();
    4643                 :            :   // Label
    4644                 :          0 :   QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
    4645                 :          0 :   if ( !labelElem.isNull() )
    4646                 :            :   {
    4647                 :          0 :     QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
    4648                 :          0 :     if ( !propertyNameElem.isNull() )
    4649                 :            :     {
    4650                 :            :       // set labeling defaults
    4651                 :            : 
    4652                 :            :       // label attribute
    4653                 :          0 :       QString labelAttribute = propertyNameElem.text();
    4654                 :          0 :       settings.fieldName = labelAttribute;
    4655                 :          0 :       settings.isExpression = false;
    4656                 :            : 
    4657                 :          0 :       int fieldIndex = mFields.lookupField( labelAttribute );
    4658                 :          0 :       if ( fieldIndex == -1 )
    4659                 :            :       {
    4660                 :            :         // label attribute is not in columns, check if it is an expression
    4661                 :          0 :         QgsExpression exp( labelAttribute );
    4662                 :          0 :         if ( !exp.hasEvalError() )
    4663                 :            :         {
    4664                 :          0 :           settings.isExpression = true;
    4665                 :          0 :         }
    4666                 :            :         else
    4667                 :            :         {
    4668                 :          0 :           QgsDebugMsgLevel( QStringLiteral( "SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
    4669                 :            :         }
    4670                 :          0 :       }
    4671                 :          0 :     }
    4672                 :            :     else
    4673                 :            :     {
    4674                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "Info: PropertyName element not found." ), 4 );
    4675                 :          0 :       return false;
    4676                 :            :     }
    4677                 :          0 :   }
    4678                 :            :   else
    4679                 :            :   {
    4680                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: Label element not found." ), 4 );
    4681                 :          0 :     return false;
    4682                 :            :   }
    4683                 :            : 
    4684                 :          0 :   QgsUnitTypes::RenderUnit sldUnitSize = QgsUnitTypes::RenderPixels;
    4685                 :          0 :   if ( textSymbolizerElem.hasAttribute( QStringLiteral( "uom" ) ) )
    4686                 :            :   {
    4687                 :          0 :     sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( textSymbolizerElem.attribute( QStringLiteral( "uom" ) ) );
    4688                 :          0 :   }
    4689                 :            : 
    4690                 :          0 :   QString fontFamily = QStringLiteral( "Sans-Serif" );
    4691                 :          0 :   int fontPointSize = 10;
    4692                 :          0 :   QgsUnitTypes::RenderUnit fontUnitSize = QgsUnitTypes::RenderPoints;
    4693                 :          0 :   int fontWeight = -1;
    4694                 :          0 :   bool fontItalic = false;
    4695                 :          0 :   bool fontUnderline = false;
    4696                 :            : 
    4697                 :            :   // Font
    4698                 :          0 :   QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
    4699                 :          0 :   if ( !fontElem.isNull() )
    4700                 :            :   {
    4701                 :          0 :     QgsStringMap fontSvgParams = QgsSymbolLayerUtils::getSvgParameterList( fontElem );
    4702                 :          0 :     for ( QgsStringMap::iterator it = fontSvgParams.begin(); it != fontSvgParams.end(); ++it )
    4703                 :            :     {
    4704                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "found fontSvgParams %1: %2" ).arg( it.key(), it.value() ), 4 );
    4705                 :            : 
    4706                 :          0 :       if ( it.key() == QLatin1String( "font-family" ) )
    4707                 :            :       {
    4708                 :          0 :         fontFamily = it.value();
    4709                 :          0 :       }
    4710                 :          0 :       else if ( it.key() == QLatin1String( "font-style" ) )
    4711                 :            :       {
    4712                 :          0 :         fontItalic = ( it.value() == QLatin1String( "italic" ) ) || ( it.value() == QLatin1String( "Italic" ) );
    4713                 :          0 :       }
    4714                 :          0 :       else if ( it.key() == QLatin1String( "font-size" ) )
    4715                 :            :       {
    4716                 :            :         bool ok;
    4717                 :          0 :         int fontSize = it.value().toInt( &ok );
    4718                 :          0 :         if ( ok )
    4719                 :            :         {
    4720                 :          0 :           fontPointSize = fontSize;
    4721                 :          0 :           fontUnitSize = sldUnitSize;
    4722                 :          0 :         }
    4723                 :          0 :       }
    4724                 :          0 :       else if ( it.key() == QLatin1String( "font-weight" ) )
    4725                 :            :       {
    4726                 :          0 :         if ( ( it.value() == QLatin1String( "bold" ) ) || ( it.value() == QLatin1String( "Bold" ) ) )
    4727                 :          0 :           fontWeight = QFont::Bold;
    4728                 :          0 :       }
    4729                 :          0 :       else if ( it.key() == QLatin1String( "font-underline" ) )
    4730                 :            :       {
    4731                 :          0 :         fontUnderline = ( it.value() == QLatin1String( "underline" ) ) || ( it.value() == QLatin1String( "Underline" ) );
    4732                 :          0 :       }
    4733                 :          0 :     }
    4734                 :          0 :   }
    4735                 :            : 
    4736                 :          0 :   QgsTextFormat format;
    4737                 :          0 :   QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
    4738                 :          0 :   font.setUnderline( fontUnderline );
    4739                 :          0 :   format.setFont( font );
    4740                 :          0 :   format.setSize( fontPointSize );
    4741                 :          0 :   format.setSizeUnit( fontUnitSize );
    4742                 :            : 
    4743                 :            :   // Fill
    4744                 :          0 :   QDomElement fillElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) );
    4745                 :          0 :   QColor textColor;
    4746                 :          0 :   Qt::BrushStyle textBrush = Qt::SolidPattern;
    4747                 :          0 :   QgsSymbolLayerUtils::fillFromSld( fillElem, textBrush, textColor );
    4748                 :          0 :   if ( textColor.isValid() )
    4749                 :            :   {
    4750                 :          0 :     QgsDebugMsgLevel( QStringLiteral( "Info: textColor %1." ).arg( QVariant( textColor ).toString() ), 4 );
    4751                 :          0 :     format.setColor( textColor );
    4752                 :          0 :   }
    4753                 :            : 
    4754                 :          0 :   QgsTextBufferSettings bufferSettings;
    4755                 :            : 
    4756                 :            :   // Halo
    4757                 :          0 :   QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
    4758                 :          0 :   if ( !haloElem.isNull() )
    4759                 :            :   {
    4760                 :          0 :     bufferSettings.setEnabled( true );
    4761                 :          0 :     bufferSettings.setSize( 1 );
    4762                 :            : 
    4763                 :          0 :     QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
    4764                 :          0 :     if ( !radiusElem.isNull() )
    4765                 :            :     {
    4766                 :            :       bool ok;
    4767                 :          0 :       double bufferSize = radiusElem.text().toDouble( &ok );
    4768                 :          0 :       if ( ok )
    4769                 :            :       {
    4770                 :          0 :         bufferSettings.setSize( bufferSize );
    4771                 :          0 :         bufferSettings.setSizeUnit( sldUnitSize );
    4772                 :          0 :       }
    4773                 :          0 :     }
    4774                 :            : 
    4775                 :          0 :     QDomElement haloFillElem = haloElem.firstChildElement( QStringLiteral( "Fill" ) );
    4776                 :          0 :     QColor bufferColor;
    4777                 :          0 :     Qt::BrushStyle bufferBrush = Qt::SolidPattern;
    4778                 :          0 :     QgsSymbolLayerUtils::fillFromSld( haloFillElem, bufferBrush, bufferColor );
    4779                 :          0 :     if ( bufferColor.isValid() )
    4780                 :            :     {
    4781                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "Info: bufferColor %1." ).arg( QVariant( bufferColor ).toString() ), 4 );
    4782                 :          0 :       bufferSettings.setColor( bufferColor );
    4783                 :          0 :     }
    4784                 :          0 :   }
    4785                 :            : 
    4786                 :            :   // LabelPlacement
    4787                 :          0 :   QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
    4788                 :          0 :   if ( !labelPlacementElem.isNull() )
    4789                 :            :   {
    4790                 :            :     // PointPlacement
    4791                 :          0 :     QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
    4792                 :          0 :     if ( !pointPlacementElem.isNull() )
    4793                 :            :     {
    4794                 :          0 :       settings.placement = QgsPalLayerSettings::OverPoint;
    4795                 :          0 :       if ( geometryType() == QgsWkbTypes::LineGeometry )
    4796                 :            :       {
    4797                 :          0 :         settings.placement = QgsPalLayerSettings::Horizontal;
    4798                 :          0 :       }
    4799                 :            : 
    4800                 :          0 :       QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
    4801                 :          0 :       if ( !displacementElem.isNull() )
    4802                 :            :       {
    4803                 :          0 :         QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
    4804                 :          0 :         if ( !displacementXElem.isNull() )
    4805                 :            :         {
    4806                 :            :           bool ok;
    4807                 :          0 :           double xOffset = displacementXElem.text().toDouble( &ok );
    4808                 :          0 :           if ( ok )
    4809                 :            :           {
    4810                 :          0 :             settings.xOffset = xOffset;
    4811                 :          0 :             settings.offsetUnits = sldUnitSize;
    4812                 :          0 :           }
    4813                 :          0 :         }
    4814                 :          0 :         QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
    4815                 :          0 :         if ( !displacementYElem.isNull() )
    4816                 :            :         {
    4817                 :            :           bool ok;
    4818                 :          0 :           double yOffset = displacementYElem.text().toDouble( &ok );
    4819                 :          0 :           if ( ok )
    4820                 :            :           {
    4821                 :          0 :             settings.yOffset = yOffset;
    4822                 :          0 :             settings.offsetUnits = sldUnitSize;
    4823                 :          0 :           }
    4824                 :          0 :         }
    4825                 :          0 :       }
    4826                 :          0 :       QDomElement anchorPointElem = pointPlacementElem.firstChildElement( QStringLiteral( "AnchorPoint" ) );
    4827                 :          0 :       if ( !anchorPointElem.isNull() )
    4828                 :            :       {
    4829                 :          0 :         QDomElement anchorPointXElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointX" ) );
    4830                 :          0 :         if ( !anchorPointXElem.isNull() )
    4831                 :            :         {
    4832                 :            :           bool ok;
    4833                 :          0 :           double xOffset = anchorPointXElem.text().toDouble( &ok );
    4834                 :          0 :           if ( ok )
    4835                 :            :           {
    4836                 :          0 :             settings.xOffset = xOffset;
    4837                 :          0 :             settings.offsetUnits = sldUnitSize;
    4838                 :          0 :           }
    4839                 :          0 :         }
    4840                 :          0 :         QDomElement anchorPointYElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointY" ) );
    4841                 :          0 :         if ( !anchorPointYElem.isNull() )
    4842                 :            :         {
    4843                 :            :           bool ok;
    4844                 :          0 :           double yOffset = anchorPointYElem.text().toDouble( &ok );
    4845                 :          0 :           if ( ok )
    4846                 :            :           {
    4847                 :          0 :             settings.yOffset = yOffset;
    4848                 :          0 :             settings.offsetUnits = sldUnitSize;
    4849                 :          0 :           }
    4850                 :          0 :         }
    4851                 :          0 :       }
    4852                 :            : 
    4853                 :          0 :       QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
    4854                 :          0 :       if ( !rotationElem.isNull() )
    4855                 :            :       {
    4856                 :            :         bool ok;
    4857                 :          0 :         double rotation = rotationElem.text().toDouble( &ok );
    4858                 :          0 :         if ( ok )
    4859                 :            :         {
    4860                 :          0 :           settings.angleOffset = 360 - rotation;
    4861                 :          0 :         }
    4862                 :          0 :       }
    4863                 :          0 :     }
    4864                 :            :     else
    4865                 :            :     {
    4866                 :            :       // PointPlacement
    4867                 :          0 :       QDomElement linePlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "LinePlacement" ) );
    4868                 :          0 :       if ( !linePlacementElem.isNull() )
    4869                 :            :       {
    4870                 :          0 :         settings.placement = QgsPalLayerSettings::Line;
    4871                 :          0 :       }
    4872                 :          0 :     }
    4873                 :          0 :   }
    4874                 :            : 
    4875                 :            :   // read vendor options
    4876                 :          0 :   QgsStringMap vendorOptions;
    4877                 :          0 :   QDomElement vendorOptionElem = textSymbolizerElem.firstChildElement( QStringLiteral( "VendorOption" ) );
    4878                 :          0 :   while ( !vendorOptionElem.isNull() && vendorOptionElem.localName() == QLatin1String( "VendorOption" ) )
    4879                 :            :   {
    4880                 :          0 :     QString optionName = vendorOptionElem.attribute( QStringLiteral( "name" ) );
    4881                 :          0 :     QString optionValue;
    4882                 :          0 :     if ( vendorOptionElem.firstChild().nodeType() == QDomNode::TextNode )
    4883                 :            :     {
    4884                 :          0 :       optionValue = vendorOptionElem.firstChild().nodeValue();
    4885                 :          0 :     }
    4886                 :            :     else
    4887                 :            :     {
    4888                 :          0 :       if ( vendorOptionElem.firstChild().nodeType() == QDomNode::ElementNode &&
    4889                 :          0 :            vendorOptionElem.firstChild().localName() == QLatin1String( "Literal" ) )
    4890                 :            :       {
    4891                 :          0 :         QgsDebugMsg( vendorOptionElem.firstChild().localName() );
    4892                 :          0 :         optionValue = vendorOptionElem.firstChild().firstChild().nodeValue();
    4893                 :          0 :       }
    4894                 :            :       else
    4895                 :            :       {
    4896                 :          0 :         QgsDebugMsg( QStringLiteral( "unexpected child of %1 named %2" ).arg( vendorOptionElem.localName(), optionName ) );
    4897                 :            :       }
    4898                 :            :     }
    4899                 :            : 
    4900                 :          0 :     if ( !optionName.isEmpty() && !optionValue.isEmpty() )
    4901                 :            :     {
    4902                 :          0 :       vendorOptions[ optionName ] = optionValue;
    4903                 :          0 :     }
    4904                 :            : 
    4905                 :          0 :     vendorOptionElem = vendorOptionElem.nextSiblingElement();
    4906                 :          0 :   }
    4907                 :          0 :   if ( !vendorOptions.isEmpty() )
    4908                 :            :   {
    4909                 :          0 :     for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
    4910                 :            :     {
    4911                 :          0 :       if ( it.key() == QLatin1String( "underlineText" ) && it.value() == QLatin1String( "true" ) )
    4912                 :            :       {
    4913                 :          0 :         font.setUnderline( true );
    4914                 :          0 :         format.setFont( font );
    4915                 :          0 :       }
    4916                 :          0 :       else if ( it.key() == QLatin1String( "strikethroughText" ) && it.value() == QLatin1String( "true" ) )
    4917                 :            :       {
    4918                 :          0 :         font.setStrikeOut( true );
    4919                 :          0 :         format.setFont( font );
    4920                 :          0 :       }
    4921                 :          0 :       else if ( it.key() == QLatin1String( "maxDisplacement" ) )
    4922                 :            :       {
    4923                 :          0 :         settings.placement = QgsPalLayerSettings::AroundPoint;
    4924                 :          0 :       }
    4925                 :          0 :       else if ( it.key() == QLatin1String( "followLine" ) && it.value() == QLatin1String( "true" ) )
    4926                 :            :       {
    4927                 :          0 :         if ( geometryType() == QgsWkbTypes::PolygonGeometry )
    4928                 :            :         {
    4929                 :          0 :           settings.placement = QgsPalLayerSettings::PerimeterCurved;
    4930                 :          0 :         }
    4931                 :            :         else
    4932                 :            :         {
    4933                 :          0 :           settings.placement = QgsPalLayerSettings::Curved;
    4934                 :            :         }
    4935                 :          0 :       }
    4936                 :          0 :       else if ( it.key() == QLatin1String( "maxAngleDelta" ) )
    4937                 :            :       {
    4938                 :            :         bool ok;
    4939                 :          0 :         double angle = it.value().toDouble( &ok );
    4940                 :          0 :         if ( ok )
    4941                 :            :         {
    4942                 :          0 :           settings.maxCurvedCharAngleIn = angle;
    4943                 :          0 :           settings.maxCurvedCharAngleOut = angle;
    4944                 :          0 :         }
    4945                 :          0 :       }
    4946                 :            :       // miscellaneous options
    4947                 :          0 :       else if ( it.key() == QLatin1String( "conflictResolution" ) && it.value() == QLatin1String( "false" ) )
    4948                 :            :       {
    4949                 :          0 :         settings.displayAll = true;
    4950                 :          0 :       }
    4951                 :          0 :       else if ( it.key() == QLatin1String( "forceLeftToRight" ) && it.value() == QLatin1String( "false" ) )
    4952                 :            :       {
    4953                 :          0 :         settings.upsidedownLabels = QgsPalLayerSettings::ShowAll;
    4954                 :          0 :       }
    4955                 :          0 :       else if ( it.key() == QLatin1String( "group" ) && it.value() == QLatin1String( "yes" ) )
    4956                 :            :       {
    4957                 :          0 :         settings.lineSettings().setMergeLines( true );
    4958                 :          0 :       }
    4959                 :          0 :       else if ( it.key() == QLatin1String( "labelAllGroup" ) && it.value() == QLatin1String( "true" ) )
    4960                 :            :       {
    4961                 :          0 :         settings.lineSettings().setMergeLines( true );
    4962                 :          0 :       }
    4963                 :          0 :     }
    4964                 :          0 :   }
    4965                 :            : 
    4966                 :          0 :   format.setBuffer( bufferSettings );
    4967                 :          0 :   settings.setFormat( format );
    4968                 :          0 :   return true;
    4969                 :          0 : }
    4970                 :            : 
    4971                 :          0 : QgsEditFormConfig QgsVectorLayer::editFormConfig() const
    4972                 :            : {
    4973                 :          0 :   return mEditFormConfig;
    4974                 :            : }
    4975                 :            : 
    4976                 :          0 : void QgsVectorLayer::setEditFormConfig( const QgsEditFormConfig &editFormConfig )
    4977                 :            : {
    4978                 :          0 :   if ( mEditFormConfig == editFormConfig )
    4979                 :          0 :     return;
    4980                 :            : 
    4981                 :          0 :   mEditFormConfig = editFormConfig;
    4982                 :          0 :   mEditFormConfig.onRelationsLoaded();
    4983                 :          0 :   emit editFormConfigChanged();
    4984                 :          0 : }
    4985                 :            : 
    4986                 :          0 : QString QgsVectorLayer::mapTipTemplate() const
    4987                 :            : {
    4988                 :          0 :   return mMapTipTemplate;
    4989                 :            : }
    4990                 :            : 
    4991                 :          0 : void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
    4992                 :            : {
    4993                 :          0 :   if ( mMapTipTemplate == mapTip )
    4994                 :          0 :     return;
    4995                 :            : 
    4996                 :          0 :   mMapTipTemplate = mapTip;
    4997                 :          0 :   emit mapTipTemplateChanged();
    4998                 :          0 : }
    4999                 :            : 
    5000                 :          0 : QgsAttributeTableConfig QgsVectorLayer::attributeTableConfig() const
    5001                 :            : {
    5002                 :          0 :   QgsAttributeTableConfig config = mAttributeTableConfig;
    5003                 :            : 
    5004                 :          0 :   if ( config.isEmpty() )
    5005                 :          0 :     config.update( fields() );
    5006                 :            : 
    5007                 :          0 :   return config;
    5008                 :          0 : }
    5009                 :            : 
    5010                 :          0 : void QgsVectorLayer::setAttributeTableConfig( const QgsAttributeTableConfig &attributeTableConfig )
    5011                 :            : {
    5012                 :          0 :   if ( mAttributeTableConfig != attributeTableConfig )
    5013                 :            :   {
    5014                 :          0 :     mAttributeTableConfig = attributeTableConfig;
    5015                 :          0 :     emit configChanged();
    5016                 :          0 :   }
    5017                 :          0 : }
    5018                 :            : 
    5019                 :          0 : QgsExpressionContext QgsVectorLayer::createExpressionContext() const
    5020                 :            : {
    5021                 :          0 :   return QgsExpressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( this ) );
    5022                 :          0 : }
    5023                 :            : 
    5024                 :          0 : QgsExpressionContextScope *QgsVectorLayer::createExpressionContextScope() const
    5025                 :            : {
    5026                 :          0 :   return QgsExpressionContextUtils::layerScope( this );
    5027                 :            : }
    5028                 :            : 
    5029                 :          0 : void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings &s )
    5030                 :            : {
    5031                 :          0 :   if ( !mDiagramLayerSettings )
    5032                 :          0 :     mDiagramLayerSettings = new QgsDiagramLayerSettings();
    5033                 :          0 :   *mDiagramLayerSettings = s;
    5034                 :          0 : }
    5035                 :            : 
    5036                 :          0 : QString QgsVectorLayer::htmlMetadata() const
    5037                 :            : {
    5038                 :          0 :   QgsLayerMetadataFormatter htmlFormatter( metadata() );
    5039                 :          0 :   QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
    5040                 :            : 
    5041                 :            :   // Begin Provider section
    5042                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5043                 :          0 :   myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
    5044                 :            : 
    5045                 :            :   // name
    5046                 :          0 :   myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
    5047                 :            : 
    5048                 :            :   // local path
    5049                 :          0 :   QVariantMap uriComponents = QgsProviderRegistry::instance()->decodeUri( mProviderKey, publicSource() );
    5050                 :          0 :   QString path;
    5051                 :          0 :   bool isLocalPath = false;
    5052                 :          0 :   if ( uriComponents.contains( QStringLiteral( "path" ) ) )
    5053                 :            :   {
    5054                 :          0 :     path = uriComponents[QStringLiteral( "path" )].toString();
    5055                 :          0 :     if ( QFile::exists( path ) )
    5056                 :            :     {
    5057                 :          0 :       isLocalPath = true;
    5058                 :          0 :       myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Path" ) + QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( path ).toString(), QDir::toNativeSeparators( path ) ) ) + QStringLiteral( "</td></tr>\n" );
    5059                 :          0 :     }
    5060                 :          0 :   }
    5061                 :          0 :   if ( uriComponents.contains( QStringLiteral( "url" ) ) )
    5062                 :            :   {
    5063                 :          0 :     const QString url = uriComponents[QStringLiteral( "url" )].toString();
    5064                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "URL" ) + QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl( url ).toString(), url ) ) + QStringLiteral( "</td></tr>\n" );
    5065                 :          0 :   }
    5066                 :            : 
    5067                 :            :   // data source
    5068                 :          0 :   if ( publicSource() != path || !isLocalPath )
    5069                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>%1" ).arg( publicSource() != path ? publicSource() : path ) + QStringLiteral( "</td></tr>\n" );
    5070                 :            : 
    5071                 :            :   // storage type
    5072                 :          0 :   myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
    5073                 :            : 
    5074                 :            :   // comment
    5075                 :          0 :   myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
    5076                 :            : 
    5077                 :            :   // encoding
    5078                 :          0 :   const QgsVectorDataProvider *provider = dataProvider();
    5079                 :          0 :   if ( provider )
    5080                 :            :   {
    5081                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + provider->encoding() + QStringLiteral( "</td></tr>\n" );
    5082                 :          0 :   }
    5083                 :            : 
    5084                 :          0 :   if ( isSpatial() )
    5085                 :            :   {
    5086                 :            :     // geom type
    5087                 :          0 :     QgsWkbTypes::GeometryType type = geometryType();
    5088                 :          0 :     if ( type < 0 || type > QgsWkbTypes::NullGeometry )
    5089                 :            :     {
    5090                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "Invalid vector type" ), 2 );
    5091                 :          0 :     }
    5092                 :            :     else
    5093                 :            :     {
    5094                 :          0 :       QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
    5095                 :          0 :                           QgsWkbTypes::displayString( wkbType() ) ) );
    5096                 :          0 :       myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
    5097                 :          0 :     }
    5098                 :            : 
    5099                 :            :     // EPSG
    5100                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" );
    5101                 :          0 :     if ( crs().isValid() )
    5102                 :            :     {
    5103                 :          0 :       myMetadata += crs().userFriendlyIdentifier( QgsCoordinateReferenceSystem::FullString ) + QStringLiteral( " - " );
    5104                 :          0 :       if ( crs().isGeographic() )
    5105                 :          0 :         myMetadata += tr( "Geographic" );
    5106                 :            :       else
    5107                 :          0 :         myMetadata += tr( "Projected" );
    5108                 :          0 :     }
    5109                 :          0 :     myMetadata += QLatin1String( "</td></tr>\n" );
    5110                 :            : 
    5111                 :            :     // Extent
    5112                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
    5113                 :            : 
    5114                 :            :     // unit
    5115                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
    5116                 :            : 
    5117                 :          0 :   }
    5118                 :            : 
    5119                 :            :   // feature count
    5120                 :          0 :   QLocale locale = QLocale();
    5121                 :          0 :   locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
    5122                 :          0 :   myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
    5123                 :          0 :                 + tr( "Feature count" ) + QStringLiteral( "</td><td>" )
    5124                 :          0 :                 + ( featureCount() == -1 ? tr( "unknown" ) : locale.toString( static_cast<qlonglong>( featureCount() ) ) )
    5125                 :          0 :                 + QStringLiteral( "</td></tr>\n" );
    5126                 :            : 
    5127                 :            :   // End Provider section
    5128                 :          0 :   myMetadata += QLatin1String( "</table>\n<br><br>" );
    5129                 :            : 
    5130                 :            :   // identification section
    5131                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5132                 :          0 :   myMetadata += htmlFormatter.identificationSectionHtml( );
    5133                 :          0 :   myMetadata += QLatin1String( "<br><br>\n" );
    5134                 :            : 
    5135                 :            :   // extent section
    5136                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5137                 :          0 :   myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
    5138                 :          0 :   myMetadata += QLatin1String( "<br><br>\n" );
    5139                 :            : 
    5140                 :            :   // Start the Access section
    5141                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5142                 :          0 :   myMetadata += htmlFormatter.accessSectionHtml( );
    5143                 :          0 :   myMetadata += QLatin1String( "<br><br>\n" );
    5144                 :            : 
    5145                 :            :   // Fields section
    5146                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
    5147                 :            : 
    5148                 :            :   // primary key
    5149                 :          0 :   QgsAttributeList pkAttrList = primaryKeyAttributes();
    5150                 :          0 :   if ( !pkAttrList.isEmpty() )
    5151                 :            :   {
    5152                 :          0 :     myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
    5153                 :          0 :     const auto constPkAttrList = pkAttrList;
    5154                 :          0 :     for ( int idx : constPkAttrList )
    5155                 :            :     {
    5156                 :          0 :       myMetadata += fields().at( idx ).name() + ' ';
    5157                 :            :     }
    5158                 :          0 :     myMetadata += QLatin1String( "</td></tr>\n" );
    5159                 :          0 :   }
    5160                 :            : 
    5161                 :          0 :   const QgsFields myFields = fields();
    5162                 :            : 
    5163                 :            :   // count fields
    5164                 :          0 :   myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
    5165                 :            : 
    5166                 :          0 :   myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
    5167                 :          0 :   myMetadata += QLatin1String( "<tr><th>" ) + tr( "Field" ) + QLatin1String( "</th><th>" ) + tr( "Type" ) + QLatin1String( "</th><th>" ) + tr( "Length" ) + QLatin1String( "</th><th>" ) + tr( "Precision" ) + QLatin1String( "</th><th>" ) + tr( "Comment" ) + QLatin1String( "</th></tr>\n" );
    5168                 :            : 
    5169                 :          0 :   for ( int i = 0; i < myFields.size(); ++i )
    5170                 :            :   {
    5171                 :          0 :     QgsField myField = myFields.at( i );
    5172                 :          0 :     QString rowClass;
    5173                 :          0 :     if ( i % 2 )
    5174                 :          0 :       rowClass = QStringLiteral( "class=\"odd-row\"" );
    5175                 :          0 :     myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td>" ) + myField.name() + QLatin1String( "</td><td>" ) + myField.typeName() + QLatin1String( "</td><td>" ) + QString::number( myField.length() ) + QLatin1String( "</td><td>" ) + QString::number( myField.precision() ) + QLatin1String( "</td><td>" ) + myField.comment() + QLatin1String( "</td></tr>\n" );
    5176                 :          0 :   }
    5177                 :            : 
    5178                 :            :   //close field list
    5179                 :          0 :   myMetadata += QLatin1String( "</table>\n<br><br>" );
    5180                 :            : 
    5181                 :            :   // Start the contacts section
    5182                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5183                 :          0 :   myMetadata += htmlFormatter.contactsSectionHtml( );
    5184                 :          0 :   myMetadata += QLatin1String( "<br><br>\n" );
    5185                 :            : 
    5186                 :            :   // Start the links section
    5187                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5188                 :          0 :   myMetadata += htmlFormatter.linksSectionHtml( );
    5189                 :          0 :   myMetadata += QLatin1String( "<br><br>\n" );
    5190                 :            : 
    5191                 :            :   // Start the history section
    5192                 :          0 :   myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
    5193                 :          0 :   myMetadata += htmlFormatter.historySectionHtml( );
    5194                 :          0 :   myMetadata += QLatin1String( "<br><br>\n" );
    5195                 :            : 
    5196                 :          0 :   myMetadata += QLatin1String( "\n</body>\n</html>\n" );
    5197                 :          0 :   return myMetadata;
    5198                 :          0 : }
    5199                 :            : 
    5200                 :          2 : void QgsVectorLayer::invalidateSymbolCountedFlag()
    5201                 :            : {
    5202                 :          2 :   mSymbolFeatureCounted = false;
    5203                 :          2 : }
    5204                 :            : 
    5205                 :          0 : void QgsVectorLayer::onFeatureCounterCompleted()
    5206                 :            : {
    5207                 :          0 :   onSymbolsCounted();
    5208                 :          0 :   mFeatureCounter = nullptr;
    5209                 :          0 : }
    5210                 :            : 
    5211                 :          0 : void QgsVectorLayer::onFeatureCounterTerminated()
    5212                 :            : {
    5213                 :          0 :   mFeatureCounter = nullptr;
    5214                 :          0 : }
    5215                 :            : 
    5216                 :          0 : void QgsVectorLayer::onJoinedFieldsChanged()
    5217                 :            : {
    5218                 :            :   // some of the fields of joined layers have changed -> we need to update this layer's fields too
    5219                 :          0 :   updateFields();
    5220                 :          0 : }
    5221                 :            : 
    5222                 :          0 : void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
    5223                 :            : {
    5224                 :          0 :   if ( mEditCommandActive )
    5225                 :          0 :     mDeletedFids << fid;
    5226                 :            :   else
    5227                 :          0 :     emit featuresDeleted( QgsFeatureIds() << fid );
    5228                 :            : 
    5229                 :          0 :   emit featureDeleted( fid );
    5230                 :          0 : }
    5231                 :            : 
    5232                 :          0 : void QgsVectorLayer::onRelationsLoaded()
    5233                 :            : {
    5234                 :          0 :   mEditFormConfig.onRelationsLoaded();
    5235                 :          0 : }
    5236                 :            : 
    5237                 :          0 : void QgsVectorLayer::onSymbolsCounted()
    5238                 :            : {
    5239                 :          0 :   if ( mFeatureCounter )
    5240                 :            :   {
    5241                 :          0 :     mSymbolFeatureCounted = true;
    5242                 :          0 :     mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
    5243                 :          0 :     mSymbolFeatureIdMap = mFeatureCounter->symbolFeatureIdMap();
    5244                 :          0 :     emit symbolFeatureCountMapChanged();
    5245                 :          0 :   }
    5246                 :          0 : }
    5247                 :            : 
    5248                 :          0 : QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
    5249                 :            : {
    5250                 :          0 :   return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
    5251                 :            : }
    5252                 :            : 
    5253                 :          0 : QList<QgsWeakRelation> QgsVectorLayer::weakRelations() const
    5254                 :            : {
    5255                 :          0 :   return mWeakRelations;
    5256                 :            : }
    5257                 :            : 
    5258                 :          0 : int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
    5259                 :            : {
    5260                 :          0 :   return QgsProviderRegistry::instance()->listStyles( mProviderKey, mDataSource, ids, names, descriptions, msgError );
    5261                 :          0 : }
    5262                 :            : 
    5263                 :          0 : QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
    5264                 :            : {
    5265                 :          0 :   return QgsProviderRegistry::instance()->getStyleById( mProviderKey, mDataSource, styleId, msgError );
    5266                 :          0 : }
    5267                 :            : 
    5268                 :          0 : bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
    5269                 :            : {
    5270                 :          0 :   return QgsProviderRegistry::instance()->deleteStyleById( mProviderKey, mDataSource, styleId, msgError );
    5271                 :          0 : }
    5272                 :            : 
    5273                 :            : 
    5274                 :          0 : void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
    5275                 :            :     bool useAsDefault, const QString &uiFileContent, QString &msgError )
    5276                 :            : {
    5277                 :            : 
    5278                 :          0 :   QString sldStyle, qmlStyle;
    5279                 :          0 :   QDomDocument qmlDocument, sldDocument;
    5280                 :          0 :   QgsReadWriteContext context;
    5281                 :          0 :   exportNamedStyle( qmlDocument, msgError, context );
    5282                 :          0 :   if ( !msgError.isNull() )
    5283                 :            :   {
    5284                 :          0 :     return;
    5285                 :            :   }
    5286                 :          0 :   qmlStyle = qmlDocument.toString();
    5287                 :            : 
    5288                 :          0 :   this->exportSldStyle( sldDocument, msgError );
    5289                 :          0 :   if ( !msgError.isNull() )
    5290                 :            :   {
    5291                 :          0 :     return;
    5292                 :            :   }
    5293                 :          0 :   sldStyle = sldDocument.toString();
    5294                 :            : 
    5295                 :          0 :   QgsProviderRegistry::instance()->saveStyle( mProviderKey,
    5296                 :          0 :       mDataSource, qmlStyle, sldStyle, name,
    5297                 :          0 :       description, uiFileContent, useAsDefault, msgError );
    5298                 :          0 : }
    5299                 :            : 
    5300                 :            : 
    5301                 :            : 
    5302                 :         78 : QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, QgsMapLayer::StyleCategories categories )
    5303                 :            : {
    5304                 :         78 :   return loadNamedStyle( theURI, resultFlag, false, categories );
    5305                 :            : }
    5306                 :            : 
    5307                 :          1 : bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
    5308                 :            : {
    5309                 :          1 :   bool rc = false;
    5310                 :            : 
    5311                 :          1 :   QString joinKey = mAuxiliaryLayerKey;
    5312                 :          1 :   if ( !key.isEmpty() )
    5313                 :          0 :     joinKey = key;
    5314                 :            : 
    5315                 :          1 :   if ( storage.isValid() && !joinKey.isEmpty() )
    5316                 :            :   {
    5317                 :          0 :     QgsAuxiliaryLayer *alayer = nullptr;
    5318                 :            : 
    5319                 :          0 :     int idx = fields().lookupField( joinKey );
    5320                 :            : 
    5321                 :          0 :     if ( idx >= 0 )
    5322                 :            :     {
    5323                 :          0 :       alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
    5324                 :            : 
    5325                 :          0 :       if ( alayer )
    5326                 :            :       {
    5327                 :          0 :         setAuxiliaryLayer( alayer );
    5328                 :          0 :         rc = true;
    5329                 :          0 :       }
    5330                 :          0 :     }
    5331                 :          0 :   }
    5332                 :            : 
    5333                 :          1 :   return rc;
    5334                 :          1 : }
    5335                 :            : 
    5336                 :          0 : void QgsVectorLayer::setAuxiliaryLayer( QgsAuxiliaryLayer *alayer )
    5337                 :            : {
    5338                 :          0 :   mAuxiliaryLayerKey.clear();
    5339                 :            : 
    5340                 :          0 :   if ( mAuxiliaryLayer )
    5341                 :          0 :     removeJoin( mAuxiliaryLayer->id() );
    5342                 :            : 
    5343                 :          0 :   if ( alayer )
    5344                 :            :   {
    5345                 :          0 :     addJoin( alayer->joinInfo() );
    5346                 :            : 
    5347                 :          0 :     if ( !alayer->isEditable() )
    5348                 :          0 :       alayer->startEditing();
    5349                 :            : 
    5350                 :          0 :     mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
    5351                 :          0 :   }
    5352                 :            : 
    5353                 :          0 :   mAuxiliaryLayer.reset( alayer );
    5354                 :          0 :   if ( mAuxiliaryLayer )
    5355                 :          0 :     mAuxiliaryLayer->setParent( this );
    5356                 :          0 :   updateFields();
    5357                 :          0 : }
    5358                 :            : 
    5359                 :          0 : const QgsAuxiliaryLayer *QgsVectorLayer::auxiliaryLayer() const
    5360                 :            : {
    5361                 :          0 :   return mAuxiliaryLayer.get();
    5362                 :            : }
    5363                 :            : 
    5364                 :          0 : QgsAuxiliaryLayer *QgsVectorLayer::auxiliaryLayer()
    5365                 :            : {
    5366                 :          0 :   return mAuxiliaryLayer.get();
    5367                 :            : }
    5368                 :            : 
    5369                 :         78 : QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories )
    5370                 :            : {
    5371                 :         78 :   QgsDataSourceUri dsUri( theURI );
    5372                 :         78 :   QString returnMessage;
    5373                 :         78 :   QString qml, errorMsg;
    5374                 :         78 :   if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
    5375                 :            :   {
    5376                 :          1 :     qml = QgsProviderRegistry::instance()->loadStyle( mProviderKey, mDataSource, errorMsg );
    5377                 :          1 :   }
    5378                 :         78 :   if ( !qml.isEmpty() )
    5379                 :            :   {
    5380                 :          0 :     QDomDocument myDocument( QStringLiteral( "qgis" ) );
    5381                 :          0 :     myDocument.setContent( qml );
    5382                 :          0 :     resultFlag = importNamedStyle( myDocument, errorMsg );
    5383                 :          0 :     returnMessage = QObject::tr( "Loaded from Provider" );
    5384                 :          0 :   }
    5385                 :            :   else
    5386                 :            :   {
    5387                 :         78 :     returnMessage = QgsMapLayer::loadNamedStyle( theURI, resultFlag, categories );
    5388                 :            :   }
    5389                 :            : 
    5390                 :         78 :   if ( resultFlag )
    5391                 :          0 :     emit styleLoaded( categories );
    5392                 :            : 
    5393                 :         78 :   return returnMessage;
    5394                 :         78 : }
    5395                 :            : 
    5396                 :          1 : QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
    5397                 :            : {
    5398                 :          1 :   if ( mDataProvider )
    5399                 :          1 :     return mDataProvider->dependencies() + mDependencies;
    5400                 :          0 :   return mDependencies;
    5401                 :          1 : }
    5402                 :            : 
    5403                 :          5 : void QgsVectorLayer::emitDataChanged()
    5404                 :            : {
    5405                 :          5 :   if ( mDataChangedFired )
    5406                 :          0 :     return;
    5407                 :            : 
    5408                 :          5 :   updateExtents(); // reset cached extent to reflect data changes
    5409                 :            : 
    5410                 :          5 :   mDataChangedFired = true;
    5411                 :          5 :   emit dataChanged();
    5412                 :          5 :   mDataChangedFired = false;
    5413                 :          5 : }
    5414                 :            : 
    5415                 :          0 : void QgsVectorLayer::onAfterCommitChangesDependency()
    5416                 :            : {
    5417                 :          0 :   mDataChangedFired = true;
    5418                 :          0 :   reload();
    5419                 :          0 :   mDataChangedFired = false;
    5420                 :          0 : }
    5421                 :            : 
    5422                 :          0 : bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
    5423                 :            : {
    5424                 :          0 :   QSet<QgsMapLayerDependency> deps;
    5425                 :          0 :   const auto constODeps = oDeps;
    5426                 :          0 :   for ( const QgsMapLayerDependency &dep : constODeps )
    5427                 :            :   {
    5428                 :          0 :     if ( dep.origin() == QgsMapLayerDependency::FromUser )
    5429                 :          0 :       deps << dep;
    5430                 :            :   }
    5431                 :            : 
    5432                 :          0 :   QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
    5433                 :            : 
    5434                 :            :   // disconnect layers that are not present in the list of dependencies anymore
    5435                 :          0 :   for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
    5436                 :            :   {
    5437                 :          0 :     QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
    5438                 :          0 :     if ( !lyr )
    5439                 :          0 :       continue;
    5440                 :          0 :     disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
    5441                 :          0 :     disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
    5442                 :          0 :     disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
    5443                 :          0 :     disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
    5444                 :          0 :     disconnect( lyr, &QgsVectorLayer::repaintRequested, this, &QgsVectorLayer::triggerRepaint );
    5445                 :          0 :     disconnect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
    5446                 :            :   }
    5447                 :            : 
    5448                 :            :   // assign new dependencies
    5449                 :          0 :   if ( mDataProvider )
    5450                 :          0 :     mDependencies = mDataProvider->dependencies() + deps;
    5451                 :            :   else
    5452                 :          0 :     mDependencies = deps;
    5453                 :          0 :   emit dependenciesChanged();
    5454                 :            : 
    5455                 :            :   // connect to new layers
    5456                 :          0 :   for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
    5457                 :            :   {
    5458                 :          0 :     QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
    5459                 :          0 :     if ( !lyr )
    5460                 :          0 :       continue;
    5461                 :          0 :     connect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
    5462                 :          0 :     connect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
    5463                 :          0 :     connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
    5464                 :          0 :     connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
    5465                 :          0 :     connect( lyr, &QgsVectorLayer::repaintRequested, this, &QgsVectorLayer::triggerRepaint );
    5466                 :          0 :     connect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
    5467                 :            :   }
    5468                 :            : 
    5469                 :            :   // if new layers are present, emit a data change
    5470                 :          0 :   if ( ! toAdd.isEmpty() )
    5471                 :          0 :     emitDataChanged();
    5472                 :            : 
    5473                 :            :   return true;
    5474                 :          0 : }
    5475                 :            : 
    5476                 :          0 : QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
    5477                 :            : {
    5478                 :          0 :   if ( fieldIndex < 0 || fieldIndex >= mFields.count() || !mDataProvider )
    5479                 :          0 :     return QgsFieldConstraints::Constraints();
    5480                 :            : 
    5481                 :          0 :   QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
    5482                 :            : 
    5483                 :            :   // make sure provider constraints are always present!
    5484                 :          0 :   if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
    5485                 :            :   {
    5486                 :          0 :     constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
    5487                 :          0 :   }
    5488                 :            : 
    5489                 :          0 :   return constraints;
    5490                 :          0 : }
    5491                 :            : 
    5492                 :          0 : QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
    5493                 :            : {
    5494                 :          0 :   QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
    5495                 :            : 
    5496                 :          0 :   if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
    5497                 :          0 :     return m;
    5498                 :            : 
    5499                 :          0 :   QString name = mFields.at( fieldIndex ).name();
    5500                 :            : 
    5501                 :          0 :   QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
    5502                 :          0 :   for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
    5503                 :            :   {
    5504                 :          0 :     if ( conIt.key().first == name )
    5505                 :            :     {
    5506                 :          0 :       m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
    5507                 :          0 :     }
    5508                 :          0 :   }
    5509                 :            : 
    5510                 :          0 :   return m;
    5511                 :          0 : }
    5512                 :            : 
    5513                 :          0 : void QgsVectorLayer::setFieldConstraint( int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength )
    5514                 :            : {
    5515                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5516                 :          0 :     return;
    5517                 :            : 
    5518                 :          0 :   QString name = mFields.at( index ).name();
    5519                 :            : 
    5520                 :            :   // add constraint to existing constraints
    5521                 :          0 :   QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
    5522                 :          0 :   constraints |= constraint;
    5523                 :          0 :   mFieldConstraints.insert( name, constraints );
    5524                 :            : 
    5525                 :          0 :   mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
    5526                 :            : 
    5527                 :          0 :   updateFields();
    5528                 :          0 : }
    5529                 :            : 
    5530                 :          0 : void QgsVectorLayer::removeFieldConstraint( int index, QgsFieldConstraints::Constraint constraint )
    5531                 :            : {
    5532                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5533                 :          0 :     return;
    5534                 :            : 
    5535                 :          0 :   QString name = mFields.at( index ).name();
    5536                 :            : 
    5537                 :            :   // remove constraint from existing constraints
    5538                 :          0 :   QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
    5539                 :          0 :   constraints &= ~constraint;
    5540                 :          0 :   mFieldConstraints.insert( name, constraints );
    5541                 :            : 
    5542                 :          0 :   mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
    5543                 :            : 
    5544                 :          0 :   updateFields();
    5545                 :          0 : }
    5546                 :            : 
    5547                 :          0 : QString QgsVectorLayer::constraintExpression( int index ) const
    5548                 :            : {
    5549                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5550                 :          0 :     return QString();
    5551                 :            : 
    5552                 :          0 :   return mFields.at( index ).constraints().constraintExpression();
    5553                 :          0 : }
    5554                 :            : 
    5555                 :          0 : QString QgsVectorLayer::constraintDescription( int index ) const
    5556                 :            : {
    5557                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5558                 :          0 :     return QString();
    5559                 :            : 
    5560                 :          0 :   return mFields.at( index ).constraints().constraintDescription();
    5561                 :          0 : }
    5562                 :            : 
    5563                 :          0 : void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
    5564                 :            : {
    5565                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5566                 :          0 :     return;
    5567                 :            : 
    5568                 :          0 :   if ( expression.isEmpty() )
    5569                 :            :   {
    5570                 :          0 :     mFieldConstraintExpressions.remove( mFields.at( index ).name() );
    5571                 :          0 :   }
    5572                 :            :   else
    5573                 :            :   {
    5574                 :          0 :     mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
    5575                 :            :   }
    5576                 :          0 :   updateFields();
    5577                 :          0 : }
    5578                 :            : 
    5579                 :          0 : void QgsVectorLayer::setFieldConfigurationFlags( int index, QgsField::ConfigurationFlags flags )
    5580                 :            : {
    5581                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5582                 :          0 :     return;
    5583                 :            : 
    5584                 :          0 :   mFieldConfigurationFlags.insert( mFields.at( index ).name(), flags );
    5585                 :          0 :   updateFields();
    5586                 :          0 : }
    5587                 :            : 
    5588                 :          0 : void QgsVectorLayer::setFieldConfigurationFlag( int index, QgsField::ConfigurationFlag flag, bool active )
    5589                 :            : {
    5590                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5591                 :          0 :     return;
    5592                 :          0 :   QgsField::ConfigurationFlags flags = mFields.at( index ).configurationFlags();
    5593                 :          0 :   flags.setFlag( flag, active );
    5594                 :          0 :   setFieldConfigurationFlags( index, flags );
    5595                 :          0 : }
    5596                 :            : 
    5597                 :          0 : QgsField::ConfigurationFlags QgsVectorLayer::fieldConfigurationFlags( int index ) const
    5598                 :            : {
    5599                 :            : 
    5600                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5601                 :          0 :     return QgsField::ConfigurationFlag::None;
    5602                 :            : 
    5603                 :          0 :   return mFields.at( index ).configurationFlags();
    5604                 :          0 : }
    5605                 :            : 
    5606                 :          0 : void QgsVectorLayer::setEditorWidgetSetup( int index, const QgsEditorWidgetSetup &setup )
    5607                 :            : {
    5608                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5609                 :          0 :     return;
    5610                 :            : 
    5611                 :          0 :   if ( setup.isNull() )
    5612                 :          0 :     mFieldWidgetSetups.remove( mFields.at( index ).name() );
    5613                 :            :   else
    5614                 :          0 :     mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
    5615                 :          0 :   updateFields();
    5616                 :          0 : }
    5617                 :            : 
    5618                 :          0 : QgsEditorWidgetSetup QgsVectorLayer::editorWidgetSetup( int index ) const
    5619                 :            : {
    5620                 :            : 
    5621                 :          0 :   if ( index < 0 || index >= mFields.count() )
    5622                 :          0 :     return QgsEditorWidgetSetup();
    5623                 :            : 
    5624                 :          0 :   return mFields.at( index ).editorWidgetSetup();
    5625                 :          0 : }
    5626                 :            : 
    5627                 :          0 : QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
    5628                 :            : {
    5629                 :          0 :   QgsAbstractVectorLayerLabeling *labeling = nullptr;
    5630                 :          0 :   if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
    5631                 :            :   {
    5632                 :          0 :     if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() )
    5633                 :            :     {
    5634                 :            :       // try to load from custom properties
    5635                 :          0 :       QgsPalLayerSettings settings;
    5636                 :          0 :       settings.readFromLayerCustomProperties( this );
    5637                 :          0 :       labeling = new QgsVectorLayerSimpleLabeling( settings );
    5638                 :          0 :     }
    5639                 :            : 
    5640                 :            :     // also clear old-style labeling config
    5641                 :          0 :     removeCustomProperty( QStringLiteral( "labeling" ) );
    5642                 :          0 :     const auto constCustomPropertyKeys = customPropertyKeys();
    5643                 :          0 :     for ( const QString &key : constCustomPropertyKeys )
    5644                 :            :     {
    5645                 :          0 :       if ( key.startsWith( QLatin1String( "labeling/" ) ) )
    5646                 :          0 :         removeCustomProperty( key );
    5647                 :            :     }
    5648                 :          0 :   }
    5649                 :            : 
    5650                 :          0 :   return labeling;
    5651                 :          0 : }
    5652                 :            : 
    5653                 :          0 : bool QgsVectorLayer::allowCommit() const
    5654                 :            : {
    5655                 :          0 :   return mAllowCommit;
    5656                 :            : }
    5657                 :            : 
    5658                 :          0 : void QgsVectorLayer::setAllowCommit( bool allowCommit )
    5659                 :            : {
    5660                 :          0 :   if ( mAllowCommit == allowCommit )
    5661                 :          0 :     return;
    5662                 :            : 
    5663                 :          0 :   mAllowCommit = allowCommit;
    5664                 :          0 :   emit allowCommitChanged();
    5665                 :          0 : }
    5666                 :            : 
    5667                 :          0 : QgsGeometryOptions *QgsVectorLayer::geometryOptions() const
    5668                 :            : {
    5669                 :          0 :   return mGeometryOptions.get();
    5670                 :            : }
    5671                 :            : 
    5672                 :          0 : void QgsVectorLayer::setReadExtentFromXml( bool readExtentFromXml )
    5673                 :            : {
    5674                 :          0 :   mReadExtentFromXml = readExtentFromXml;
    5675                 :          0 : }
    5676                 :            : 
    5677                 :          0 : bool QgsVectorLayer::readExtentFromXml() const
    5678                 :            : {
    5679                 :          0 :   return mReadExtentFromXml;
    5680                 :            : }
    5681                 :            : 
    5682                 :          0 : void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
    5683                 :            : {
    5684                 :          0 :   QgsTransaction *tr = dataProvider()->transaction();
    5685                 :          0 :   if ( tr && mEditBuffer )
    5686                 :            :   {
    5687                 :          0 :     qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
    5688                 :          0 :   }
    5689                 :          0 : }
    5690                 :            : 
    5691                 :          0 : QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers( bool includeAuxiliaryLayers ) const
    5692                 :            : {
    5693                 :          0 :   QList<QgsVectorLayer *> layers;
    5694                 :          0 :   QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
    5695                 :          0 :   for ( i = mHandledFeatures.begin(); i != mHandledFeatures.end(); ++i )
    5696                 :            :   {
    5697                 :          0 :     if ( includeAuxiliaryLayers || !qobject_cast< QgsAuxiliaryLayer * >( i.key() ) )
    5698                 :          0 :       layers.append( i.key() );
    5699                 :          0 :   }
    5700                 :          0 :   return layers;
    5701                 :          0 : }
    5702                 :            : 
    5703                 :          0 : QgsFeatureIds QgsVectorLayer::DeleteContext::handledFeatures( QgsVectorLayer *layer ) const
    5704                 :            : {
    5705                 :          0 :   return mHandledFeatures[layer];
    5706                 :            : }

Generated by: LCOV version 1.14