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