QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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  for ( QgsFeatureId fid : std::as_const( selectedFeatures ) )
1197  {
1198  deleted += deleteFeature( fid, context ); // removes from selection
1199  }
1200 
1201  triggerRepaint();
1202  updateExtents();
1203 
1204  if ( deletedCount )
1205  {
1206  *deletedCount = deleted;
1207  }
1208 
1209  return deleted == count;
1210 }
1211 
1212 static const QgsPointSequence vectorPointXY2pointSequence( const QVector<QgsPointXY> &points )
1213 {
1214  QgsPointSequence pts;
1215  pts.reserve( points.size() );
1216  QVector<QgsPointXY>::const_iterator it = points.constBegin();
1217  while ( it != points.constEnd() )
1218  {
1219  pts.append( QgsPoint( *it ) );
1220  ++it;
1221  }
1222  return pts;
1223 }
1224 Qgis::GeometryOperationResult QgsVectorLayer::addRing( const QVector<QgsPointXY> &ring, QgsFeatureId *featureId )
1225 {
1226  return addRing( vectorPointXY2pointSequence( ring ), featureId );
1227 }
1228 
1230 {
1231  if ( !isValid() || !mEditBuffer || !mDataProvider )
1233 
1234  QgsVectorLayerEditUtils utils( this );
1236 
1237  //first try with selected features
1238  if ( !mSelectedFeatureIds.isEmpty() )
1239  {
1240  result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1241  }
1242 
1244  {
1245  //try with all intersecting features
1246  result = utils.addRing( ring, QgsFeatureIds(), featureId );
1247  }
1248 
1249  return result;
1250 }
1251 
1253 {
1254  if ( !isValid() || !mEditBuffer || !mDataProvider )
1255  {
1256  delete ring;
1258  }
1259 
1260  if ( !ring )
1261  {
1263  }
1264 
1265  if ( !ring->isClosed() )
1266  {
1267  delete ring;
1269  }
1270 
1271  QgsVectorLayerEditUtils utils( this );
1273 
1274  //first try with selected features
1275  if ( !mSelectedFeatureIds.isEmpty() )
1276  {
1277  result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), mSelectedFeatureIds, featureId );
1278  }
1279 
1281  {
1282  //try with all intersecting features
1283  result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), QgsFeatureIds(), featureId );
1284  }
1285 
1286  delete ring;
1287  return result;
1288 }
1289 
1290 Qgis::GeometryOperationResult QgsVectorLayer::addPart( const QList<QgsPointXY> &points )
1291 {
1292  QgsPointSequence pts;
1293  pts.reserve( points.size() );
1294  for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd() ; ++it )
1295  {
1296  pts.append( QgsPoint( *it ) );
1297  }
1298  return addPart( pts );
1299 }
1300 
1301 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1302 Qgis::GeometryOperationResult QgsVectorLayer::addPart( const QVector<QgsPointXY> &points )
1303 {
1304  return addPart( vectorPointXY2pointSequence( points ) );
1305 }
1306 #endif
1307 
1309 {
1310  if ( !isValid() || !mEditBuffer || !mDataProvider )
1312 
1313  //number of selected features must be 1
1314 
1315  if ( mSelectedFeatureIds.empty() )
1316  {
1317  QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1319  }
1320  else if ( mSelectedFeatureIds.size() > 1 )
1321  {
1322  QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1324  }
1325 
1326  QgsVectorLayerEditUtils utils( this );
1327  Qgis::GeometryOperationResult result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1328 
1330  updateExtents();
1331  return result;
1332 }
1333 
1335 {
1336  if ( !isValid() || !mEditBuffer || !mDataProvider )
1338 
1339  //number of selected features must be 1
1340 
1341  if ( mSelectedFeatureIds.empty() )
1342  {
1343  QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1345  }
1346  else if ( mSelectedFeatureIds.size() > 1 )
1347  {
1348  QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1350  }
1351 
1352  QgsVectorLayerEditUtils utils( this );
1353  Qgis::GeometryOperationResult result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1354 
1356  updateExtents();
1357  return result;
1358 }
1359 
1360 // TODO QGIS 4.0 -- this should return Qgis::GeometryOperationResult, not int
1361 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1362 {
1363  if ( !isValid() || !mEditBuffer || !mDataProvider )
1364  return static_cast< int >( Qgis::GeometryOperationResult::LayerNotEditable );
1365 
1366  QgsVectorLayerEditUtils utils( this );
1367  int result = utils.translateFeature( featureId, dx, dy );
1368 
1369  if ( result == static_cast< int >( Qgis::GeometryOperationResult::Success ) )
1370  updateExtents();
1371  return result;
1372 }
1373 
1374 Qgis::GeometryOperationResult QgsVectorLayer::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1375 {
1376  return splitParts( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1377 }
1378 
1380 {
1381  if ( !isValid() || !mEditBuffer || !mDataProvider )
1383 
1384  QgsVectorLayerEditUtils utils( this );
1385  return utils.splitParts( splitLine, topologicalEditing );
1386 }
1387 
1388 Qgis::GeometryOperationResult QgsVectorLayer::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1389 {
1390  return splitFeatures( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1391 }
1392 
1394 {
1395  QgsLineString splitLineString( splitLine );
1396  QgsPointSequence topologyTestPoints;
1397  bool preserveCircular = false;
1398  return splitFeatures( &splitLineString, topologyTestPoints, preserveCircular, topologicalEditing );
1399 }
1400 
1401 Qgis::GeometryOperationResult QgsVectorLayer::splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints, bool preserveCircular, bool topologicalEditing )
1402 {
1403  if ( !isValid() || !mEditBuffer || !mDataProvider )
1405 
1406  QgsVectorLayerEditUtils utils( this );
1407  return utils.splitFeatures( curve, topologyTestPoints, preserveCircular, topologicalEditing );
1408 }
1409 
1411 {
1412  if ( !isValid() || !mEditBuffer || !mDataProvider )
1413  return -1;
1414 
1415  QgsVectorLayerEditUtils utils( this );
1416  return utils.addTopologicalPoints( geom );
1417 }
1418 
1420 {
1421  return addTopologicalPoints( QgsPoint( p ) );
1422 }
1423 
1425 {
1426  if ( !isValid() || !mEditBuffer || !mDataProvider )
1427  return -1;
1428 
1429  QgsVectorLayerEditUtils utils( this );
1430  return utils.addTopologicalPoints( p );
1431 }
1432 
1434 {
1435  if ( !mValid || !mEditBuffer || !mDataProvider )
1436  return -1;
1437 
1438  QgsVectorLayerEditUtils utils( this );
1439  return utils.addTopologicalPoints( ps );
1440 }
1441 
1443 {
1444  if ( mLabeling == labeling )
1445  return;
1446 
1447  delete mLabeling;
1448  mLabeling = labeling;
1449 }
1450 
1452 {
1453  if ( !isValid() || !mDataProvider )
1454  {
1455  return false;
1456  }
1457 
1458  // allow editing if provider supports any of the capabilities
1459  if ( !supportsEditing() )
1460  {
1461  return false;
1462  }
1463 
1464  if ( mEditBuffer )
1465  {
1466  // editing already underway
1467  return false;
1468  }
1469 
1470  emit beforeEditingStarted();
1471 
1472  mDataProvider->enterUpdateMode();
1473 
1474  if ( mDataProvider->transaction() )
1475  {
1476  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1477 
1478  connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
1479  }
1480  else
1481  {
1482  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1483  }
1484  // forward signals
1485  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
1486  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
1487  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1489  connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
1500 
1501  updateFields();
1502 
1503  emit editingStarted();
1504 
1505  return true;
1506 }
1507 
1509 {
1510  if ( mDataProvider )
1511  mDataProvider->setTransformContext( transformContext );
1512 }
1513 
1515 {
1516  return mDataProvider ? mDataProvider->hasSpatialIndex() : QgsFeatureSource::SpatialIndexUnknown;
1517 }
1518 
1520 {
1521  if ( mRenderer )
1522  if ( !mRenderer->accept( visitor ) )
1523  return false;
1524 
1525  if ( mLabeling )
1526  if ( !mLabeling->accept( visitor ) )
1527  return false;
1528 
1529  return true;
1530 }
1531 
1532 bool QgsVectorLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1533 {
1534  QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsVectorLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1535 
1536  //process provider key
1537  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1538 
1539  if ( pkeyNode.isNull() )
1540  {
1541  mProviderKey.clear();
1542  }
1543  else
1544  {
1545  QDomElement pkeyElt = pkeyNode.toElement();
1546  mProviderKey = pkeyElt.text();
1547  }
1548 
1549  // determine type of vector layer
1550  if ( !mProviderKey.isNull() )
1551  {
1552  // if the provider string isn't empty, then we successfully
1553  // got the stored provider
1554  }
1555  else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
1556  {
1557  mProviderKey = QStringLiteral( "postgres" );
1558  }
1559  else
1560  {
1561  mProviderKey = QStringLiteral( "ogr" );
1562  }
1563 
1564  QgsDataProvider::ProviderOptions options { context.transformContext() };
1565  QgsDataProvider::ReadFlags flags;
1567  {
1569  }
1570  if ( ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) || !setDataProvider( mProviderKey, options, flags ) )
1571  {
1573  {
1574  QgsDebugMsg( QStringLiteral( "Could not set data provider for layer %1" ).arg( publicSource() ) );
1575  }
1576  const QDomElement elem = layer_node.toElement();
1577 
1578  // for invalid layer sources, we fallback to stored wkbType if available
1579  if ( elem.hasAttribute( QStringLiteral( "wkbType" ) ) )
1580  mWkbType = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "wkbType" ) ), mWkbType );
1581  }
1582 
1583  QDomElement pkeyElem = pkeyNode.toElement();
1584  if ( !pkeyElem.isNull() )
1585  {
1586  QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1587  if ( mDataProvider && !encodingString.isEmpty() )
1588  {
1589  mDataProvider->setEncoding( encodingString );
1590  }
1591  }
1592 
1593  // load vector joins - does not resolve references to layers yet
1594  mJoinBuffer->readXml( layer_node );
1595 
1596  updateFields();
1597 
1598  // If style doesn't include a legend, we'll need to make a default one later...
1599  mSetLegendFromStyle = false;
1600 
1601  QString errorMsg;
1602  if ( !readSymbology( layer_node, errorMsg, context ) )
1603  {
1604  return false;
1605  }
1606 
1607  readStyleManager( layer_node );
1608 
1609  QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1610  QDomNodeList depsNodes = depsNode.childNodes();
1611  QSet<QgsMapLayerDependency> sources;
1612  for ( int i = 0; i < depsNodes.count(); i++ )
1613  {
1614  QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1615  sources << QgsMapLayerDependency( source );
1616  }
1617  setDependencies( sources );
1618 
1619  if ( !mSetLegendFromStyle )
1621 
1622  // read extent
1624  {
1625  mReadExtentFromXml = true;
1626  }
1627  if ( mReadExtentFromXml )
1628  {
1629  const QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1630  if ( !extentNode.isNull() )
1631  {
1632  mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1633  }
1634  }
1635 
1636  // auxiliary layer
1637  const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
1638  const QDomElement asElem = asNode.toElement();
1639  if ( !asElem.isNull() )
1640  {
1641  mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
1642  }
1643 
1644  // QGIS Server WMS Dimensions
1645  mServerProperties->readXml( layer_node );
1646 
1647  return isValid(); // should be true if read successfully
1648 
1649 } // void QgsVectorLayer::readXml
1650 
1651 
1652 void QgsVectorLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider,
1653  const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1654 {
1656 
1657  mDataSource = dataSource;
1658  setName( baseName );
1659  setDataProvider( provider, options, flags );
1660 
1661  if ( !isValid() )
1662  {
1663  return;
1664  }
1665 
1666  // Always set crs
1668 
1669  bool loadDefaultStyleFlag = false;
1671  {
1672  loadDefaultStyleFlag = true;
1673  }
1674 
1675  // reset style if loading default style, style is missing, or geometry type is has changed (and layer is valid)
1676  if ( !renderer() || !legend() || ( isValid() && geomType != geometryType() ) || loadDefaultStyleFlag )
1677  {
1678  std::unique_ptr< QgsScopedRuntimeProfile > profile;
1679  if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
1680  profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Load layer style" ), QStringLiteral( "projectload" ) );
1681 
1682  bool defaultLoadedFlag = false;
1683 
1684  // defer style changed signal until we've set the renderer, labeling, everything.
1685  // we don't want multiple signals!
1686  ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
1687 
1688  if ( loadDefaultStyleFlag && isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1689  {
1690  // first try to create a renderer directly from the data provider
1691  std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1692  if ( defaultRenderer )
1693  {
1694  defaultLoadedFlag = true;
1695  setRenderer( defaultRenderer.release() );
1696  }
1697  }
1698 
1699  // need to check whether the default style included a legend, and if not, we need to make a default legend
1700  // later...
1701  mSetLegendFromStyle = false;
1702 
1703  // else check if there is a default style / propertysheet defined
1704  // for this layer and if so apply it
1705  if ( !defaultLoadedFlag && loadDefaultStyleFlag )
1706  {
1707  loadDefaultStyle( defaultLoadedFlag );
1708  }
1709 
1710  // if the default style failed to load or was disabled use some very basic defaults
1711  if ( !defaultLoadedFlag && isSpatial() )
1712  {
1713  // add single symbol renderer
1715  }
1716 
1717  if ( !mSetLegendFromStyle )
1719 
1720  if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
1721  {
1722  std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
1723  if ( defaultLabeling )
1724  {
1725  setLabeling( defaultLabeling.release() );
1726  setLabelsEnabled( true );
1727  }
1728  }
1729 
1730  styleChangedSignalBlocker.release();
1731  emitStyleChanged();
1732  }
1733 }
1734 
1735 QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
1736 {
1737  if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1738  {
1739  // first try to create a renderer directly from the data provider
1740  std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1741  if ( defaultRenderer )
1742  {
1743  resultFlag = true;
1744  setRenderer( defaultRenderer.release() );
1745  return QString();
1746  }
1747  }
1748 
1749  return QgsMapLayer::loadDefaultStyle( resultFlag );
1750 }
1751 
1752 
1753 bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1754 {
1755  mProviderKey = provider;
1756  delete mDataProvider;
1757 
1758  // For Postgres provider primary key unicity is tested at construction time,
1759  // so it has to be set before initializing the provider,
1760  // this manipulation is necessary to preserve default behavior when
1761  // "trust layer metadata" project level option is set and checkPrimaryKeyUnicity
1762  // was not explicitly passed in the uri
1763  if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
1764  {
1765  const QString checkUnicityKey { QStringLiteral( "checkPrimaryKeyUnicity" ) };
1767  if ( ! uri.hasParam( checkUnicityKey ) )
1768  {
1769  uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
1770  mDataSource = uri.uri( false );
1771  }
1772  }
1773 
1774  std::unique_ptr< QgsScopedRuntimeProfile > profile;
1775  if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
1776  profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
1777 
1778  mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, mDataSource, options, flags ) );
1779  if ( !mDataProvider )
1780  {
1781  setValid( false );
1782  QgsDebugMsgLevel( QStringLiteral( "Unable to get data provider" ), 2 );
1783  return false;
1784  }
1785 
1786  mDataProvider->setParent( this );
1787  connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1788 
1789  QgsDebugMsgLevel( QStringLiteral( "Instantiated the data provider plugin" ), 2 );
1790 
1791  setValid( mDataProvider->isValid() );
1792  if ( !isValid() )
1793  {
1794  QgsDebugMsgLevel( QStringLiteral( "Invalid provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1795  return false;
1796  }
1797 
1798  if ( profile )
1799  profile->switchTask( tr( "Read layer metadata" ) );
1800  if ( mDataProvider->capabilities() & QgsVectorDataProvider::ReadLayerMetadata )
1801  {
1802  // we combine the provider metadata with the layer's existing metadata, so as not to reset any user customizations to the metadata
1803  // back to the default if a layer's data source is changed
1804  QgsLayerMetadata newMetadata = mDataProvider->layerMetadata();
1805  // this overwrites the provider metadata with any properties which are non-empty from the existing layer metadata
1806  newMetadata.combine( &mMetadata );
1807 
1808  setMetadata( newMetadata );
1809  QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
1810  }
1811 
1812  // TODO: Check if the provider has the capability to send fullExtentCalculated
1813  connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
1814 
1815  // get and store the feature type
1816  mWkbType = mDataProvider->wkbType();
1817 
1818  // before we update the layer fields from the provider, we first copy any default set alias and
1819  // editor widget config from the data provider fields, if present
1820  const QgsFields providerFields = mDataProvider->fields();
1821  for ( const QgsField &field : providerFields )
1822  {
1823  // we only copy defaults from the provider if we aren't overriding any configuration made in the layer
1824  if ( !field.editorWidgetSetup().isNull() && mFieldWidgetSetups.value( field.name() ).isNull() )
1825  {
1826  mFieldWidgetSetups[ field.name() ] = field.editorWidgetSetup();
1827  }
1828  if ( !field.alias().isEmpty() && mAttributeAliasMap.value( field.name() ).isEmpty() )
1829  {
1830  mAttributeAliasMap[ field.name() ] = field.alias();
1831  }
1832  }
1833 
1834  if ( profile )
1835  profile->switchTask( tr( "Read layer fields" ) );
1836  updateFields();
1837 
1838  if ( mProviderKey == QLatin1String( "postgres" ) )
1839  {
1840  // update datasource from data provider computed one
1841  mDataSource = mDataProvider->dataSourceUri( false );
1842 
1843  QgsDebugMsgLevel( QStringLiteral( "Beautifying layer name %1" ).arg( name() ), 3 );
1844 
1845  // adjust the display name for postgres layers
1846  const QRegularExpression reg( R"lit("[^"]+"\."([^"] + )"( \‍([^)]+\))?)lit" );
1847  const QRegularExpressionMatch match = reg.match( name() );
1848  if ( match.hasMatch() )
1849  {
1850  QStringList stuff = match.capturedTexts();
1851  QString lName = stuff[1];
1852 
1853  const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
1854 
1855  QMap<QString, QgsMapLayer *>::const_iterator it;
1856  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1857  ;
1858 
1859  if ( it != layers.constEnd() && stuff.size() > 2 )
1860  {
1861  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1862  }
1863 
1864  if ( !lName.isEmpty() )
1865  setName( lName );
1866  }
1867  QgsDebugMsgLevel( QStringLiteral( "Beautified layer name %1" ).arg( name() ), 3 );
1868  }
1869  else if ( mProviderKey == QLatin1String( "osm" ) )
1870  {
1871  // make sure that the "observer" has been removed from URI to avoid crashes
1872  mDataSource = mDataProvider->dataSourceUri();
1873  }
1874  else if ( provider == QLatin1String( "ogr" ) )
1875  {
1876  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1877  mDataSource = mDataProvider->dataSourceUri();
1878  if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1879  mDataSource.chop( 10 );
1880  }
1881  else if ( provider == QLatin1String( "memory" ) )
1882  {
1883  // required so that source differs between memory layers
1884  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1885  }
1886 
1887  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::emitDataChanged );
1888  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
1889 
1890  return true;
1891 } // QgsVectorLayer:: setDataProvider
1892 
1893 
1894 
1895 
1896 /* virtual */
1897 bool QgsVectorLayer::writeXml( QDomNode &layer_node,
1898  QDomDocument &document,
1899  const QgsReadWriteContext &context ) const
1900 {
1901  // first get the layer element so that we can append the type attribute
1902 
1903  QDomElement mapLayerNode = layer_node.toElement();
1904 
1905  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1906  {
1907  QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1908  return false;
1909  }
1910 
1911  mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::VectorLayer ) );
1912 
1913  // set the geometry type
1914  mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1915  mapLayerNode.setAttribute( QStringLiteral( "wkbType" ), qgsEnumValueToKey( wkbType() ) );
1916 
1917  // add provider node
1918  if ( mDataProvider )
1919  {
1920  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1921  provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1922  QDomText providerText = document.createTextNode( providerType() );
1923  provider.appendChild( providerText );
1924  layer_node.appendChild( provider );
1925  }
1926 
1927  //save joins
1928  mJoinBuffer->writeXml( layer_node, document );
1929 
1930  // dependencies
1931  QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1932  const auto constDependencies = dependencies();
1933  for ( const QgsMapLayerDependency &dep : constDependencies )
1934  {
1935  if ( dep.type() != QgsMapLayerDependency::PresenceDependency )
1936  continue;
1937  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1938  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1939  dependenciesElement.appendChild( depElem );
1940  }
1941  layer_node.appendChild( dependenciesElement );
1942 
1943  // change dependencies
1944  QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1945  for ( const QgsMapLayerDependency &dep : constDependencies )
1946  {
1947  if ( dep.type() != QgsMapLayerDependency::DataDependency )
1948  continue;
1949  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1950  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1951  dataDependenciesElement.appendChild( depElem );
1952  }
1953  layer_node.appendChild( dataDependenciesElement );
1954 
1955  // save expression fields
1956  mExpressionFieldBuffer->writeXml( layer_node, document );
1957 
1958  writeStyleManager( layer_node, document );
1959 
1960  // auxiliary layer
1961  QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
1962  if ( mAuxiliaryLayer )
1963  {
1964  const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
1965  asElem.setAttribute( QStringLiteral( "key" ), pkField );
1966  }
1967  layer_node.appendChild( asElem );
1968 
1969  // save QGIS Server properties (WMS Dimension, metadata URLS...)
1970  mServerProperties->writeXml( layer_node, document );
1971 
1972  // renderer specific settings
1973  QString errorMsg;
1974  return writeSymbology( layer_node, document, errorMsg, context );
1975 }
1976 
1977 QString QgsVectorLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1978 {
1979  QString src( source );
1980 
1981  // TODO: what about postgres, mysql and others, they should not go through writePath()
1982  if ( providerType() == QLatin1String( "spatialite" ) )
1983  {
1984  QgsDataSourceUri uri( src );
1985  QString database = context.pathResolver().writePath( uri.database() );
1986  uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
1987  src = uri.uri();
1988  }
1989  else if ( providerType() == QLatin1String( "ogr" ) )
1990  {
1991  QStringList theURIParts = src.split( '|' );
1992  theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
1993  src = theURIParts.join( QLatin1Char( '|' ) );
1994  }
1995  else if ( providerType() == QLatin1String( "gpx" ) )
1996  {
1997  QStringList theURIParts = src.split( '?' );
1998  theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
1999  src = theURIParts.join( QLatin1Char( '?' ) );
2000  }
2001  else if ( providerType() == QLatin1String( "delimitedtext" ) )
2002  {
2003  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2004  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
2005  urlDest.setQuery( urlSource.query() );
2006  src = QString::fromLatin1( urlDest.toEncoded() );
2007  }
2008  else if ( providerType() == QLatin1String( "memory" ) )
2009  {
2010  // Refetch the source from the provider, because adding fields actually changes the source for this provider.
2011  src = dataProvider()->dataSourceUri();
2012  }
2013  else if ( providerType() == QLatin1String( "virtual" ) )
2014  {
2015  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2016  QStringList theURIParts;
2017 
2018  QUrlQuery query = QUrlQuery( urlSource.query() );
2019  QList<QPair<QString, QString> > queryItems = query.queryItems();
2020 
2021  for ( int i = 0; i < queryItems.size(); i++ )
2022  {
2023  QString key = queryItems.at( i ).first;
2024  QString value = queryItems.at( i ).second;
2025  if ( key == QLatin1String( "layer" ) )
2026  {
2027  // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
2028  theURIParts = value.split( ':' );
2029  theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2030 
2031  if ( theURIParts[0] == QLatin1String( "delimitedtext" ) )
2032  {
2033  QUrl urlSource = QUrl( theURIParts[1] );
2034  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
2035  urlDest.setQuery( urlSource.query() );
2036  theURIParts[1] = QUrl::toPercentEncoding( urlDest.toString(), QByteArray( "" ), QByteArray( ":" ) );
2037  }
2038  else
2039  {
2040  theURIParts[1] = context.pathResolver().writePath( theURIParts[1] );
2041  theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2042  }
2043 
2044  queryItems[i].second = theURIParts.join( QLatin1Char( ':' ) ) ;
2045  }
2046  }
2047 
2048  query.setQueryItems( queryItems );
2049 
2050  QUrl urlDest = QUrl( urlSource );
2051  urlDest.setQuery( query.query() );
2052  src = QString::fromLatin1( urlDest.toEncoded() );
2053  }
2054  else
2055  {
2056  src = context.pathResolver().writePath( src );
2057  }
2058 
2059  return src;
2060 }
2061 
2062 QString QgsVectorLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2063 {
2064  QString src( source );
2065 
2066  if ( provider == QLatin1String( "spatialite" ) )
2067  {
2068  QgsDataSourceUri uri( src );
2069  uri.setDatabase( context.pathResolver().readPath( uri.database() ) );
2070  src = uri.uri();
2071  }
2072  else if ( provider == QLatin1String( "ogr" ) )
2073  {
2074  QStringList theURIParts = src.split( '|' );
2075  theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
2076  src = theURIParts.join( QLatin1Char( '|' ) );
2077  }
2078  else if ( provider == QLatin1String( "gpx" ) )
2079  {
2080  QStringList theURIParts = src.split( '?' );
2081  theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
2082  src = theURIParts.join( QLatin1Char( '?' ) );
2083  }
2084  else if ( provider == QLatin1String( "delimitedtext" ) )
2085  {
2086  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2087 
2088  if ( !src.startsWith( QLatin1String( "file:" ) ) )
2089  {
2090  QUrl file = QUrl::fromLocalFile( src.left( src.indexOf( '?' ) ) );
2091  urlSource.setScheme( QStringLiteral( "file" ) );
2092  urlSource.setPath( file.path() );
2093  }
2094 
2095  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
2096  urlDest.setQuery( urlSource.query() );
2097  src = QString::fromLatin1( urlDest.toEncoded() );
2098  }
2099  else if ( provider == QLatin1String( "virtual" ) )
2100  {
2101  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2102  QStringList theURIParts;
2103 
2104  QUrlQuery query = QUrlQuery( urlSource.query() );
2105  QList<QPair<QString, QString> > queryItems = query.queryItems();
2106 
2107  for ( int i = 0; i < queryItems.size(); i++ )
2108  {
2109  QString key = queryItems.at( i ).first;
2110  QString value = queryItems.at( i ).second;
2111  if ( key == QLatin1String( "layer" ) )
2112  {
2113  // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
2114  theURIParts = value.split( ':' );
2115  theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2116 
2117  if ( theURIParts[0] == QLatin1String( "delimitedtext" ) )
2118  {
2119  QUrl urlSource = QUrl( theURIParts[1] );
2120 
2121  if ( !theURIParts[1].startsWith( QLatin1String( "file:" ) ) )
2122  {
2123  QUrl file = QUrl::fromLocalFile( theURIParts[1].left( theURIParts[1].indexOf( '?' ) ) );
2124  urlSource.setScheme( QStringLiteral( "file" ) );
2125  urlSource.setPath( file.path() );
2126  }
2127 
2128  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
2129  urlDest.setQuery( urlSource.query() );
2130 
2131  theURIParts[1] = urlDest.toString();
2132  }
2133  else
2134  {
2135  theURIParts[1] = context.pathResolver().readPath( theURIParts[1] );
2136  }
2137 
2138  theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2139  queryItems[i].second = theURIParts.join( QLatin1Char( ':' ) ) ;
2140  }
2141  }
2142 
2143  query.setQueryItems( queryItems );
2144 
2145  QUrl urlDest = QUrl( urlSource );
2146  urlDest.setQuery( query.query() );
2147  src = QString::fromLatin1( urlDest.toEncoded() );
2148  }
2149  else
2150  {
2151  src = context.pathResolver().readPath( src );
2152  }
2153 
2154  return src;
2155 }
2156 
2157 
2158 
2160 {
2162  mJoinBuffer->resolveReferences( project );
2163 }
2164 
2165 
2166 bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage,
2167  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2168 {
2169  if ( categories.testFlag( Fields ) )
2170  {
2171  if ( !mExpressionFieldBuffer )
2172  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
2173  mExpressionFieldBuffer->readXml( layerNode );
2174 
2175  updateFields();
2176  }
2177 
2178  if ( categories.testFlag( Relations ) )
2179  {
2180  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Relations" ) );
2181 
2182  const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
2183 
2184  // Restore referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2185  QDomNodeList referencedLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencedLayers" ) );
2186  if ( referencedLayersNodeList.size() > 0 )
2187  {
2188  const QDomNodeList relationNodes { referencedLayersNodeList.at( 0 ).childNodes() };
2189  for ( int i = 0; i < relationNodes.length(); ++i )
2190  {
2191  const QDomElement relationElement = relationNodes.at( i ).toElement();
2192 
2193  mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referencing, relationElement, resolver ) );
2194  }
2195  }
2196 
2197  // Restore referencing layers: relations where "this" is the parent layer (the referenced part where the FK points to)
2198  QDomNodeList referencingLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencingLayers" ) );
2199  if ( referencingLayersNodeList.size() > 0 )
2200  {
2201  const QDomNodeList relationNodes { referencingLayersNodeList.at( 0 ).childNodes() };
2202  for ( int i = 0; i < relationNodes.length(); ++i )
2203  {
2204  const QDomElement relationElement = relationNodes.at( i ).toElement();
2205  mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referenced, relationElement, resolver ) );
2206  }
2207  }
2208  }
2209 
2210  QDomElement layerElement = layerNode.toElement();
2211 
2212  readCommonStyle( layerElement, context, categories );
2213 
2214  readStyle( layerNode, errorMessage, context, categories );
2215 
2216  if ( categories.testFlag( MapTips ) )
2217  mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
2218 
2219  if ( categories.testFlag( LayerConfiguration ) )
2220  mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
2221 
2222  // Try to migrate pre QGIS 3.0 display field property
2223  QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
2224  if ( mFields.lookupField( displayField ) < 0 )
2225  {
2226  // if it's not a field, it's a maptip
2227  if ( mMapTipTemplate.isEmpty() && categories.testFlag( MapTips ) )
2228  mMapTipTemplate = displayField;
2229  }
2230  else
2231  {
2232  if ( mDisplayExpression.isEmpty() && categories.testFlag( LayerConfiguration ) )
2233  mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
2234  }
2235 
2236  // process the attribute actions
2237  if ( categories.testFlag( Actions ) )
2238  mActions->readXml( layerNode );
2239 
2240  if ( categories.testFlag( Fields ) )
2241  {
2242  // IMPORTANT - we don't clear mAttributeAliasMap here, as it may contain aliases which are coming direct
2243  // from the data provider. Instead we leave any existing aliases and only overwrite them if the style
2244  // has a specific value for that field's alias
2245  QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
2246  if ( !aliasesNode.isNull() )
2247  {
2248  QDomElement aliasElem;
2249 
2250  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
2251  for ( int i = 0; i < aliasNodeList.size(); ++i )
2252  {
2253  aliasElem = aliasNodeList.at( i ).toElement();
2254 
2255  QString field;
2256  if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
2257  {
2258  field = aliasElem.attribute( QStringLiteral( "field" ) );
2259  }
2260  else
2261  {
2262  int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
2263 
2264  if ( index >= 0 && index < fields().count() )
2265  field = fields().at( index ).name();
2266  }
2267 
2268  QString alias;
2269 
2270  if ( !aliasElem.attribute( QStringLiteral( "name" ) ).isEmpty() )
2271  {
2272  //if it has alias
2273  alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral( "name" ) ) );
2274  QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + aliasElem.attribute( QStringLiteral( "name" ) ), 3 );
2275  }
2276  else
2277  {
2278  //if it has no alias, it should be the fields translation
2279  alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), field );
2280  QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + field, 3 );
2281  //if it gets the exact field value, there has been no translation (or not even translation loaded) - so no alias should be generated;
2282  if ( alias == aliasElem.attribute( QStringLiteral( "field" ) ) )
2283  alias.clear();
2284  }
2285 
2286  QgsDebugMsgLevel( "field " + field + " origalias " + aliasElem.attribute( QStringLiteral( "name" ) ) + " trans " + alias, 3 );
2287  mAttributeAliasMap.insert( field, alias );
2288  }
2289  }
2290 
2291  // default expressions
2292  mDefaultExpressionMap.clear();
2293  QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
2294  if ( !defaultsNode.isNull() )
2295  {
2296  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
2297  for ( int i = 0; i < defaultNodeList.size(); ++i )
2298  {
2299  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
2300 
2301  QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
2302  QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
2303  bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
2304  if ( field.isEmpty() || expression.isEmpty() )
2305  continue;
2306 
2307  mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
2308  }
2309  }
2310 
2311  // constraints
2312  mFieldConstraints.clear();
2313  mFieldConstraintStrength.clear();
2314  QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
2315  if ( !constraintsNode.isNull() )
2316  {
2317  QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2318  for ( int i = 0; i < constraintNodeList.size(); ++i )
2319  {
2320  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2321 
2322  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2323  int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
2324  if ( field.isEmpty() || constraints == 0 )
2325  continue;
2326 
2327  mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
2328 
2329  int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
2330  int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
2331  int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
2332 
2333  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
2334  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
2335  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
2336  }
2337  }
2338  mFieldConstraintExpressions.clear();
2339  QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
2340  if ( !constraintExpressionsNode.isNull() )
2341  {
2342  QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2343  for ( int i = 0; i < constraintNodeList.size(); ++i )
2344  {
2345  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2346 
2347  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2348  QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
2349  QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
2350  if ( field.isEmpty() || exp.isEmpty() )
2351  continue;
2352 
2353  mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
2354  }
2355  }
2356 
2357  updateFields();
2358  }
2359 
2360  // load field configuration
2361  if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
2362  {
2363  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Forms" ) );
2364 
2365  QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
2366  QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
2367  for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
2368  {
2369  const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
2370  const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
2371 
2372  QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
2373 
2374  if ( categories.testFlag( Fields ) )
2375  mFieldConfigurationFlags[fieldName] = qgsFlagKeysToValue( fieldConfigElement.attribute( QStringLiteral( "configurationFlags" ) ), QgsField::ConfigurationFlag::None );
2376 
2377  // Load editor widget configuration
2378  if ( categories.testFlag( Forms ) )
2379  {
2380  const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
2381  const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
2382  const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
2383  QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
2384  if ( widgetType == QLatin1String( "ValueRelation" ) )
2385  {
2386  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() );
2387  }
2388  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
2389  mFieldWidgetSetups[fieldName] = setup;
2390  }
2391  }
2392  }
2393 
2394  // Legacy reading for QGIS 3.14 and older projects
2395  // Attributes excluded from WMS and WFS
2396  if ( categories.testFlag( Fields ) )
2397  {
2398  const QList<QPair<QString, QgsField::ConfigurationFlag>> legacyConfig
2399  {
2400  qMakePair( QStringLiteral( "excludeAttributesWMS" ), QgsField::ConfigurationFlag::HideFromWms ),
2401  qMakePair( QStringLiteral( "excludeAttributesWFS" ), QgsField::ConfigurationFlag::HideFromWfs )
2402  };
2403  for ( const auto &config : legacyConfig )
2404  {
2405  QDomNode excludeNode = layerNode.namedItem( config.first );
2406  if ( !excludeNode.isNull() )
2407  {
2408  QDomNodeList attributeNodeList = excludeNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2409  for ( int i = 0; i < attributeNodeList.size(); ++i )
2410  {
2411  QString fieldName = attributeNodeList.at( i ).toElement().text();
2412  if ( !mFieldConfigurationFlags.contains( fieldName ) )
2413  mFieldConfigurationFlags[fieldName] = config.second;
2414  else
2415  mFieldConfigurationFlags[fieldName].setFlag( config.second, true );
2416  }
2417  }
2418  }
2419  }
2420 
2421  if ( categories.testFlag( GeometryOptions ) )
2422  mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral( "geometryOptions" ) ) );
2423 
2424  if ( categories.testFlag( Forms ) )
2425  mEditFormConfig.readXml( layerNode, context );
2426 
2427  if ( categories.testFlag( AttributeTable ) )
2428  {
2429  mAttributeTableConfig.readXml( layerNode );
2430  mConditionalStyles->readXml( layerNode, context );
2431  mStoredExpressionManager->readXml( layerNode );
2432  }
2433 
2434  if ( categories.testFlag( CustomProperties ) )
2435  readCustomProperties( layerNode, QStringLiteral( "variable" ) );
2436 
2437  QDomElement mapLayerNode = layerNode.toElement();
2438  if ( categories.testFlag( LayerConfiguration )
2439  && mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
2440  mReadOnly = true;
2441 
2442  updateFields();
2443 
2444  if ( categories.testFlag( Legend ) )
2445  {
2446  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Legend" ) );
2447 
2448  const QDomElement legendElem = layerNode.firstChildElement( QStringLiteral( "legend" ) );
2449  if ( !legendElem.isNull() )
2450  {
2451  std::unique_ptr< QgsMapLayerLegend > legend( QgsMapLayerLegend::defaultVectorLegend( this ) );
2452  legend->readXml( legendElem, context );
2453  setLegend( legend.release() );
2454  mSetLegendFromStyle = true;
2455  }
2456  }
2457 
2458  return true;
2459 }
2460 
2461 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage,
2462  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2463 {
2464  bool result = true;
2465  emit readCustomSymbology( node.toElement(), errorMessage );
2466 
2467  // we must try to restore a renderer if our geometry type is unknown
2468  // as this allows the renderer to be correctly restored even for layers
2469  // with broken sources
2470  if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2471  {
2472  // defer style changed signal until we've set the renderer, labeling, everything.
2473  // we don't want multiple signals!
2474  ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
2475 
2476  // try renderer v2 first
2477  if ( categories.testFlag( Symbology ) )
2478  {
2479  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Symbology" ) );
2480 
2481  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
2482  if ( !rendererElement.isNull() )
2483  {
2484  QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
2485  if ( r )
2486  {
2487  setRenderer( r );
2488  }
2489  else
2490  {
2491  result = false;
2492  }
2493  }
2494  // make sure layer has a renderer - if none exists, fallback to a default renderer
2495  if ( isSpatial() && !renderer() )
2496  {
2498  }
2499  }
2500 
2501  // read labeling definition
2502  if ( categories.testFlag( Labeling ) )
2503  {
2504  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2505 
2506  QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
2508  if ( labelingElement.isNull() ||
2509  ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
2510  {
2511  // make sure we have custom properties for labeling for 2.x projects
2512  // (custom properties should be already loaded when reading the whole layer from XML,
2513  // but when reading style, custom properties are not read)
2514  readCustomProperties( node, QStringLiteral( "labeling" ) );
2515 
2516  // support for pre-QGIS 3 labeling configurations written in custom properties
2517  labeling = readLabelingFromCustomProperties();
2518  }
2519  else
2520  {
2521  labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
2522  }
2523  setLabeling( labeling );
2524 
2525  if ( node.toElement().hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
2526  mLabelsEnabled = node.toElement().attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
2527  else
2528  mLabelsEnabled = true;
2529  }
2530 
2531  if ( categories.testFlag( Symbology ) )
2532  {
2533  // get and set the blend mode if it exists
2534  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
2535  if ( !blendModeNode.isNull() )
2536  {
2537  QDomElement e = blendModeNode.toElement();
2538  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2539  }
2540 
2541  // get and set the feature blend mode if it exists
2542  QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
2543  if ( !featureBlendModeNode.isNull() )
2544  {
2545  QDomElement e = featureBlendModeNode.toElement();
2546  setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2547  }
2548  }
2549 
2550  // get and set the layer transparency and scale visibility if they exists
2551  if ( categories.testFlag( Rendering ) )
2552  {
2553  QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
2554  if ( !layerTransparencyNode.isNull() )
2555  {
2556  QDomElement e = layerTransparencyNode.toElement();
2557  setOpacity( 1.0 - e.text().toInt() / 100.0 );
2558  }
2559  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
2560  if ( !layerOpacityNode.isNull() )
2561  {
2562  QDomElement e = layerOpacityNode.toElement();
2563  setOpacity( e.text().toDouble() );
2564  }
2565 
2566  const bool hasScaleBasedVisibiliy { node.attributes().namedItem( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).nodeValue() == '1' };
2567  setScaleBasedVisibility( hasScaleBasedVisibiliy );
2568  bool ok;
2569  const double maxScale { node.attributes().namedItem( QStringLiteral( "maxScale" ) ).nodeValue().toDouble( &ok ) };
2570  if ( ok )
2571  {
2572  setMaximumScale( maxScale );
2573  }
2574  const double minScale { node.attributes().namedItem( QStringLiteral( "minScale" ) ).nodeValue().toDouble( &ok ) };
2575  if ( ok )
2576  {
2577  setMinimumScale( minScale );
2578  }
2579 
2580  QDomElement e = node.toElement();
2581 
2582  // get the simplification drawing settings
2583  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
2584  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
2585  mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
2586  mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
2587  mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
2588 
2589  if ( mRenderer )
2590  mRenderer->setReferenceScale( e.attribute( QStringLiteral( "symbologyReferenceScale" ), QStringLiteral( "-1" ) ).toDouble() );
2591  }
2592 
2593  //diagram renderer and diagram layer settings
2594  if ( categories.testFlag( Diagrams ) )
2595  {
2596  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Diagrams" ) );
2597 
2598  delete mDiagramRenderer;
2599  mDiagramRenderer = nullptr;
2600  QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
2601  if ( !singleCatDiagramElem.isNull() )
2602  {
2603  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2604  mDiagramRenderer->readXml( singleCatDiagramElem, context );
2605  }
2606  QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
2607  if ( !linearDiagramElem.isNull() )
2608  {
2609  if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
2610  {
2611  // fix project from before QGIS 3.0
2612  int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
2613  if ( idx >= 0 && idx < mFields.count() )
2614  linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
2615  }
2616 
2617  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2618  mDiagramRenderer->readXml( linearDiagramElem, context );
2619  }
2620 
2621  if ( mDiagramRenderer )
2622  {
2623  QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
2624  if ( !diagramSettingsElem.isNull() )
2625  {
2626  bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
2627  bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
2628  bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
2629  if ( oldXPos || oldYPos || oldShow )
2630  {
2631  // fix project from before QGIS 3.0
2633  if ( oldXPos )
2634  {
2635  int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
2636  if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
2637  ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
2638  }
2639  if ( oldYPos )
2640  {
2641  int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
2642  if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
2643  ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
2644  }
2645  if ( oldShow )
2646  {
2647  int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
2648  if ( showColumn >= 0 && showColumn < mFields.count() )
2649  ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
2650  }
2651  QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
2653  {
2654  { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
2655  { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
2656  { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
2657  };
2658  ddp.writeXml( propertiesElem, defs );
2659  diagramSettingsElem.appendChild( propertiesElem );
2660  }
2661 
2662  delete mDiagramLayerSettings;
2663  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2664  mDiagramLayerSettings->readXml( diagramSettingsElem );
2665  }
2666  }
2667  }
2668  // end diagram
2669 
2670  styleChangedSignalBlocker.release();
2671  emitStyleChanged();
2672  }
2673  return result;
2674 }
2675 
2676 
2677 bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2678  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2679 {
2680  QDomElement layerElement = node.toElement();
2681  writeCommonStyle( layerElement, doc, context, categories );
2682 
2683  ( void )writeStyle( node, doc, errorMessage, context, categories );
2684 
2685  if ( categories.testFlag( GeometryOptions ) )
2686  mGeometryOptions->writeXml( node );
2687 
2688  if ( categories.testFlag( Legend ) && legend() )
2689  {
2690  QDomElement legendElement = legend()->writeXml( doc, context );
2691  if ( !legendElement.isNull() )
2692  node.appendChild( legendElement );
2693  }
2694 
2695  // Relation information for both referenced and referencing sides
2696  if ( categories.testFlag( Relations ) )
2697  {
2698  // Store referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2699  QDomElement referencedLayersElement = doc.createElement( QStringLiteral( "referencedLayers" ) );
2700  node.appendChild( referencedLayersElement );
2701 
2702  const auto constReferencingRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
2703  for ( const auto &rel : constReferencingRelations )
2704  {
2705  if ( rel.type() == QgsRelation::Normal )
2706  {
2707  QgsWeakRelation::writeXml( this, QgsWeakRelation::Referencing, rel, referencedLayersElement, doc );
2708  }
2709  }
2710 
2711  // Store referencing layers: relations where "this" is the parent layer (the referenced part, that holds the FK)
2712  QDomElement referencingLayersElement = doc.createElement( QStringLiteral( "referencingLayers" ) );
2713  node.appendChild( referencedLayersElement );
2714 
2715  const auto constReferencedRelations { QgsProject::instance()->relationManager()->referencedRelations( this ) };
2716  for ( const auto &rel : constReferencedRelations )
2717  {
2718  if ( rel.type() == QgsRelation::Normal )
2719  {
2720  QgsWeakRelation::writeXml( this, QgsWeakRelation::Referenced, rel, referencingLayersElement, doc );
2721  }
2722  }
2723 
2724  }
2725 
2726  // write field configurations
2727  if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
2728  {
2729  QDomElement fieldConfigurationElement;
2730  // field configuration flag
2731  fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2732  node.appendChild( fieldConfigurationElement );
2733 
2734  for ( const QgsField &field : std::as_const( mFields ) )
2735  {
2736  QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2737  fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2738  fieldConfigurationElement.appendChild( fieldElement );
2739 
2740  if ( categories.testFlag( Fields ) )
2741  {
2742  fieldElement.setAttribute( QStringLiteral( "configurationFlags" ), qgsFlagValueToKeys( field.configurationFlags() ) );
2743  }
2744 
2745  if ( categories.testFlag( Forms ) )
2746  {
2748 
2749  // TODO : wrap this part in an if to only save if it was user-modified
2750  QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2751  fieldElement.appendChild( editWidgetElement );
2752  editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2753  QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2754 
2755  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2756  editWidgetElement.appendChild( editWidgetConfigElement );
2757  // END TODO : wrap this part in an if to only save if it was user-modified
2758  }
2759  }
2760  }
2761 
2762  if ( categories.testFlag( Fields ) )
2763  {
2764  //attribute aliases
2765  QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2766  for ( const QgsField &field : std::as_const( mFields ) )
2767  {
2768  QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2769  aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2770  aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2771  aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2772  aliasElem.appendChild( aliasEntryElem );
2773  }
2774  node.appendChild( aliasElem );
2775 
2776  //default expressions
2777  QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2778  for ( const QgsField &field : std::as_const( mFields ) )
2779  {
2780  QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2781  defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2782  defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
2783  defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2784  defaultsElem.appendChild( defaultElem );
2785  }
2786  node.appendChild( defaultsElem );
2787 
2788  // constraints
2789  QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2790  for ( const QgsField &field : std::as_const( mFields ) )
2791  {
2792  QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2793  constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2794  constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2795  constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2796  constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2797  constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2798  constraintsElem.appendChild( constraintElem );
2799  }
2800  node.appendChild( constraintsElem );
2801 
2802  // constraint expressions
2803  QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2804  for ( const QgsField &field : std::as_const( mFields ) )
2805  {
2806  QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2807  constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2808  constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2809  constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2810  constraintExpressionsElem.appendChild( constraintExpressionElem );
2811  }
2812  node.appendChild( constraintExpressionsElem );
2813 
2814  // save expression fields
2815  if ( !mExpressionFieldBuffer )
2816  {
2817  // can happen when saving style on a invalid layer
2819  dummy.writeXml( node, doc );
2820  }
2821  else
2822  {
2823  mExpressionFieldBuffer->writeXml( node, doc );
2824  }
2825  }
2826 
2827  // add attribute actions
2828  if ( categories.testFlag( Actions ) )
2829  mActions->writeXml( node );
2830 
2831  if ( categories.testFlag( AttributeTable ) )
2832  {
2833  mAttributeTableConfig.writeXml( node );
2834  mConditionalStyles->writeXml( node, doc, context );
2835  mStoredExpressionManager->writeXml( node );
2836  }
2837 
2838  if ( categories.testFlag( Forms ) )
2839  mEditFormConfig.writeXml( node, context );
2840 
2841  // save readonly state
2842  if ( categories.testFlag( LayerConfiguration ) )
2843  node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2844 
2845  // save preview expression
2846  if ( categories.testFlag( LayerConfiguration ) )
2847  {
2848  QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2849  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2850  prevExpElem.appendChild( prevExpText );
2851  node.appendChild( prevExpElem );
2852  }
2853 
2854  // save map tip
2855  if ( categories.testFlag( MapTips ) )
2856  {
2857  QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2858  QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2859  mapTipElem.appendChild( mapTipText );
2860  node.toElement().appendChild( mapTipElem );
2861  }
2862 
2863  return true;
2864 }
2865 
2866 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2867  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2868 {
2869  QDomElement mapLayerNode = node.toElement();
2870 
2871  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2872 
2873  // we must try to write the renderer if our geometry type is unknown
2874  // as this allows the renderer to be correctly restored even for layers
2875  // with broken sources
2876  if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2877  {
2878  if ( categories.testFlag( Symbology ) )
2879  {
2880  if ( mRenderer )
2881  {
2882  QDomElement rendererElement = mRenderer->save( doc, context );
2883  node.appendChild( rendererElement );
2884  }
2885  }
2886 
2887  if ( categories.testFlag( Labeling ) )
2888  {
2889  if ( mLabeling )
2890  {
2891  QDomElement labelingElement = mLabeling->save( doc, context );
2892  node.appendChild( labelingElement );
2893  }
2894  mapLayerNode.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2895  }
2896 
2897  // save the simplification drawing settings
2898  if ( categories.testFlag( Rendering ) )
2899  {
2900  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2901  mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2902  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2903  mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2904  mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2905  }
2906 
2907  //save customproperties
2908  if ( categories.testFlag( CustomProperties ) )
2909  {
2910  writeCustomProperties( node, doc );
2911  }
2912 
2913  if ( categories.testFlag( Symbology ) )
2914  {
2915  // add the blend mode field
2916  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2917  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2918  blendModeElem.appendChild( blendModeText );
2919  node.appendChild( blendModeElem );
2920 
2921  // add the feature blend mode field
2922  QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2923  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2924  featureBlendModeElem.appendChild( featureBlendModeText );
2925  node.appendChild( featureBlendModeElem );
2926  }
2927 
2928  // add the layer opacity and scale visibility
2929  if ( categories.testFlag( Rendering ) )
2930  {
2931  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
2932  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
2933  layerOpacityElem.appendChild( layerOpacityText );
2934  node.appendChild( layerOpacityElem );
2935  mapLayerNode.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
2936  mapLayerNode.setAttribute( QStringLiteral( "maxScale" ), maximumScale() );
2937  mapLayerNode.setAttribute( QStringLiteral( "minScale" ), minimumScale() );
2938 
2939  mapLayerNode.setAttribute( QStringLiteral( "symbologyReferenceScale" ), mRenderer ? mRenderer->referenceScale() : -1 );
2940  }
2941 
2942  if ( categories.testFlag( Diagrams ) && mDiagramRenderer )
2943  {
2944  mDiagramRenderer->writeXml( mapLayerNode, doc, context );
2945  if ( mDiagramLayerSettings )
2946  mDiagramLayerSettings->writeXml( mapLayerNode, doc );
2947  }
2948  }
2949  return true;
2950 }
2951 
2952 bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
2953 {
2954  // get the Name element
2955  QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2956  if ( nameElem.isNull() )
2957  {
2958  errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2959  }
2960 
2961  if ( isSpatial() )
2962  {
2963  QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
2964  if ( !r )
2965  return false;
2966 
2967  // defer style changed signal until we've set the renderer, labeling, everything.
2968  // we don't want multiple signals!
2969  ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
2970 
2971  setRenderer( r );
2972 
2973  // labeling
2974  readSldLabeling( node );
2975 
2976  styleChangedSignalBlocker.release();
2977  emitStyleChanged();
2978  }
2979  return true;
2980 }
2981 
2982 bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props ) const
2983 {
2984  Q_UNUSED( errorMessage )
2985 
2986  QVariantMap localProps = QVariantMap( props );
2987  if ( hasScaleBasedVisibility() )
2988  {
2990  }
2991 
2992  if ( isSpatial() )
2993  {
2994  // store the Name element
2995  QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
2996  nameNode.appendChild( doc.createTextNode( name() ) );
2997  node.appendChild( nameNode );
2998 
2999  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
3000  node.appendChild( userStyleElem );
3001 
3002  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
3003  nameElem.appendChild( doc.createTextNode( name() ) );
3004 
3005  userStyleElem.appendChild( nameElem );
3006 
3007  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
3008  userStyleElem.appendChild( featureTypeStyleElem );
3009 
3010  mRenderer->toSld( doc, featureTypeStyleElem, localProps );
3011  if ( labelsEnabled() )
3012  {
3013  mLabeling->toSld( featureTypeStyleElem, localProps );
3014  }
3015  }
3016  return true;
3017 }
3018 
3019 
3020 bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
3021 {
3022  if ( !mEditBuffer || !mDataProvider )
3023  {
3024  return false;
3025  }
3026 
3027  if ( mGeometryOptions->isActive() )
3028  mGeometryOptions->apply( geom );
3029 
3030  updateExtents();
3031 
3032  bool result = mEditBuffer->changeGeometry( fid, geom );
3033 
3034  if ( result )
3035  {
3036  updateExtents();
3037  if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
3038  updateDefaultValues( fid );
3039  }
3040  return result;
3041 }
3042 
3043 
3044 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
3045 {
3046  bool result = false;
3047 
3048  switch ( fields().fieldOrigin( field ) )
3049  {
3050  case QgsFields::OriginJoin:
3051  result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
3052  if ( result )
3053  emit attributeValueChanged( fid, field, newValue );
3054  break;
3055 
3057  case QgsFields::OriginEdit:
3059  {
3060  if ( mEditBuffer && mDataProvider )
3061  result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
3062  break;
3063  }
3064 
3066  break;
3067  }
3068 
3069  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3070  updateDefaultValues( fid );
3071 
3072  return result;
3073 }
3074 
3075 bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
3076 {
3077  bool result = true;
3078 
3079  QgsAttributeMap newValuesJoin;
3080  QgsAttributeMap oldValuesJoin;
3081 
3082  QgsAttributeMap newValuesNotJoin;
3083  QgsAttributeMap oldValuesNotJoin;
3084 
3085  for ( auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
3086  {
3087  const int field = it.key();
3088  const QVariant newValue = it.value();
3089  QVariant oldValue;
3090 
3091  if ( oldValues.contains( field ) )
3092  oldValue = oldValues[field];
3093 
3094  switch ( fields().fieldOrigin( field ) )
3095  {
3096  case QgsFields::OriginJoin:
3097  newValuesJoin[field] = newValue;
3098  oldValuesJoin[field] = oldValue;
3099  break;
3100 
3102  case QgsFields::OriginEdit:
3104  {
3105  newValuesNotJoin[field] = newValue;
3106  oldValuesNotJoin[field] = oldValue;
3107  break;
3108  }
3109 
3111  break;
3112  }
3113  }
3114 
3115  if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
3116  {
3117  result = mJoinBuffer->changeAttributeValues( fid, newValuesJoin, oldValuesJoin );
3118  }
3119 
3120  if ( ! newValuesNotJoin.isEmpty() && mEditBuffer && mDataProvider )
3121  {
3122  result &= mEditBuffer->changeAttributeValues( fid, newValuesNotJoin, oldValues );
3123  }
3124 
3125  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3126  {
3127  updateDefaultValues( fid );
3128  }
3129 
3130  return result;
3131 }
3132 
3134 {
3135  if ( !mEditBuffer || !mDataProvider )
3136  return false;
3137 
3138  return mEditBuffer->addAttribute( field );
3139 }
3140 
3142 {
3143  if ( attIndex < 0 || attIndex >= fields().count() )
3144  return;
3145 
3146  QString name = fields().at( attIndex ).name();
3147  mFields[ attIndex ].setAlias( QString() );
3148  if ( mAttributeAliasMap.contains( name ) )
3149  {
3150  mAttributeAliasMap.remove( name );
3151  updateFields();
3152  mEditFormConfig.setFields( mFields );
3153  emit layerModified();
3154  }
3155 }
3156 
3157 bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
3158 {
3159  if ( index < 0 || index >= fields().count() )
3160  return false;
3161 
3162  switch ( mFields.fieldOrigin( index ) )
3163  {
3165  {
3166  if ( mExpressionFieldBuffer )
3167  {
3168  int oi = mFields.fieldOriginIndex( index );
3169  mExpressionFieldBuffer->renameExpression( oi, newName );
3170  updateFields();
3171  return true;
3172  }
3173  else
3174  {
3175  return false;
3176  }
3177  }
3178 
3180  case QgsFields::OriginEdit:
3181 
3182  if ( !mEditBuffer || !mDataProvider )
3183  return false;
3184 
3185  return mEditBuffer->renameAttribute( index, newName );
3186 
3187  case QgsFields::OriginJoin:
3189  return false;
3190 
3191  }
3192 
3193  return false; // avoid warning
3194 }
3195 
3196 void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
3197 {
3198  if ( attIndex < 0 || attIndex >= fields().count() )
3199  return;
3200 
3201  QString name = fields().at( attIndex ).name();
3202 
3203  mAttributeAliasMap.insert( name, aliasString );
3204  mFields[ attIndex ].setAlias( aliasString );
3205  mEditFormConfig.setFields( mFields );
3206  emit layerModified(); // TODO[MD]: should have a different signal?
3207 }
3208 
3209 QString QgsVectorLayer::attributeAlias( int index ) const
3210 {
3211  if ( index < 0 || index >= fields().count() )
3212  return QString();
3213 
3214  return fields().at( index ).alias();
3215 }
3216 
3217 QString QgsVectorLayer::attributeDisplayName( int index ) const
3218 {
3219  if ( index >= 0 && index < mFields.count() )
3220  return mFields.at( index ).displayName();
3221  else
3222  return QString();
3223 }
3224 
3226 {
3227  return mAttributeAliasMap;
3228 }
3229 
3231 {
3232  QSet<QString> excludeList;
3233  QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3234  for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3235  {
3236  if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWms ) )
3237  {
3238  excludeList << flagsIt.key();
3239  }
3240  }
3241  return excludeList;
3242 }
3243 
3244 void QgsVectorLayer::setExcludeAttributesWms( const QSet<QString> &att )
3245 {
3246  QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3247  for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3248  {
3249  flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWms, att.contains( flagsIt.key() ) );
3250  }
3251  updateFields();
3252 }
3253 
3255 {
3256  QSet<QString> excludeList;
3257  QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3258  for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3259  {
3260  if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWfs ) )
3261  {
3262  excludeList << flagsIt.key();
3263  }
3264  }
3265  return excludeList;
3266 }
3267 
3268 void QgsVectorLayer::setExcludeAttributesWfs( const QSet<QString> &att )
3269 {
3270  QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3271  for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3272  {
3273  flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWfs, att.contains( flagsIt.key() ) );
3274  }
3275  updateFields();
3276 }
3277 
3279 {
3280  if ( index < 0 || index >= fields().count() )
3281  return false;
3282 
3283  if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
3284  {
3285  removeExpressionField( index );
3286  return true;
3287  }
3288 
3289  if ( !mEditBuffer || !mDataProvider )
3290  return false;
3291 
3292  return mEditBuffer->deleteAttribute( index );
3293 }
3294 
3295 bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
3296 {
3297  bool deleted = false;
3298 
3299  // Remove multiple occurrences of same attribute
3300  QList<int> attrList = qgis::setToList( qgis::listToSet( attrs ) );
3301 
3302  std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
3303 
3304  for ( int attr : std::as_const( attrList ) )
3305  {
3306  if ( deleteAttribute( attr ) )
3307  {
3308  deleted = true;
3309  }
3310  }
3311 
3312  return deleted;
3313 }
3314 
3315 bool QgsVectorLayer::deleteFeatureCascade( QgsFeatureId fid, QgsVectorLayer::DeleteContext *context )
3316 {
3317  if ( !mEditBuffer )
3318  return false;
3319 
3320  if ( context && context->cascade )
3321  {
3322  const QList<QgsRelation> relations = context->project->relationManager()->referencedRelations( this );
3323  const bool hasRelationsOrJoins = !relations.empty() || mJoinBuffer->containsJoins();
3324  if ( hasRelationsOrJoins )
3325  {
3326  if ( context->mHandledFeatures.contains( this ) )
3327  {
3328  QgsFeatureIds &handledFeatureIds = context->mHandledFeatures[ this ];
3329  if ( handledFeatureIds.contains( fid ) )
3330  {
3331  // avoid endless recursion
3332  return false;
3333  }
3334  else
3335  {
3336  // add feature id
3337  handledFeatureIds << fid;
3338  }
3339  }
3340  else
3341  {
3342  // add layer and feature id
3343  context->mHandledFeatures.insert( this, QgsFeatureIds() << fid );
3344  }
3345 
3346  for ( const QgsRelation &relation : relations )
3347  {
3348  //check if composition (and not association)
3349  if ( relation.strength() == QgsRelation::Composition )
3350  {
3351  //get features connected over this relation
3352  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( getFeature( fid ) );
3353  QgsFeatureIds childFeatureIds;
3354  QgsFeature childFeature;
3355  while ( relatedFeaturesIt.nextFeature( childFeature ) )
3356  {
3357  childFeatureIds.insert( childFeature.id() );
3358  }
3359  if ( childFeatureIds.count() > 0 )
3360  {
3361  relation.referencingLayer()->startEditing();
3362  relation.referencingLayer()->deleteFeatures( childFeatureIds, context );
3363  }
3364  }
3365  }
3366  }
3367  }
3368 
3369  if ( mJoinBuffer->containsJoins() )
3370  mJoinBuffer->deleteFeature( fid, context );
3371 
3372  bool res = mEditBuffer->deleteFeature( fid );
3373 
3374  return res;
3375 }
3376 
3378 {
3379  if ( !mEditBuffer )
3380  return false;
3381 
3382  bool res = deleteFeatureCascade( fid, context );
3383 
3384  if ( res )
3385  {
3386  updateExtents();
3387  }
3388 
3389  return res;
3390 }
3391 
3393 {
3394  bool res = true;
3395  const auto constFids = fids;
3396  for ( QgsFeatureId fid : constFids )
3397  res = deleteFeatureCascade( fid, context ) && res;
3398 
3399  if ( res )
3400  {
3401  mSelectedFeatureIds.subtract( fids ); // remove it from selection
3402  updateExtents();
3403  }
3404 
3405  return res;
3406 }
3407 
3409 {
3410  return mFields;
3411 }
3412 
3414 {
3415  QgsAttributeList pkAttributesList;
3416  if ( !mDataProvider )
3417  return pkAttributesList;
3418 
3419  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
3420  for ( int i = 0; i < mFields.count(); ++i )
3421  {
3422  if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
3423  providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
3424  pkAttributesList << i;
3425  }
3426 
3427  return pkAttributesList;
3428 }
3429 
3431 {
3432  if ( !mDataProvider )
3433  return static_cast< long long >( Qgis::FeatureCountState::UnknownCount );
3434  return mDataProvider->featureCount() +
3435  ( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures().size() - mEditBuffer->deletedFeatureIds().size() : 0 );
3436 }
3437 
3439 {
3440  const QgsFeatureIds deletedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->deletedFeatureIds() : QgsFeatureIds() );
3441  const QgsFeatureMap addedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures() : QgsFeatureMap() );
3442 
3443  if ( mEditBuffer && !deletedFeatures.empty() )
3444  {
3445  if ( addedFeatures.size() > deletedFeatures.size() )
3446  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3447  else
3448  return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
3449  }
3450 
3451  if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider && mDataProvider->empty() )
3452  return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
3453  else
3454  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3455 }
3456 
3457 bool QgsVectorLayer::commitChanges( bool stopEditing )
3458 {
3459  mCommitErrors.clear();
3460 
3461  if ( !mDataProvider )
3462  {
3463  mCommitErrors << tr( "ERROR: no provider" );
3464  return false;
3465  }
3466 
3467  if ( !mEditBuffer )
3468  {
3469  mCommitErrors << tr( "ERROR: layer not editable" );
3470  return false;
3471  }
3472 
3473  emit beforeCommitChanges( stopEditing );
3474 
3475  if ( !mAllowCommit )
3476  return false;
3477 
3478  bool success = mEditBuffer->commitChanges( mCommitErrors );
3479 
3480  if ( success )
3481  {
3482  if ( stopEditing )
3483  {
3484  delete mEditBuffer;
3485  mEditBuffer = nullptr;
3486  }
3487  undoStack()->clear();
3488  emit afterCommitChanges();
3489  if ( stopEditing )
3490  emit editingStopped();
3491  }
3492  else
3493  {
3494  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QLatin1String( "\n " ) ) ) );
3495  }
3496 
3497  updateFields();
3498 
3499  mDataProvider->updateExtents();
3500  mDataProvider->leaveUpdateMode();
3501 
3502  // This second call is required because OGR provider with JSON
3503  // driver might have changed fields order after the call to
3504  // leaveUpdateMode
3505  if ( mFields.names() != mDataProvider->fields().names() )
3506  {
3507  updateFields();
3508  }
3509 
3510  triggerRepaint();
3511 
3512  return success;
3513 }
3514 
3515 QStringList QgsVectorLayer::commitErrors() const
3516 {
3517  return mCommitErrors;
3518 }
3519 
3520 bool QgsVectorLayer::rollBack( bool deleteBuffer )
3521 {
3522  if ( !mEditBuffer )
3523  {
3524  return false;
3525  }
3526 
3527  if ( !mDataProvider )
3528  {
3529  mCommitErrors << tr( "ERROR: no provider" );
3530  return false;
3531  }
3532 
3533  bool rollbackExtent = !mDataProvider->transaction() && ( !mEditBuffer->deletedFeatureIds().isEmpty() ||
3534  !mEditBuffer->addedFeatures().isEmpty() ||
3535  !mEditBuffer->changedGeometries().isEmpty() );
3536 
3537  emit beforeRollBack();
3538 
3539  mEditBuffer->rollBack();
3540 
3541  emit afterRollBack();
3542 
3543  if ( isModified() )
3544  {
3545  // new undo stack roll back method
3546  // old method of calling every undo could cause many canvas refreshes
3547  undoStack()->setIndex( 0 );
3548  }
3549 
3550  updateFields();
3551 
3552  if ( deleteBuffer )
3553  {
3554  delete mEditBuffer;
3555  mEditBuffer = nullptr;
3556  undoStack()->clear();
3557  }
3558  emit editingStopped();
3559 
3560  if ( rollbackExtent )
3561  updateExtents();
3562 
3563  mDataProvider->leaveUpdateMode();
3564 
3565  triggerRepaint();
3566  return true;
3567 }
3568 
3570 {
3571  return mSelectedFeatureIds.size();
3572 }
3573 
3575 {
3576  return mSelectedFeatureIds;
3577 }
3578 
3580 {
3581  QgsFeatureList features;
3582  features.reserve( mSelectedFeatureIds.count() );
3583  QgsFeature f;
3584 
3585  if ( mSelectedFeatureIds.count() <= 8 )
3586  {
3587  // for small amount of selected features, fetch them directly
3588  // because request with FilterFids would go iterate over the whole layer
3589  const auto constMSelectedFeatureIds = mSelectedFeatureIds;
3590  for ( QgsFeatureId fid : constMSelectedFeatureIds )
3591  {
3592  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
3593  features << f;
3594  }
3595  }
3596  else
3597  {
3599 
3600  while ( it.nextFeature( f ) )
3601  {
3602  features.push_back( f );
3603  }
3604  }
3605 
3606  return features;
3607 }
3608 
3610 {
3611  if ( mSelectedFeatureIds.isEmpty() )
3612  return QgsFeatureIterator();
3613 
3616 
3617  if ( mSelectedFeatureIds.count() == 1 )
3618  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
3619  else
3620  request.setFilterFids( mSelectedFeatureIds );
3621 
3622  return getFeatures( request );
3623 }
3624 
3626 {
3627  if ( !mEditBuffer || !mDataProvider )
3628  return false;
3629 
3630  if ( mGeometryOptions->isActive() )
3631  {
3632  for ( auto feature = features.begin(); feature != features.end(); ++feature )
3633  {
3634  QgsGeometry geom = feature->geometry();
3635  mGeometryOptions->apply( geom );
3636  feature->setGeometry( geom );
3637  }
3638  }
3639 
3640  bool res = mEditBuffer->addFeatures( features );
3641  updateExtents();
3642 
3643  if ( res && mJoinBuffer->containsJoins() )
3644  res = mJoinBuffer->addFeatures( features );
3645 
3646  return res;
3647 }
3648 
3650 {
3651  // if layer is not spatial, it has not CRS!
3652  setCrs( ( isSpatial() && mDataProvider ) ? mDataProvider->crs() : QgsCoordinateReferenceSystem() );
3653 }
3654 
3656 {
3658  if ( exp.isField() )
3659  {
3660  return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
3661  }
3662 
3663  return QString();
3664 }
3665 
3666 void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
3667 {
3668  if ( mDisplayExpression == displayExpression )
3669  return;
3670 
3671  mDisplayExpression = displayExpression;
3672  emit displayExpressionChanged();
3673 }
3674 
3676 {
3677  if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
3678  {
3679  return mDisplayExpression;
3680  }
3681  else
3682  {
3683  const QString candidateName = QgsVectorLayerUtils::guessFriendlyIdentifierField( mFields );
3684  if ( !candidateName.isEmpty() )
3685  {
3686  return QgsExpression::quotedColumnRef( candidateName );
3687  }
3688  else
3689  {
3690  return QString();
3691  }
3692  }
3693 }
3694 
3696 {
3697  return ( mEditBuffer && mDataProvider );
3698 }
3699 
3701 {
3704 }
3705 
3706 bool QgsVectorLayer::isReadOnly() const
3707 {
3708  return mReadOnly;
3709 }
3710 
3711 bool QgsVectorLayer::setReadOnly( bool readonly )
3712 {
3713  // exit if the layer is in editing mode
3714  if ( readonly && mEditBuffer )
3715  return false;
3716 
3717  mReadOnly = readonly;
3718  emit readOnlyChanged();
3719  return true;
3720 }
3721 
3723 {
3724  if ( ! mDataProvider )
3725  return false;
3726 
3727  return mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities && ! mReadOnly;
3728 }
3729 
3731 {
3732  emit beforeModifiedCheck();
3733  return mEditBuffer && mEditBuffer->isModified();
3734 }
3735 
3736 bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
3737 {
3738  bool auxiliaryField = false;
3739  srcIndex = -1;
3740 
3741  if ( !auxiliaryLayer() )
3742  return auxiliaryField;
3743 
3744  if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
3745  {
3746  const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
3747 
3748  if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
3749  auxiliaryField = true;
3750  }
3751 
3752  return auxiliaryField;
3753 }
3754 
3756 {
3757  // we must allow setting a renderer if our geometry type is unknown
3758  // as this allows the renderer to be correctly set even for layers
3759  // with broken sources
3760  if ( !isSpatial() && mWkbType != QgsWkbTypes::Unknown )
3761  return;
3762 
3763  if ( r != mRenderer )
3764  {
3765  delete mRenderer;
3766  mRenderer = r;
3767  mSymbolFeatureCounted = false;
3768  mSymbolFeatureCountMap.clear();
3769  mSymbolFeatureIdMap.clear();
3770 
3771  emit rendererChanged();
3772  emitStyleChanged();
3773  }
3774 }
3775 
3777 {
3778  if ( generator )
3779  {
3780  mRendererGenerators << generator;
3781  }
3782 }
3783 
3785 {
3786  for ( int i = mRendererGenerators.count() - 1; i >= 0; --i )
3787  {
3788  if ( mRendererGenerators.at( i )->id() == id )
3789  {
3790  delete mRendererGenerators.at( i );
3791  mRendererGenerators.removeAt( i );
3792  }
3793  }
3794 }
3795 
3796 QList<const QgsFeatureRendererGenerator *> QgsVectorLayer::featureRendererGenerators() const
3797 {
3798  QList< const QgsFeatureRendererGenerator * > res;
3799  for ( const QgsFeatureRendererGenerator *generator : mRendererGenerators )
3800  res << generator;
3801  return res;
3802 }
3803 
3804 void QgsVectorLayer::beginEditCommand( const QString &text )
3805 {
3806  if ( !mDataProvider )
3807  {
3808  return;
3809  }
3810  if ( mDataProvider->transaction() )
3811  {
3812  QString ignoredError;
3813  mDataProvider->transaction()->createSavepoint( ignoredError );
3814  }
3815  undoStack()->beginMacro( text );
3816  mEditCommandActive = true;
3817  emit editCommandStarted( text );
3818 }
3819 
3821 {
3822  if ( !mDataProvider )
3823  {
3824  return;
3825  }
3826  undoStack()->endMacro();
3827  mEditCommandActive = false;
3828  if ( !mDeletedFids.isEmpty() )
3829  {
3830  if ( selectedFeatureCount() > 0 )
3831  {
3832  mSelectedFeatureIds.subtract( mDeletedFids );
3833  }
3834  emit featuresDeleted( mDeletedFids );
3835  mDeletedFids.clear();
3836  }
3837  emit editCommandEnded();
3838 }
3839 
3841 {
3842  if ( !mDataProvider )
3843  {
3844  return;
3845  }
3846  undoStack()->endMacro();
3847  undoStack()->undo();
3848 
3849  // it's not directly possible to pop the last command off the stack (the destroyed one)
3850  // and delete, so we add a dummy obsolete command to force this to occur.
3851  // Pushing the new command deletes the destroyed one, and since the new
3852  // command is obsolete it's automatically deleted by the undo stack.
3853  std::unique_ptr< QUndoCommand > command = std::make_unique< QUndoCommand >();
3854  command->setObsolete( true );
3855  undoStack()->push( command.release() );
3856 
3857  mEditCommandActive = false;
3858  mDeletedFids.clear();
3859  emit editCommandDestroyed();
3860 }
3861 
3863 {
3864  return mJoinBuffer->addJoin( joinInfo );
3865 }
3866 
3867 
3868 bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
3869 {
3870  return mJoinBuffer->removeJoin( joinLayerId );
3871 }
3872 
3873 const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
3874 {
3875  return mJoinBuffer->vectorJoins();
3876 }
3877 
3878 int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
3879 {
3880  emit beforeAddingExpressionField( fld.name() );
3881  mExpressionFieldBuffer->addExpression( exp, fld );
3882  updateFields();
3883  int idx = mFields.indexFromName( fld.name() );
3884  emit attributeAdded( idx );
3885  return idx;
3886 }
3887 
3889 {
3890  emit beforeRemovingExpressionField( index );
3891  int oi = mFields.fieldOriginIndex( index );
3892  mExpressionFieldBuffer->removeExpression( oi );
3893  updateFields();
3894  emit attributeDeleted( index );
3895 }
3896 
3897 QString QgsVectorLayer::expressionField( int index ) const
3898 {
3899  if ( mFields.fieldOrigin( index ) != QgsFields::OriginExpression )
3900  return QString();
3901 
3902  int oi = mFields.fieldOriginIndex( index );
3903  if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
3904  return QString();
3905 
3906  return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
3907 }
3908 
3909 void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
3910 {
3911  int oi = mFields.fieldOriginIndex( index );
3912  mExpressionFieldBuffer->updateExpression( oi, exp );
3913 }
3914 
3916 {
3917  if ( !mDataProvider )
3918  return;
3919 
3920  QgsFields oldFields = mFields;
3921 
3922  mFields = mDataProvider->fields();
3923 
3924  // added / removed fields
3925  if ( mEditBuffer )
3926  mEditBuffer->updateFields( mFields );
3927 
3928  // joined fields
3929  if ( mJoinBuffer->containsJoins() )
3930  mJoinBuffer->updateFields( mFields );
3931 
3932  if ( mExpressionFieldBuffer )
3933  mExpressionFieldBuffer->updateFields( mFields );
3934 
3935  // set aliases and default values
3936  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
3937  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
3938  {
3939  int index = mFields.lookupField( aliasIt.key() );
3940  if ( index < 0 )
3941  continue;
3942 
3943  mFields[ index ].setAlias( aliasIt.value() );
3944  }
3945 
3946  // Update configuration flags
3947  QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3948  for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3949  {
3950  int index = mFields.lookupField( flagsIt.key() );
3951  if ( index < 0 )
3952  continue;
3953 
3954  mFields[index].setConfigurationFlags( flagsIt.value() );
3955  }
3956 
3957  // Update default values
3958  mDefaultValueOnUpdateFields.clear();
3959  QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
3960  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
3961  {
3962  int index = mFields.lookupField( defaultIt.key() );
3963  if ( index < 0 )
3964  continue;
3965 
3966  mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
3967  if ( defaultIt.value().applyOnUpdate() )
3968  mDefaultValueOnUpdateFields.insert( index );
3969  }
3970 
3971  QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
3972  for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
3973  {
3974  int index = mFields.lookupField( constraintIt.key() );
3975  if ( index < 0 )
3976  continue;
3977 
3978  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3979 
3980  // always keep provider constraints intact
3981  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
3983  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
3985  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
3987  mFields[ index ].setConstraints( constraints );
3988  }
3989 
3990  QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
3991  for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
3992  {
3993  int index = mFields.lookupField( constraintExpIt.key() );
3994  if ( index < 0 )
3995  continue;
3996 
3997  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3998 
3999  // always keep provider constraints intact
4001  continue;
4002 
4003  constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
4004  mFields[ index ].setConstraints( constraints );
4005  }
4006 
4007  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
4008  for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
4009  {
4010  int index = mFields.lookupField( constraintStrengthIt.key().first );
4011  if ( index < 0 )
4012  continue;
4013 
4014  QgsFieldConstraints constraints = mFields.at( index ).constraints();
4015 
4016  // always keep provider constraints intact
4018  continue;
4019 
4020  constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
4021  mFields[ index ].setConstraints( constraints );
4022  }
4023 
4024  auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
4025  for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
4026  {
4027  int index = mFields.indexOf( fieldWidgetIterator.key() );
4028  if ( index < 0 )
4029  continue;
4030 
4031  mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
4032  }
4033 
4034  if ( oldFields != mFields )
4035  {
4036  emit updatedFields();
4037  mEditFormConfig.setFields( mFields );
4038  }
4039 
4040 }
4041 
4042 
4043 QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
4044 {
4045  if ( index < 0 || index >= mFields.count() || !mDataProvider )
4046  return QVariant();
4047 
4048  QString expression = mFields.at( index ).defaultValueDefinition().expression();
4049  if ( expression.isEmpty() )
4050  return mDataProvider->defaultValue( index );
4051 
4052  QgsExpressionContext *evalContext = context;
4053  std::unique_ptr< QgsExpressionContext > tempContext;
4054  if ( !evalContext )
4055  {
4056  // no context passed, so we create a default one
4058  evalContext = tempContext.get();
4059  }
4060 
4061  if ( feature.isValid() )
4062  {
4064  featScope->setFeature( feature );
4065  featScope->setFields( feature.fields() );
4066  evalContext->appendScope( featScope );
4067  }
4068 
4069  QVariant val;
4070  QgsExpression exp( expression );
4071  exp.prepare( evalContext );
4072  if ( exp.hasEvalError() )
4073  {
4074  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
4075  }
4076  else
4077  {
4078  val = exp.evaluate( evalContext );
4079  }
4080 
4081  if ( feature.isValid() )
4082  {
4083  delete evalContext->popScope();
4084  }
4085 
4086  return val;
4087 }
4088 
4090 {
4091  if ( index < 0 || index >= mFields.count() )
4092  return;
4093 
4094  if ( definition.isValid() )
4095  {
4096  mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
4097  }
4098  else
4099  {
4100  mDefaultExpressionMap.remove( mFields.at( index ).name() );
4101  }
4102  updateFields();
4103 }
4104 
4106 {
4107  if ( index < 0 || index >= mFields.count() )
4108  return QgsDefaultValue();
4109  else
4110  return mFields.at( index ).defaultValueDefinition();
4111 }
4112 
4113 QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
4114 {
4115  QSet<QVariant> uniqueValues;
4116  if ( !mDataProvider )
4117  {
4118  return uniqueValues;
4119  }
4120 
4121  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4122  switch ( origin )
4123  {
4125  return uniqueValues;
4126 
4127  case QgsFields::OriginProvider: //a provider field
4128  {
4129  uniqueValues = mDataProvider->uniqueValues( index, limit );
4130 
4131  if ( mEditBuffer && ! mDataProvider->transaction() )
4132  {
4133  QSet<QString> vals;
4134  const auto constUniqueValues = uniqueValues;
4135  for ( const QVariant &v : constUniqueValues )
4136  {
4137  vals << v.toString();
4138  }
4139 
4140  QgsFeatureMap added = mEditBuffer->addedFeatures();
4141  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4142  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
4143  {
4144  addedIt.next();
4145  QVariant v = addedIt.value().attribute( index );
4146  if ( v.isValid() )
4147  {
4148  QString vs = v.toString();
4149  if ( !vals.contains( vs ) )
4150  {
4151  vals << vs;
4152  uniqueValues << v;
4153  }
4154  }
4155  }
4156 
4157  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4158  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
4159  {
4160  it.next();
4161  QVariant v = it.value().value( index );
4162  if ( v.isValid() )
4163  {
4164  QString vs = v.toString();
4165  if ( !vals.contains( vs ) )
4166  {
4167  vals << vs;
4168  uniqueValues << v;
4169  }
4170  }
4171  }
4172  }
4173 
4174  return uniqueValues;
4175  }
4176 
4177  case QgsFields::OriginEdit:
4178  // the layer is editable, but in certain cases it can still be avoided going through all features
4179  if ( mDataProvider->transaction() || (
4180  mEditBuffer->deletedFeatureIds().isEmpty() &&
4181  mEditBuffer->addedFeatures().isEmpty() &&
4182  !mEditBuffer->deletedAttributeIds().contains( index ) &&
4183  mEditBuffer->changedAttributeValues().isEmpty() ) )
4184  {
4185  uniqueValues = mDataProvider->uniqueValues( index, limit );
4186  return uniqueValues;
4187  }
4188  FALLTHROUGH
4189  //we need to go through each feature
4190  case QgsFields::OriginJoin:
4192  {
4193  QgsAttributeList attList;
4194  attList << index;
4195 
4198  .setSubsetOfAttributes( attList ) );
4199 
4200  QgsFeature f;
4201  QVariant currentValue;
4202  QHash<QString, QVariant> val;
4203  while ( fit.nextFeature( f ) )
4204  {
4205  currentValue = f.attribute( index );
4206  val.insert( currentValue.toString(), currentValue );
4207  if ( limit >= 0 && val.size() >= limit )
4208  {
4209  break;
4210  }
4211  }
4212 
4213  return qgis::listToSet( val.values() );
4214  }
4215  }
4216 
4217  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
4218  return uniqueValues;
4219 }
4220 
4221 QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
4222 {
4223  QStringList results;
4224  if ( !mDataProvider )
4225  {
4226  return results;
4227  }
4228 
4229  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4230  switch ( origin )
4231  {
4233  return results;
4234 
4235  case QgsFields::OriginProvider: //a provider field
4236  {
4237  results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4238 
4239  if ( mEditBuffer && ! mDataProvider->transaction() )
4240  {
4241  QgsFeatureMap added = mEditBuffer->addedFeatures();
4242  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4243  while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4244  {
4245  addedIt.next();
4246  QVariant v = addedIt.value().attribute( index );
4247  if ( v.isValid() )
4248  {
4249  QString vs = v.toString();
4250  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4251  {
4252  results << vs;
4253  }
4254  }
4255  }
4256 
4257  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4258  while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4259  {
4260  it.next();
4261  QVariant v = it.value().value( index );
4262  if ( v.isValid() )
4263  {
4264  QString vs = v.toString();
4265  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4266  {
4267  results << vs;
4268  }
4269  }
4270  }
4271  }
4272 
4273  return results;
4274  }
4275 
4276  case QgsFields::OriginEdit:
4277  // the layer is editable, but in certain cases it can still be avoided going through all features
4278  if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
4279  mEditBuffer->addedFeatures().isEmpty() &&
4280  !mEditBuffer->deletedAttributeIds().contains( index ) &&
4281  mEditBuffer->changedAttributeValues().isEmpty() ) )
4282  {
4283  return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4284  }
4285  FALLTHROUGH
4286  //we need to go through each feature
4287  case QgsFields::OriginJoin:
4289  {
4290  QgsAttributeList attList;
4291  attList << index;
4292 
4293  QgsFeatureRequest request;
4294  request.setSubsetOfAttributes( attList );
4296  QString fieldName = mFields.at( index ).name();
4297  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
4298  QgsFeatureIterator fit = getFeatures( request );
4299 
4300  QgsFeature f;
4301  QString currentValue;
4302  while ( fit.nextFeature( f ) )
4303  {
4304  currentValue = f.attribute( index ).toString();
4305  if ( !results.contains( currentValue ) )
4306  results << currentValue;
4307 
4308  if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
4309  {
4310  break;
4311  }
4312  }
4313 
4314  return results;
4315  }
4316  }
4317 
4318  Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
4319  return results;
4320 }
4321 
4322 QVariant QgsVectorLayer::minimumValue( int index ) const
4323 {
4324  QVariant minimum;
4325  minimumOrMaximumValue( index, &minimum, nullptr );
4326  return minimum;
4327 }
4328 
4329 QVariant QgsVectorLayer::maximumValue( int index ) const
4330 {
4331  QVariant maximum;
4332  minimumOrMaximumValue( index, nullptr, &maximum );
4333  return maximum;
4334 }
4335 
4336 void QgsVectorLayer::minimumAndMaximumValue( int index, QVariant &minimum, QVariant &maximum ) const
4337 {
4338  minimumOrMaximumValue( index, &minimum, &maximum );
4339 }
4340 
4341 void QgsVectorLayer::minimumOrMaximumValue( int index, QVariant *minimum, QVariant *maximum ) const
4342 {
4343  if ( minimum )
4344  *minimum = QVariant();
4345  if ( maximum )
4346  *maximum = QVariant();
4347 
4348  if ( !mDataProvider )
4349  {
4350  return;
4351  }
4352 
4353  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4354 
4355  switch ( origin )
4356  {
4358  {
4359  return;
4360  }
4361 
4362  case QgsFields::OriginProvider: //a provider field
4363  {
4364  if ( minimum )
4365  *minimum = mDataProvider->minimumValue( index );
4366  if ( maximum )
4367  *maximum = mDataProvider->maximumValue( index );
4368  if ( mEditBuffer && ! mDataProvider->transaction() )
4369  {
4370  const QgsFeatureMap added = mEditBuffer->addedFeatures();
4371  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4372  while ( addedIt.hasNext() )
4373  {
4374  addedIt.next();
4375  const QVariant v = addedIt.value().attribute( index );
4376  if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
4377  *minimum = v;
4378  if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
4379  *maximum = v;
4380  }
4381 
4382  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4383  while ( it.hasNext() )
4384  {
4385  it.next();
4386  const QVariant v = it.value().value( index );
4387  if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
4388  *minimum = v;
4389  if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
4390  *maximum = v;
4391  }
4392  }
4393  return;
4394  }
4395 
4396  case QgsFields::OriginEdit:
4397  {
4398  // the layer is editable, but in certain cases it can still be avoided going through all features
4399  if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
4400  mEditBuffer->addedFeatures().isEmpty() &&
4401  !mEditBuffer->deletedAttributeIds().contains( index ) &&
4402  mEditBuffer->changedAttributeValues().isEmpty() ) )
4403  {
4404  if ( minimum )
4405  *minimum = mDataProvider->minimumValue( index );
4406  if ( maximum )
4407  *maximum = mDataProvider->maximumValue( index );
4408  return;
4409  }
4410  }
4411  FALLTHROUGH
4412  // no choice but to go through all features
4414  case QgsFields::OriginJoin:
4415  {
4416  // we need to go through each feature
4417  QgsAttributeList attList;
4418  attList << index;
4419 
4422  .setSubsetOfAttributes( attList ) );
4423 
4424  QgsFeature f;
4425  bool firstValue = true;
4426  while ( fit.nextFeature( f ) )
4427  {
4428  const QVariant currentValue = f.attribute( index );
4429  if ( currentValue.isNull() )
4430  continue;
4431 
4432  if ( firstValue )
4433  {
4434  if ( minimum )
4435  *minimum = currentValue;
4436  if ( maximum )
4437  *maximum = currentValue;
4438  firstValue = false;
4439  }
4440  else
4441  {
4442  if ( minimum && currentValue.isValid() && qgsVariantLessThan( currentValue, *minimum ) )
4443  *minimum = currentValue;
4444  if ( maximum && currentValue.isValid() && qgsVariantGreaterThan( currentValue, *maximum ) )
4445  *maximum = currentValue;
4446  }
4447  }
4448  return;
4449  }
4450  }
4451 
4452  Q_ASSERT_X( false, "QgsVectorLayer::minimumOrMaximumValue()", "Unknown source of the field!" );
4453 }
4454 
4455 QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
4457  bool *ok, QgsFeatureIds *fids, QgsFeedback *feedback, QString *error ) const
4458 {
4459  if ( ok )
4460  *ok = false;
4461  if ( error )
4462  error->clear();
4463 
4464  if ( !mDataProvider )
4465  {
4466  if ( error )
4467  *error = tr( "Layer is invalid" );
4468  return QVariant();
4469  }
4470 
4471  // test if we are calculating based on a field
4472  const int attrIndex = QgsExpression::expressionToLayerFieldIndex( fieldOrExpression, this );
4473  if ( attrIndex >= 0 )
4474  {
4475  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
4476  // to the provider itself
4477  QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
4478  if ( origin == QgsFields::OriginProvider )
4479  {
4480  bool providerOk = false;
4481  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk, fids );
4482  if ( providerOk )
4483  {
4484  // provider handled calculation
4485  if ( ok )
4486  *ok = true;
4487  return val;
4488  }
4489  }
4490  }
4491 
4492  // fallback to using aggregate calculator to determine aggregate
4493  QgsAggregateCalculator c( this );
4494  if ( fids )
4495  c.setFidsFilter( *fids );
4496  c.setParameters( parameters );
4497  bool aggregateOk = false;
4498  const QVariant result = c.calculate( aggregate, fieldOrExpression, context, &aggregateOk, feedback );
4499  if ( ok )
4500  *ok = aggregateOk;
4501  if ( !aggregateOk && error )
4502  *error = c.lastError();
4503 
4504  return result;
4505 }
4506 
4507 void QgsVectorLayer::setFeatureBlendMode( QPainter::CompositionMode featureBlendMode )
4508 {
4509  if ( mFeatureBlendMode == featureBlendMode )
4510  return;
4511 
4512  mFeatureBlendMode = featureBlendMode;
4514  emitStyleChanged();
4515 }
4516 
4517 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
4518 {
4519  return mFeatureBlendMode;
4520 }
4521 
4522 void QgsVectorLayer::readSldLabeling( const QDomNode &node )
4523 {
4524  setLabeling( nullptr ); // start with no labeling
4525  setLabelsEnabled( false );
4526 
4527  QDomElement element = node.toElement();
4528  if ( element.isNull() )
4529  return;
4530 
4531  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
4532  if ( userStyleElem.isNull() )
4533  {
4534  QgsDebugMsgLevel( QStringLiteral( "Info: UserStyle element not found." ), 4 );
4535  return;
4536  }
4537 
4538  QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
4539  if ( featTypeStyleElem.isNull() )
4540  {
4541  QgsDebugMsgLevel( QStringLiteral( "Info: FeatureTypeStyle element not found." ), 4 );
4542  return;
4543  }
4544 
4545  // create empty FeatureTypeStyle element to merge TextSymbolizer's Rule's from all FeatureTypeStyle's
4546  QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode( false ).toElement();
4547 
4548  // use the RuleRenderer when more rules are present or the rule
4549  // has filters or min/max scale denominators set,
4550  // otherwise use the Simple labeling
4551  bool needRuleBasedLabeling = false;
4552  int ruleCount = 0;
4553 
4554  while ( !featTypeStyleElem.isNull() )
4555  {
4556  QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
4557  while ( !ruleElem.isNull() )
4558  {
4559  // test rule children element to check if we need to create RuleRenderer
4560  // and if the rule has a symbolizer
4561  bool hasTextSymbolizer = false;
4562  bool hasRuleBased = false;
4563  QDomElement ruleChildElem = ruleElem.firstChildElement();
4564  while ( !ruleChildElem.isNull() )
4565  {
4566  // rule has filter or min/max scale denominator, use the RuleRenderer
4567  if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
4568  ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
4569  ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4570  {
4571  hasRuleBased = true;
4572  }
4573  // rule has a renderer symbolizer, not a text symbolizer
4574  else if ( ruleChildElem.localName() == QLatin1String( "TextSymbolizer" ) )
4575  {
4576  QgsDebugMsgLevel( QStringLiteral( "Info: TextSymbolizer element found" ), 4 );
4577  hasTextSymbolizer = true;
4578  }
4579 
4580  ruleChildElem = ruleChildElem.nextSiblingElement();
4581  }
4582 
4583  if ( hasTextSymbolizer )
4584  {
4585  ruleCount++;
4586 
4587  // append a clone of all Rules to the merged FeatureTypeStyle element
4588  mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
4589 
4590  if ( hasRuleBased )
4591  {
4592  QgsDebugMsgLevel( QStringLiteral( "Info: Filter or Min/MaxScaleDenominator element found: need a RuleBasedLabeling" ), 4 );
4593  needRuleBasedLabeling = true;
4594  }
4595  }
4596 
4597  // more rules present, use the RuleRenderer
4598  if ( ruleCount > 1 )
4599  {
4600  QgsDebugMsgLevel( QStringLiteral( "Info: More Rule elements found: need a RuleBasedLabeling" ), 4 );
4601  needRuleBasedLabeling = true;
4602  }
4603 
4604  // not use the rule based labeling if no rules with textSymbolizer
4605  if ( ruleCount == 0 )
4606  {
4607  needRuleBasedLabeling = false;
4608  }
4609 
4610  ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
4611  }
4612  featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral( "FeatureTypeStyle" ) );
4613  }
4614 
4615  if ( ruleCount == 0 )
4616  {
4617  QgsDebugMsgLevel( QStringLiteral( "Info: No TextSymbolizer element." ), 4 );
4618  return;
4619  }
4620 
4621  QDomElement ruleElem = mergedFeatTypeStyle.firstChildElement( QStringLiteral( "Rule" ) );
4622 
4623  if ( needRuleBasedLabeling )
4624  {
4625  QgsDebugMsgLevel( QStringLiteral( "Info: rule based labeling" ), 4 );
4626  QgsRuleBasedLabeling::Rule *rootRule = new QgsRuleBasedLabeling::Rule( nullptr );
4627  while ( !ruleElem.isNull() )
4628  {
4629 
4630  QString label, description, filterExp;
4631  int scaleMinDenom = 0, scaleMaxDenom = 0;
4632  QgsPalLayerSettings settings;
4633 
4634  // retrieve the Rule element child nodes
4635  QDomElement childElem = ruleElem.firstChildElement();
4636  while ( !childElem.isNull() )
4637  {
4638  if ( childElem.localName() == QLatin1String( "Name" ) )
4639  {
4640  // <se:Name> tag contains the rule identifier,
4641  // so prefer title tag for the label property value
4642  if ( label.isEmpty() )
4643  label = childElem.firstChild().nodeValue();
4644  }
4645  else if ( childElem.localName() == QLatin1String( "Description" ) )
4646  {
4647  // <se:Description> can contains a title and an abstract
4648  QDomElement titleElem = childElem.firstChildElement( QStringLiteral( "Title" ) );
4649  if ( !titleElem.isNull() )
4650  {
4651  label = titleElem.firstChild().nodeValue();
4652  }
4653 
4654  QDomElement abstractElem = childElem.firstChildElement( QStringLiteral( "Abstract" ) );
4655  if ( !abstractElem.isNull() )
4656  {
4657  description = abstractElem.firstChild().nodeValue();
4658  }
4659  }
4660  else if ( childElem.localName() == QLatin1String( "Abstract" ) )
4661  {
4662  // <sld:Abstract> (v1.0)
4663  description = childElem.firstChild().nodeValue();
4664  }
4665  else if ( childElem.localName() == QLatin1String( "Title" ) )
4666  {
4667  // <sld:Title> (v1.0)
4668  label = childElem.firstChild().nodeValue();
4669  }
4670  else if ( childElem.localName() == QLatin1String( "Filter" ) )
4671  {
4672  QgsExpression *filter = QgsOgcUtils::expressionFromOgcFilter( childElem );
4673  if ( filter )
4674  {
4675  if ( filter->hasParserError() )
4676  {
4677  QgsDebugMsgLevel( QStringLiteral( "SLD Filter parsing error: %1" ).arg( filter->parserErrorString() ), 3 );
4678  }
4679  else
4680  {
4681  filterExp = filter->expression();
4682  }
4683  delete filter;
4684  }
4685  }
4686  else if ( childElem.localName() == QLatin1String( "MinScaleDenominator" ) )
4687  {
4688  bool ok;
4689  int v = childElem.firstChild().nodeValue().toInt( &ok );
4690  if ( ok )
4691  scaleMinDenom = v;
4692  }
4693  else if ( childElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4694  {
4695  bool ok;
4696  int v = childElem.firstChild().nodeValue().toInt( &ok );
4697  if ( ok )
4698  scaleMaxDenom = v;
4699  }
4700  else if ( childElem.localName() == QLatin1String( "TextSymbolizer" ) )
4701  {
4702  readSldTextSymbolizer( childElem, settings );
4703  }
4704 
4705  childElem = childElem.nextSiblingElement();
4706  }
4707 
4708  QgsRuleBasedLabeling::Rule *ruleLabeling = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings( settings ), scaleMinDenom, scaleMaxDenom, filterExp, label );
4709  rootRule->appendChild( ruleLabeling );
4710 
4711  ruleElem = ruleElem.nextSiblingElement();
4712  }
4713 
4714  setLabeling( new QgsRuleBasedLabeling( rootRule ) );
4715  setLabelsEnabled( true );
4716  }
4717  else
4718  {
4719  QgsDebugMsgLevel( QStringLiteral( "Info: simple labeling" ), 4 );
4720  // retrieve the TextSymbolizer element child node
4721  QDomElement textSymbolizerElem = ruleElem.firstChildElement( QStringLiteral( "TextSymbolizer" ) );
4723  if ( readSldTextSymbolizer( textSymbolizerElem, s ) )
4724  {
4726  setLabelsEnabled( true );
4727  }
4728  }
4729 }
4730 
4731 bool QgsVectorLayer::readSldTextSymbolizer( const QDomNode &node, QgsPalLayerSettings &settings ) const
4732 {
4733  if ( node.localName() != QLatin1String( "TextSymbolizer" ) )
4734  {
4735  QgsDebugMsgLevel( QStringLiteral( "Not a TextSymbolizer element: %1" ).arg( node.localName() ), 3 );
4736  return false;
4737  }
4738  QDomElement textSymbolizerElem = node.toElement();
4739  // Label
4740  QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
4741  if ( !labelElem.isNull() )
4742  {
4743  QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
4744  if ( !propertyNameElem.isNull() )
4745  {
4746  // set labeling defaults
4747 
4748  // label attribute
4749  QString labelAttribute = propertyNameElem.text();
4750  settings.fieldName = labelAttribute;
4751  settings.isExpression = false;
4752 
4753  int fieldIndex = mFields.lookupField( labelAttribute );
4754  if ( fieldIndex == -1 )
4755  {
4756  // label attribute is not in columns, check if it is an expression
4757  QgsExpression exp( labelAttribute );
4758  if ( !exp.hasEvalError() )
4759  {
4760  settings.isExpression = true;
4761  }
4762  else
4763  {
4764  QgsDebugMsgLevel( QStringLiteral( "SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
4765  }
4766  }
4767  }
4768  else
4769  {
4770  QgsDebugMsgLevel( QStringLiteral( "Info: PropertyName element not found." ), 4 );
4771  return false;
4772  }
4773  }
4774  else
4775  {
4776  QgsDebugMsgLevel( QStringLiteral( "Info: Label element not found." ), 4 );
4777  return false;
4778  }
4779 
4781  if ( textSymbolizerElem.hasAttribute( QStringLiteral( "uom" ) ) )
4782  {
4783  sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( textSymbolizerElem.attribute( QStringLiteral( "uom" ) ) );
4784  }
4785 
4786  QString fontFamily = QStringLiteral( "Sans-Serif" );
4787  int fontPointSize = 10;
4789  int fontWeight = -1;
4790  bool fontItalic = false;
4791  bool fontUnderline = false;
4792 
4793  // Font
4794  QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
4795  if ( !fontElem.isNull() )
4796  {
4797  QgsStringMap fontSvgParams = QgsSymbolLayerUtils::getSvgParameterList( fontElem );
4798  for ( QgsStringMap::iterator it = fontSvgParams.begin(); it != fontSvgParams.end(); ++it )
4799  {
4800  QgsDebugMsgLevel( QStringLiteral( "found fontSvgParams %1: %2" ).arg( it.key(), it.value() ), 4 );
4801 
4802  if ( it.key() == QLatin1String( "font-family" ) )
4803  {
4804  fontFamily = it.value();
4805  }
4806  else if ( it.key() == QLatin1String( "font-style" ) )
4807  {
4808  fontItalic = ( it.value() == QLatin1String( "italic" ) ) || ( it.value() == QLatin1String( "Italic" ) );
4809  }
4810  else if ( it.key() == QLatin1String( "font-size" ) )
4811  {
4812  bool ok;
4813  int fontSize = it.value().toInt( &ok );
4814  if ( ok )
4815  {
4816  fontPointSize = fontSize;
4817  fontUnitSize = sldUnitSize;
4818  }
4819  }
4820  else if ( it.key() == QLatin1String( "font-weight" ) )
4821  {
4822  if ( ( it.value() == QLatin1String( "bold" ) ) || ( it.value() == QLatin1String( "Bold" ) ) )
4823  fontWeight = QFont::Bold;
4824  }
4825  else if ( it.key() == QLatin1String( "font-underline" ) )
4826  {
4827  fontUnderline = ( it.value() == QLatin1String( "underline" ) ) || ( it.value() == QLatin1String( "Underline" ) );
4828  }
4829  }
4830  }
4831 
4832  QgsTextFormat format;
4833  QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
4834  font.setUnderline( fontUnderline );
4835  format.setFont( font );
4836  format.setSize( fontPointSize );
4837  format.setSizeUnit( fontUnitSize );
4838 
4839  // Fill
4840  QDomElement fillElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) );
4841  QColor textColor;
4842  Qt::BrushStyle textBrush = Qt::SolidPattern;
4843  QgsSymbolLayerUtils::fillFromSld( fillElem, textBrush, textColor );
4844  if ( textColor.isValid() )
4845  {
4846  QgsDebugMsgLevel( QStringLiteral( "Info: textColor %1." ).arg( QVariant( textColor ).toString() ), 4 );
4847  format.setColor( textColor );
4848  }
4849 
4850  QgsTextBufferSettings bufferSettings;
4851 
4852  // Halo
4853  QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
4854  if ( !haloElem.isNull() )
4855  {
4856  bufferSettings.setEnabled( true );
4857  bufferSettings.setSize( 1 );
4858 
4859  QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
4860  if ( !radiusElem.isNull() )
4861  {
4862  bool ok;
4863  double bufferSize = radiusElem.text().toDouble( &ok );
4864  if ( ok )
4865  {
4866  bufferSettings.setSize( bufferSize );
4867  bufferSettings.setSizeUnit( sldUnitSize );
4868  }
4869  }
4870 
4871  QDomElement haloFillElem = haloElem.firstChildElement( QStringLiteral( "Fill" ) );
4872  QColor bufferColor;
4873  Qt::BrushStyle bufferBrush = Qt::SolidPattern;
4874  QgsSymbolLayerUtils::fillFromSld( haloFillElem, bufferBrush, bufferColor );
4875  if ( bufferColor.isValid() )
4876  {
4877  QgsDebugMsgLevel( QStringLiteral( "Info: bufferColor %1." ).arg( QVariant( bufferColor ).toString() ), 4 );
4878  bufferSettings.setColor( bufferColor );
4879  }
4880  }
4881 
4882  // LabelPlacement
4883  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
4884  if ( !labelPlacementElem.isNull() )
4885  {
4886  // PointPlacement
4887  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
4888  if ( !pointPlacementElem.isNull() )
4889  {
4892  {
4894  }
4895 
4896  QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
4897  if ( !displacementElem.isNull() )
4898  {
4899  QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
4900  if ( !displacementXElem.isNull() )
4901  {
4902  bool ok;
4903  double xOffset = displacementXElem.text().toDouble( &ok );
4904  if ( ok )
4905  {
4906  settings.xOffset = xOffset;
4907  settings.offsetUnits = sldUnitSize;
4908  }
4909  }
4910  QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
4911  if ( !displacementYElem.isNull() )
4912  {
4913  bool ok;
4914  double yOffset = displacementYElem.text().toDouble( &ok );
4915  if ( ok )
4916  {
4917  settings.yOffset = yOffset;
4918  settings.offsetUnits = sldUnitSize;
4919  }
4920  }
4921  }
4922  QDomElement anchorPointElem = pointPlacementElem.firstChildElement( QStringLiteral( "AnchorPoint" ) );
4923  if ( !anchorPointElem.isNull() )
4924  {
4925  QDomElement anchorPointXElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointX" ) );
4926  if ( !anchorPointXElem.isNull() )
4927  {
4928  bool ok;
4929  double xOffset = anchorPointXElem.text().toDouble( &ok );
4930  if ( ok )
4931  {
4932  settings.xOffset = xOffset;
4933  settings.offsetUnits = sldUnitSize;
4934  }
4935  }
4936  QDomElement anchorPointYElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointY" ) );
4937  if ( !anchorPointYElem.isNull() )
4938  {
4939  bool ok;
4940  double yOffset = anchorPointYElem.text().toDouble( &ok );
4941  if ( ok )
4942  {
4943  settings.yOffset = yOffset;
4944  settings.offsetUnits = sldUnitSize;
4945  }
4946  }
4947  }
4948 
4949  QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
4950  if ( !rotationElem.isNull() )
4951  {
4952  bool ok;
4953  double rotation = rotationElem.text().toDouble( &ok );
4954  if ( ok )
4955  {
4956  settings.angleOffset = 360 - rotation;
4957  }
4958  }
4959  }
4960  else
4961  {
4962  // PointPlacement
4963  QDomElement linePlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "LinePlacement" ) );
4964  if ( !linePlacementElem.isNull() )
4965  {
4967  }
4968  }
4969  }
4970 
4971  // read vendor options
4972  QgsStringMap vendorOptions;
4973  QDomElement vendorOptionElem = textSymbolizerElem.firstChildElement( QStringLiteral( "VendorOption" ) );
4974  while ( !vendorOptionElem.isNull() && vendorOptionElem.localName() == QLatin1String( "VendorOption" ) )
4975  {
4976  QString optionName = vendorOptionElem.attribute( QStringLiteral( "name" ) );
4977  QString optionValue;
4978  if ( vendorOptionElem.firstChild().nodeType() == QDomNode::TextNode )
4979  {
4980  optionValue = vendorOptionElem.firstChild().nodeValue();
4981  }
4982  else
4983  {
4984  if ( vendorOptionElem.firstChild().nodeType() == QDomNode::ElementNode &&
4985  vendorOptionElem.firstChild().localName() == QLatin1String( "Literal" ) )
4986  {
4987  QgsDebugMsg( vendorOptionElem.firstChild().localName() );
4988  optionValue = vendorOptionElem.firstChild().firstChild().nodeValue();
4989  }
4990  else
4991  {
4992  QgsDebugMsg( QStringLiteral( "unexpected child of %1 named %2" ).arg( vendorOptionElem.localName(), optionName ) );
4993  }
4994  }
4995 
4996  if ( !optionName.isEmpty() && !optionValue.isEmpty() )
4997  {
4998  vendorOptions[ optionName ] = optionValue;
4999  }
5000 
5001  vendorOptionElem = vendorOptionElem.nextSiblingElement();
5002  }
5003  if ( !vendorOptions.isEmpty() )
5004  {
5005  for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
5006  {
5007  if ( it.key() == QLatin1String( "underlineText" ) && it.value() == QLatin1String( "true" ) )
5008  {
5009  font.setUnderline( true );
5010  format.setFont( font );
5011  }
5012  else if ( it.key() == QLatin1String( "strikethroughText" ) && it.value() == QLatin1String( "true" ) )
5013  {
5014  font.setStrikeOut( true );
5015  format.setFont( font );
5016  }
5017  else if ( it.key() == QLatin1String( "maxDisplacement" ) )
5018  {
5020  }
5021  else if ( it.key() == QLatin1String( "followLine" ) && it.value() == QLatin1String( "true" ) )
5022  {
5024  {
5026  }
5027  else
5028  {
5030  }
5031  }
5032  else if ( it.key() == QLatin1String( "maxAngleDelta" ) )
5033  {
5034  bool ok;
5035  double angle = it.value().toDouble( &ok );
5036  if ( ok )
5037  {
5038  settings.maxCurvedCharAngleIn = angle;
5039  settings.maxCurvedCharAngleOut = angle;
5040  }
5041  }
5042  // miscellaneous options
5043  else if ( it.key() == QLatin1String( "conflictResolution" ) && it.value() == QLatin1String( "false" ) )
5044  {
5045  settings.displayAll = true;
5046  }
5047  else if ( it.key() == QLatin1String( "forceLeftToRight" ) && it.value() == QLatin1String( "false" ) )
5048  {
5050  }
5051  else if ( it.key() == QLatin1String( "group" ) && it.value() == QLatin1String( "yes" ) )
5052  {
5053  settings.lineSettings().setMergeLines( true );
5054  }
5055  else if ( it.key() == QLatin1String( "labelAllGroup" ) && it.value() == QLatin1String( "true" ) )
5056  {
5057  settings.lineSettings().setMergeLines( true );
5058  }
5059  }
5060  }
5061 
5062  format.setBuffer( bufferSettings );
5063  settings.setFormat( format );
5064  return true;
5065 }
5066 
5068 {
5069  return mEditFormConfig;
5070 }
5071 
5073 {
5074  if ( mEditFormConfig == editFormConfig )
5075  return;
5076 
5077  mEditFormConfig = editFormConfig;
5078  mEditFormConfig.onRelationsLoaded();
5079  emit editFormConfigChanged();
5080 }
5081 
5083 {
5084  return mMapTipTemplate;
5085 }
5086 
5087 void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
5088 {
5089  if ( mMapTipTemplate == mapTip )
5090  return;
5091 
5092  mMapTipTemplate = mapTip;
5093  emit mapTipTemplateChanged();
5094 }
5095 
5097 {
5098  QgsAttributeTableConfig config = mAttributeTableConfig;
5099 
5100  if ( config.isEmpty() )
5101  config.update( fields() );
5102 
5103  return config;
5104 }
5105 
5107 {
5108  if ( mAttributeTableConfig != attributeTableConfig )
5109  {
5110  mAttributeTableConfig = attributeTableConfig;
5111  emit configChanged();
5112  }
5113 }
5114 
5116 {
5118 }
5119 
5121 {
5123 }
5124 
5126 {
5127  if ( !mDiagramLayerSettings )
5128  mDiagramLayerSettings = new QgsDiagramLayerSettings();
5129  *mDiagramLayerSettings = s;
5130 }
5131 
5133 {
5134  QgsLayerMetadataFormatter htmlFormatter( metadata() );
5135  QString myMetadata = QStringLiteral( "<html><head></head>\n<body>\n" );
5136 
5137  myMetadata += generalHtmlMetadata();
5138 
5139  // Begin Provider section
5140  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
5141  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
5142 
5143  // storage type
5144  if ( !storageType().isEmpty() )
5145  {
5146  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
5147  }
5148 
5149  // comment
5150  if ( !dataComment().isEmpty() )
5151  {
5152  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
5153  }
5154 
5155  // encoding
5156  const QgsVectorDataProvider *provider = dataProvider();
5157  if ( provider )
5158  {
5159  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + provider->encoding() + QStringLiteral( "</td></tr>\n" );
5160  }
5161 
5162  if ( isSpatial() )
5163  {
5164  // geom type
5166  if ( type < 0 || type > QgsWkbTypes::NullGeometry )
5167  {
5168  QgsDebugMsgLevel( QStringLiteral( "Invalid vector type" ), 2 );
5169  }
5170  else
5171  {
5172  QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
5174  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
5175  }
5176 
5177  // Extent
5178  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
5179  }
5180 
5181  // feature count
5182  QLocale locale = QLocale();
5183  locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
5184  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
5185  + tr( "Feature count" ) + QStringLiteral( "</td><td>" )
5186  + ( featureCount() == -1 ? tr( "unknown" ) : locale.toString( static_cast<qlonglong>( featureCount() ) ) )
5187  + QStringLiteral( "</td></tr>\n" );
5188 
5189  // End Provider section
5190  myMetadata += QLatin1String( "</table>\n<br><br>" );
5191 
5192  if ( isSpatial() )
5193  {
5194  // CRS
5195  myMetadata += crsHtmlMetadata();
5196  }
5197 
5198  // identification section
5199  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
5200  myMetadata += htmlFormatter.identificationSectionHtml( );
5201  myMetadata += QLatin1String( "<br><br>\n" );
5202 
5203  // extent section
5204  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
5205  myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
5206  myMetadata += QLatin1String( "<br><br>\n" );
5207 
5208  // Start the Access section
5209  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
5210  myMetadata += htmlFormatter.accessSectionHtml( );
5211  myMetadata += QLatin1String( "<br><br>\n" );
5212 
5213  // Fields section
5214  myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
5215 
5216  // primary key
5217  QgsAttributeList pkAttrList = primaryKeyAttributes();
5218  if ( !pkAttrList.isEmpty() )
5219  {
5220  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
5221  const auto constPkAttrList = pkAttrList;
5222  for ( int idx : constPkAttrList )
5223  {
5224  myMetadata += fields().at( idx ).name() + ' ';
5225  }
5226  myMetadata += QLatin1String( "</td></tr>\n" );
5227  }
5228 
5229  const QgsFields myFields = fields();
5230 
5231  // count fields
5232  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
5233 
5234  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
5235  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" );
5236 
5237  for ( int i = 0; i < myFields.size(); ++i )
5238  {
5239  QgsField myField = myFields.at( i );
5240  QString rowClass;
5241  if ( i % 2 )
5242  rowClass = QStringLiteral( "class=\"odd-row\"" );
5243  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" );
5244  }
5245 
5246  //close field list
5247  myMetadata += QLatin1String( "</table>\n<br><br>" );
5248 
5249  // Start the contacts section
5250  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
5251  myMetadata += htmlFormatter.contactsSectionHtml( );
5252  myMetadata += QLatin1String( "<br><br>\n" );
5253 
5254  // Start the links section
5255  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
5256  myMetadata += htmlFormatter.linksSectionHtml( );
5257  myMetadata += QLatin1String( "<br><br>\n" );
5258 
5259  // Start the history section
5260  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
5261  myMetadata += htmlFormatter.historySectionHtml( );
5262  myMetadata += QLatin1String( "<br><br>\n" );
5263 
5264  myMetadata += QLatin1String( "\n</body>\n</html>\n" );
5265  return myMetadata;
5266 }
5267 
5268 void QgsVectorLayer::invalidateSymbolCountedFlag()
5269 {
5270  mSymbolFeatureCounted = false;
5271 }
5272 
5273 void QgsVectorLayer::onFeatureCounterCompleted()
5274 {
5275  onSymbolsCounted();
5276  mFeatureCounter = nullptr;
5277 }
5278 
5279 void QgsVectorLayer::onFeatureCounterTerminated()
5280 {
5281  mFeatureCounter = nullptr;
5282 }
5283 
5284 void QgsVectorLayer::onJoinedFieldsChanged()
5285 {
5286  // some of the fields of joined layers have changed -> we need to update this layer's fields too
5287  updateFields();
5288 }
5289 
5290 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
5291 {
5292  if ( mEditCommandActive )
5293  {
5294  mDeletedFids << fid;
5295  }
5296  else
5297  {
5298  mSelectedFeatureIds.remove( fid );
5299  emit featuresDeleted( QgsFeatureIds() << fid );
5300  }
5301 
5302  emit featureDeleted( fid );
5303 }
5304 
5305 void QgsVectorLayer::onRelationsLoaded()
5306 {
5307  mEditFormConfig.onRelationsLoaded();
5308 }
5309 
5310 void QgsVectorLayer::onSymbolsCounted()
5311 {
5312  if ( mFeatureCounter )
5313  {
5314  mSymbolFeatureCounted = true;
5315  mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
5316  mSymbolFeatureIdMap = mFeatureCounter->symbolFeatureIdMap();
5318  }
5319 }
5320 
5321 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
5322 {
5323  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
5324 }
5325 
5326 QList<QgsWeakRelation> QgsVectorLayer::weakRelations() const
5327 {
5328  return mWeakRelations;
5329 }
5330 
5331 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
5332 {
5333  return QgsProviderRegistry::instance()->listStyles( mProviderKey, mDataSource, ids, names, descriptions, msgError );
5334 }
5335 
5336 QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
5337 {
5338  return QgsProviderRegistry::instance()->getStyleById( mProviderKey, mDataSource, styleId, msgError );
5339 }
5340 
5341 bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
5342 {
5343  return QgsProviderRegistry::instance()->deleteStyleById( mProviderKey, mDataSource, styleId, msgError );
5344 }
5345 
5346 
5347 void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
5348  bool useAsDefault, const QString &uiFileContent, QString &msgError )
5349 {
5350 
5351  QString sldStyle, qmlStyle;
5352  QDomDocument qmlDocument, sldDocument;
5353  QgsReadWriteContext context;
5354  exportNamedStyle( qmlDocument, msgError, context );
5355  if ( !msgError.isNull() )
5356  {
5357  return;
5358  }
5359  qmlStyle = qmlDocument.toString();
5360 
5361  this->exportSldStyle( sldDocument, msgError );
5362  if ( !msgError.isNull() )
5363  {
5364  return;
5365  }
5366  sldStyle = sldDocument.toString();
5367 
5369  mDataSource, qmlStyle, sldStyle, name,
5370  description, uiFileContent, useAsDefault, msgError );
5371 }
5372 
5373 
5374 
5375 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, QgsMapLayer::StyleCategories categories )
5376 {
5377  return loadNamedStyle( theURI, resultFlag, false, categories );
5378 }
5379 
5380 bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
5381 {
5382  bool rc = false;
5383 
5384  QString joinKey = mAuxiliaryLayerKey;
5385  if ( !key.isEmpty() )
5386  joinKey = key;
5387 
5388  if ( storage.isValid() && !joinKey.isEmpty() )
5389  {
5390  QgsAuxiliaryLayer *alayer = nullptr;
5391 
5392  int idx = fields().lookupField( joinKey );
5393 
5394  if ( idx >= 0 )
5395  {
5396  alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
5397 
5398  if ( alayer )
5399  {
5400  setAuxiliaryLayer( alayer );
5401  rc = true;
5402  }
5403  }
5404  }
5405 
5406  return rc;
5407 }
5408 
5410 {
5411  mAuxiliaryLayerKey.clear();
5412 
5413  if ( mAuxiliaryLayer )
5414  removeJoin( mAuxiliaryLayer->id() );
5415 
5416  if ( alayer )
5417  {
5418  addJoin( alayer->joinInfo() );
5419 
5420  if ( !alayer->isEditable() )
5421  alayer->startEditing();
5422 
5423  mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
5424  }
5425 
5426  mAuxiliaryLayer.reset( alayer );
5427  if ( mAuxiliaryLayer )
5428  mAuxiliaryLayer->setParent( this );
5429  updateFields();
5430 }
5431 
5433 {
5434  return mAuxiliaryLayer.get();
5435 }
5436 
5438 {
5439  return mAuxiliaryLayer.get();
5440 }
5441 
5442 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories )
5443 {
5444  QgsDataSourceUri dsUri( theURI );
5445  QString returnMessage;
5446  QString qml, errorMsg;
5447  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
5448  {
5450  }
5451  if ( !qml.isEmpty() )
5452  {
5453  QDomDocument myDocument( QStringLiteral( "qgis" ) );
5454  myDocument.setContent( qml );
5455  resultFlag = importNamedStyle( myDocument, errorMsg );
5456  returnMessage = QObject::tr( "Loaded from Provider" );
5457  }
5458  else
5459  {
5460  returnMessage = QgsMapLayer::loadNamedStyle( theURI, resultFlag, categories );
5461  }
5462 
5463  if ( resultFlag )
5464  emit styleLoaded( categories );
5465 
5466  return returnMessage;
5467 }
5468 
5469 QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
5470 {
5471  if ( mDataProvider )
5472  return mDataProvider->dependencies() + mDependencies;
5473  return mDependencies;
5474 }
5475 
5476 void QgsVectorLayer::emitDataChanged()
5477 {
5478  if ( mDataChangedFired )
5479  return;
5480 
5481  updateExtents(); // reset cached extent to reflect data changes
5482 
5483  mDataChangedFired = true;
5484  emit dataChanged();
5485  mDataChangedFired = false;
5486 }
5487 
5488 void QgsVectorLayer::onAfterCommitChangesDependency()
5489 {
5490  mDataChangedFired = true;
5491  reload();
5492  mDataChangedFired = false;
5493 }
5494 
5495 bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
5496 {
5497  QSet<QgsMapLayerDependency> deps;
5498  const auto constODeps = oDeps;
5499  for ( const QgsMapLayerDependency &dep : constODeps )
5500  {
5501  if ( dep.origin() == QgsMapLayerDependency::FromUser )
5502  deps << dep;
5503  }
5504 
5505  QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
5506 
5507  // disconnect layers that are not present in the list of dependencies anymore
5508  for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
5509  {
5510  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5511  if ( !lyr )
5512  continue;
5513  disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5514  disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5515  disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5516  disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5518  disconnect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
5519  }
5520 
5521  // assign new dependencies
5522  if ( mDataProvider )
5523  mDependencies = mDataProvider->dependencies() + deps;
5524  else
5525  mDependencies = deps;
5526  emit dependenciesChanged();
5527 
5528  // connect to new layers
5529  for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
5530  {
5531  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5532  if ( !lyr )
5533  continue;
5534  connect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5535  connect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5536  connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5537  connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5539  connect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
5540  }
5541 
5542  // if new layers are present, emit a data change
5543  if ( ! toAdd.isEmpty() )
5544  emitDataChanged();
5545 
5546  return true;
5547 }
5548 
5549 QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
5550 {
5551  if ( fieldIndex < 0 || fieldIndex >= mFields.count() || !mDataProvider )
5552  return QgsFieldConstraints::Constraints();
5553 
5554  QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
5555 
5556  // make sure provider constraints are always present!
5557  if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
5558  {
5559  constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
5560  }
5561 
5562  return constraints;
5563 }
5564 
5565 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
5566 {
5567  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
5568 
5569  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
5570  return m;
5571 
5572  QString name = mFields.at( fieldIndex ).name();
5573 
5574  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
5575  for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
5576  {
5577  if ( conIt.key().first == name )
5578  {
5579  m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
5580  }
5581  }
5582 
5583  return m;
5584 }
5585 
5587 {
5588  if ( index < 0 || index >= mFields.count() )
5589  return;
5590 
5591  QString name = mFields.at( index ).name();
5592 
5593  // add constraint to existing constraints
5594  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
5595  constraints |= constraint;
5596  mFieldConstraints.insert( name, constraints );
5597 
5598  mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
5599 
5600  updateFields();
5601 }
5602 
5604 {
5605  if ( index < 0 || index >= mFields.count() )
5606  return;
5607 
5608  QString name = mFields.at( index ).name();
5609 
5610  // remove constraint from existing constraints
5611  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
5612  constraints &= ~constraint;
5613  mFieldConstraints.insert( name, constraints );
5614 
5615  mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
5616 
5617  updateFields();
5618 }
5619 
5620 QString QgsVectorLayer::constraintExpression( int index ) const
5621 {
5622  if ( index < 0 || index >= mFields.count() )
5623  return QString();
5624 
5625  return mFields.at( index ).constraints().constraintExpression();
5626 }
5627 
5628 QString QgsVectorLayer::constraintDescription( int index ) const
5629 {
5630  if ( index < 0 || index >= mFields.count() )
5631  return QString();
5632 
5633  return mFields.at( index ).constraints().constraintDescription();
5634 }
5635 
5636 void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
5637 {
5638  if ( index < 0 || index >= mFields.count() )
5639  return;
5640 
5641  if ( expression.isEmpty() )
5642  {
5643  mFieldConstraintExpressions.remove( mFields.at( index ).name() );
5644  }
5645  else
5646  {
5647  mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
5648  }
5649  updateFields();
5650 }
5651 
5652 void QgsVectorLayer::setFieldConfigurationFlags( int index, QgsField::ConfigurationFlags flags )
5653 {
5654  if ( index < 0 || index >= mFields.count() )
5655  return;
5656 
5657  mFieldConfigurationFlags.insert( mFields.at( index ).name(), flags );
5658  updateFields();
5659 }
5660 
5662 {
5663  if ( index < 0 || index >= mFields.count() )
5664  return;
5665  QgsField::ConfigurationFlags flags = mFields.at( index ).configurationFlags();
5666  flags.setFlag( flag, active );
5668 }
5669 
5670 QgsField::ConfigurationFlags QgsVectorLayer::fieldConfigurationFlags( int index ) const
5671 {
5672 
5673  if ( index < 0 || index >= mFields.count() )
5675 
5676  return mFields.at( index ).configurationFlags();
5677 }
5678 
5680 {
5681  if ( index < 0 || index >= mFields.count() )
5682  return;
5683 
5684  if ( setup.isNull() )
5685  mFieldWidgetSetups.remove( mFields.at( index ).name() );
5686  else
5687  mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
5688  updateFields();
5689 }
5690 
5692 {
5693 
5694  if ( index < 0 || index >= mFields.count() )
5695  return QgsEditorWidgetSetup();
5696 
5697  return mFields.at( index ).editorWidgetSetup();
5698 }
5699 
5700 QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
5701 {
5703  if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
5704  {
5705  if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() )
5706  {
5707  // try to load from custom properties
5708  QgsPalLayerSettings settings;
5709  settings.readFromLayerCustomProperties( this );
5710  labeling = new QgsVectorLayerSimpleLabeling( settings );
5711  }
5712 
5713  // also clear old-style labeling config
5714  removeCustomProperty( QStringLiteral( "labeling" ) );
5715  const auto constCustomPropertyKeys = customPropertyKeys();
5716  for ( const QString &key : constCustomPropertyKeys )
5717  {
5718  if ( key.startsWith( QLatin1String( "labeling/" ) ) )
5719  removeCustomProperty( key );
5720  }
5721  }
5722 
5723  return labeling;
5724 }
5725 
5727 {
5728  return mAllowCommit;
5729 }
5730 
5731 void QgsVectorLayer::setAllowCommit( bool allowCommit )
5732 {
5733  if ( mAllowCommit == allowCommit )
5734  return;
5735 
5736  mAllowCommit = allowCommit;
5737  emit allowCommitChanged();
5738 }
5739 
5741 {
5742  return mGeometryOptions.get();
5743 }
5744 
5745 void QgsVectorLayer::setReadExtentFromXml( bool readExtentFromXml )
5746 {
5747  mReadExtentFromXml = readExtentFromXml;
5748 }
5749 
5751 {
5752  return mReadExtentFromXml;
5753 }
5754 
5755 void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
5756 {
5758  if ( tr && mEditBuffer )
5759  {
5760  qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
5761  }
5762 }
5763 
5764 QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers( bool includeAuxiliaryLayers ) const
5765 {
5766  QList<QgsVectorLayer *> layers;
5767  QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
5768  for ( i = mHandledFeatures.begin(); i != mHandledFeatures.end(); ++i )
5769  {
5770  if ( includeAuxiliaryLayers || !qobject_cast< QgsAuxiliaryLayer * >( i.key() ) )
5771  layers.append( i.key() );
5772  }
5773  return layers;
5774 }
5775 
5777 {
5778  return mHandledFeatures[layer];
5779 }
GeometryOperationResult
Success or failure of a geometry operation.
Definition: qgis.h:647
@ 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:574
@ SemiTransparentCircle
Semi-transparent circle marker.
@ Cross
Cross marker.
VectorEditResult
Specifies the result of a vector layer edit operation.
Definition: qgis.h:559
@ Success
Edit operation was successful.
@ InvalidLayer
Edit failed due to invalid layer.
SelectBehavior
Specifies how a selection should be applied.
Definition: qgis.h:545
@ 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:53
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.
@ PositionY
Y-coordinate data defined diagram position.
void readXml(const QDomElement &elem)
Reads the diagram settings from a DOM element.
void writeXml(QDomElement &layerElem, QDomDocument &doc) const
Writes the diagram settings to a DOM element.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
virtual void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const =0
Writes diagram state to a DOM element.
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads diagram state from a DOM element.
Contains configuration settings for an editor form.
void readXml(const QDomNode &node, QgsReadWriteContext &context)
Read XML information Deserialize on project load.
void writeXml(QDomNode &node, const QgsReadWriteContext &context) const
Write XML information Serialize on project save.
Holder for the widget type and its configuration for a field.
QVariantMap config() const
void clear()
Clear error messages.
Definition: qgserror.h:127
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Buffers information about expression fields for a vector layer.
void removeExpression(int index)
Remove an expression from the buffer.
void updateFields(QgsFields &flds)
Adds fields with the expressions buffered in this object to a QgsFields object.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves expressions to xml under the layer node.
void readXml(const QDomNode &layer_node)
Reads expressions from project file.
QList< QgsExpressionFieldBuffer::ExpressionField > expressions() const
void addExpression(const QString &exp, const QgsField &fld)
Add an expression to the buffer.
void updateExpression(int index, const QString &exp)
Changes the expression at a given index.
void renameExpression(int index, const QString &name)
Renames an expression field at a given index.
An expression node which takes it value from a feature's field.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString evalErrorString() const
Returns evaluation error.
QString parserErrorString() const
Returns parser error.
bool isField() const
Checks whether an expression consists only of a single field reference.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
static int expressionToLayerFieldIndex(const QString &expression, const QgsVectorLayer *layer)
Attempts to resolve an expression to a field index from the given layer.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
An interface for objects which generate feature renderers for vector layers.
static QgsFeatureRenderer * defaultRenderer(QgsWkbTypes::GeometryType geomType)
Returns a new renderer - used by default in vector layers.
Definition: qgsrenderer.cpp:79
virtual void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgsrenderer.h:326
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context)
Stores renderer properties to an XML element.
double referenceScale() const
Returns the symbology reference scale.
Definition: qgsrenderer.h:452
static QgsFeatureRenderer * loadSld(const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
void setReferenceScale(double scale)
Sets the symbology reference scale.
Definition: qgsrenderer.h:468
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ SubsetOfAttributes
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())
Adds a single feature to the sink.
virtual QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const
Returns the set of unique values contained within the specified fieldIndex from this source.
SpatialIndexPresence
Enumeration of spatial index presence states.
@ SpatialIndexUnknown
Spatial index presence cannot be determined, index may or may not exist.
FeatureAvailability
Possible return value for hasFeatures() to determine if a source is empty.
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
virtual SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source,...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:255
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsFields fields
Definition: qgsfeature.h:66
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:223
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:209
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:320
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:163
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Stores information about constraints which may be present on a field.
ConstraintStrength
Strength of constraints.
void setConstraintStrength(Constraint constraint, ConstraintStrength strength)
Sets the strength of a constraint.
void setConstraintExpression(const QString &expression, const QString &description=QString())
Set the constraint expression for the field.
@ ConstraintOriginProvider
Constraint was set at data provider.
@ ConstraintOriginLayer
Constraint was set by layer.
ConstraintStrength constraintStrength(Constraint constraint) const
Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint is not pres...
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
QString constraintExpression() const
Returns the constraint expression for the field, if set.
Constraint
Constraints which may be present on a field.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
@ ConstraintExpression
Field has an expression constraint set. See constraintExpression().
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
Q_GADGET Constraints constraints
void setConstraint(Constraint constraint, ConstraintOrigin origin=ConstraintOriginLayer)
Sets a constraint on the field.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:138
QString name
Definition: qgsfield.h:60
int precision
Definition: qgsfield.h:57
int length
Definition: qgsfield.h:56
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:88
ConfigurationFlags configurationFlags
Definition: qgsfield.h:64
QString alias
Definition: qgsfield.h:61
QgsDefaultValue defaultValueDefinition
Definition: qgsfield.h:62
QString comment
Definition: qgsfield.h:59
QgsFieldConstraints constraints
Definition: qgsfield.h:63
ConfigurationFlag
Configuration flags for fields These flags are meant to be user-configurable and are not describing a...
Definition: qgsfield.h:80
@ HideFromWfs
Fields is available if layer is served as WFS from QGIS server.
@ None
No flag is defined.
@ HideFromWms
Fields is available if layer is served as WMS from QGIS server.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:572
Container of fields for a vector layer.
Definition: qgsfields.h:45
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
@ OriginExpression
Field is calculated from an expression.
Definition: qgsfields.h:54
@ OriginEdit
Field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfields.h:53
@ OriginUnknown
It has not been specified where the field comes from.
Definition: qgsfields.h:50
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:52
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfields.h:51
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Definition: qgsfields.cpp:189
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
int size() const
Returns number of items.
Definition: qgsfields.cpp:138
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Definition: qgsfields.cpp:197
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
QStringList names() const
Returns a list with field names.
Definition: qgsfields.cpp:143
The QgsGeometryOptions class contains options to automatically adjust geometries to constraints on a ...
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
void setMergeLines(bool merge)
Sets whether connected line features with identical label text should be merged prior to generating l...
Class for metadata formatter.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
A structured metadata store for a map layer.
void combine(const QgsAbstractMetadataBase *other) override
Combines the metadata from this object with the metadata from an other object.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
This class models dependencies with or between map layers.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml()
virtual QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml()
static QgsMapLayerLegend * defaultVectorLegend(QgsVectorLayer *vl)
Create new legend implementation for vector layer.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
void dependenciesChanged()
Emitted when dependencies are changed.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QgsMapLayerLegend * legend() const
Can be nullptr.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void recalculateExtents() const
This is used to send a request that any mapcanvas using this layer update its extents.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
int mBlockStyleChangedSignal
If non-zero, the styleChanged signal should not be emitted.
Definition: qgsmaplayer.h:1992
QString providerType() const
Returns the provider type (provider key) for this layer.
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:80
void configChanged()
Emitted whenever the configuration is changed.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
void editingStarted()
Emitted when editing on this layer has started.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
friend class QgsVectorLayer
Definition: qgsmaplayer.h:2113
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
void setFlags(QgsMapLayer::LayerFlags flags)
Returns the flags for this layer.
QSet< QgsMapLayerDependency > mDependencies
List of layers that may modify this layer on modification.
Definition: qgsmaplayer.h:1953
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:1966
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
void styleChanged()
Signal emitted whenever a change affects the layer's style.
QUndoStack * undoStack()
Returns pointer to layer's undo stack.
void rendererChanged()
Signal emitted when renderer is changed.
virtual QgsError error() const
Gets current status error.
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void styleLoaded(QgsMapLayer::StyleCategories categories)
Emitted when a style has been loaded.
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void dataChanged()
Data of layer changed.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
void setName(const QString &name)
Set the display name of the layer.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
virtual void resolveReferences(QgsProject *project)
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
bool isValid
Definition: qgsmaplayer.h:81
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1925
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
Definition: qgsmaplayer.h:639
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:638
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:637
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1971
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
double minimumScale() const
Returns the minimum map scale (i.e.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as SLD style in a QDomDocument.
Q_INVOKABLE QStringList customPropertyKeys() const
Returns list of all keys within custom properties.
QgsProject * project() const
Returns the parent project if this map layer is added to a project.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:82
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1922
@ GeometryOptions
Geometry validation configuration.
Definition: qgsmaplayer.h:169
@ AttributeTable
Attribute table settings: choice and order of columns, conditional styling.
Definition: qgsmaplayer.h:166
@ LayerConfiguration
General configuration: identifiable, removable, searchable, display expression, read-only.
Definition: qgsmaplayer.h:157
@ Symbology
Symbology.
Definition: qgsmaplayer.h:158
@ MapTips
Map tips.
Definition: qgsmaplayer.h:164
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:167
@ Relations
Relations.
Definition: qgsmaplayer.h:170
@ CustomProperties
Custom properties (by plugins for instance)
Definition: qgsmaplayer.h:168
@ Actions
Actions.
Definition: qgsmaplayer.h:163
@ Forms
Feature form.
Definition: qgsmaplayer.h:162
@ Fields
Aliases, widgets, WMS/WFS, expressions, constraints, virtual fields.
Definition: qgsmaplayer.h:161
@ Legend
Legend settings (since QGIS 3.16)
Definition: qgsmaplayer.h:172
@ Diagrams
Diagrams.
Definition: qgsmaplayer.h:165
@ Labeling
Labeling.
Definition: qgsmaplayer.h:160
void layerModified()
Emitted when modifications has been done on layer.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
double maximumScale() const
Returns the maximum map scale (i.e.
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1978
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
Contains settings for how a map layer will be labeled.
double yOffset
Vertical offset of label.
double maxCurvedCharAngleIn
Maximum angle between inside curved label characters (valid range 20.0 to 60.0).
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
bool displayAll
If true, all features will be labelled even when overlaps occur.
double xOffset
Horizontal offset of label.
@ ShowAll
Show upside down for all labels, including dynamic ones.
QgsUnitTypes::RenderUnit offsetUnits
Units for offsets of label.
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
double angleOffset
Label rotation, in degrees clockwise.
double maxCurvedCharAngleOut
Maximum angle between outside curved label characters (valid range -20.0 to -95.0)
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
UpsideDownLabels upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
QString fieldName
Name of field (or an expression) to use for label text.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
A class to represent a 2D point.
Definition: qgspointxy.h:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
The derived translate() translates with QTranslator and qm file the sourceText.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:101
QgsRelationManager * relationManager
Definition: qgsproject.h:111
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:467
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
Definition for a property.
Definition: qgsproperty.h:48
@ Double
Double value (including negative values)
Definition: qgsproperty.h:58
@ Boolean
Boolean value.
Definition: qgsproperty.h:54
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
bool deleteStyleById(const QString &providerKey, const QString &uri, QString styleId, QString &errCause)
Deletes a layer style defined by styleId.
QString loadStyle(const QString &providerKey, const QString &uri, QString &errCause)
Loads a layer style defined by uri.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString getStyleById(const QString &providerKey, const QString &uri, QString styleId, QString &errCause)
Gets a layer style defined by styleId.
int listStyles(const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Lists stored layer styles in the provider defined by providerKey and uri.
bool saveStyle(const QString &providerKey, const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Saves a layer style to provider.
Allows entering a context category and takes care of leaving this category on deletion of the class.
The class is used as a container of context for various read/write operations on other objects.
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString()) const
Push a category to the stack.
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void set(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Sets the rectangle from two QgsPoints.
Definition: qgsrectangle.h:122
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
void normalize()
Normalize the rectangle so it has non-negative width/height.
Definition: qgsrectangle.h:203
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
QList< QgsRelation > referencingRelations(const QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Gets all relations where the specified layer (and field) is the referencing part (i....
void relationsLoaded()
Emitted when the relations were loaded after reading a project.
@ Normal
A normal relation.
Definition: qgsrelation.h:61
@ Composition
Fix relation, related elements are part of the parent and a parent copy will copy any children or del...
Definition: qgsrelation.h:73
Contains information about the context of a rendering operation.
double rendererScale() const
Returns the renderer map scale.
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
A child rule for QgsRuleBasedLabeling.
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
Rule based labeling for a vector layer.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
T flagValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on a flag.
Definition: qgssettings.h:331
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
Definition: qgssettings.h:253
Renders the diagrams for all features with the same settings.
Manages stored expressions regarding creation, modification and storing in the project.
bool writeXml(QDomNode &layerNode) const
Writes the stored expressions out in XML format.
bool readXml(const QDomNode &layerNode)
Reads the stored expressions in in XML format.
An interface for classes which can visit style entity (e.g.
static QgsUnitTypes::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static QgsStringMap getSvgParameterList(QDomElement &element)
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e....
bool isActive() const
Returns true if the temporal property is active.
Container for settings relating to a text buffer.
void setColor(const QColor &color)
Sets the color for the buffer.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
void setSize(double size)
Sets the size of the buffer.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
QString createSavepoint(QString &error)
creates a save point returns empty string on error returns the last created savepoint if it's not dir...
void dirtied(const QString &sql, const QString &name)
Emitted if a sql query is executed and the underlying data is modified.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:168
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
This is the base class for vector data providers.
virtual QString dataComment() const override
Returns a short comment for the data that this provider is providing access to (e....
@ ReadLayerMetadata
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
@ SelectAtId
Fast access to features using their ID.
@ DeleteFeatures
Allows deletion of features.
@ CreateLabeling
Provider can set labeling settings using backend-specific formatting information. Since QGIS 3....
@ CreateRenderer
Provider can create feature renderers using backend-specific formatting information....
QgsWkbTypes::Type wkbType() const override=0
Returns the geometry type which is returned by this layer.
virtual bool isSaveAndLoadStyleToDatabaseSupported() const
It returns false by default.
static const int EditingCapabilities
Bitmask of all provider's editing capabilities.
long long featureCount() const override=0
Number of features in the layer.
virtual QgsFeatureRenderer * createRenderer(const QVariantMap &configuration=QVariantMap()) const
Creates a new vector layer feature renderer, using provider backend specific information.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
virtual QStringList uniqueStringsMatching(int index, const QString &substring, int limit=-1, QgsFeedback *feedback=nullptr) const
Returns unique string values of an attribute which contain a specified subset string.
void raiseError(const QString &msg) const
Signals an error in this provider.
virtual bool empty() const
Returns true if the layer does not contain any feature.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
virtual void handlePostCloneOperations(QgsVectorDataProvider *source)
Handles any post-clone operations required after this vector data provider was cloned from the source...
virtual QSet< QgsMapLayerDependency > dependencies() const
Gets the list of layer ids on which this layer depends.
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
QVariant maximumValue(int index) const override
Returns the maximum value of an attribute.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QVariant minimumValue(int index) const override
Returns the minimum value of an attribute.
virtual QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, int index, const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool &ok, QgsFeatureIds *fids=nullptr) const
Calculates an aggregated value from the layer's features.
QString encoding() const
Returns the encoding which is used for accessing data.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present at the provider for a specified field index.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
virtual QgsAbstractVectorLayerLabeling * createLabeling(const QVariantMap &configuration=QVariantMap()) const
Creates labeling settings, using provider backend specific information.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
QgsVectorDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QString capabilitiesString() const
Returns the above in friendly format.
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
virtual bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
QgsFeatureIds deletedFeatureIds() const
Returns a list of deleted feature IDs which are not committed.
QgsChangedAttributesMap changedAttributeValues() const
Returns a map of features with changed attributes values which are not committed.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
virtual bool renameAttribute(int attr, const QString &newName)
Renames an attribute field (but does not commit it)
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geom)
Emitted when a feature's geometry is changed.
virtual bool addAttribute(const QgsField &field)
Adds an attribute field (but does not commit it) returns true if the field was added.
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
virtual bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues)
Changes values of attributes (but does not commit it).
QgsFeatureMap addedFeatures() const
Returns a map of new features which are not committed.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
void updateFields(QgsFields &fields)
Updates fields.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
void featureDeleted(QgsFeatureId fid)
QgsGeometryMap changedGeometries() const
Returns a map of features with changed geometries which are not committed.
QgsAttributeList deletedAttributeIds() const
Returns a list of deleted attributes fields which are not committed.
void attributeAdded(int idx)
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
virtual bool addFeature(QgsFeature &f)
Adds a feature.
virtual void rollBack()
Stop editing and discard the edits.
void attributeDeleted(int idx)
void featureAdded(QgsFeatureId fid)
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
virtual bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it)
virtual bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changed an attribute value (but does not commit it)
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature's geometry.
void layerModified()
Emitted when modifications has been done on layer.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Insert a new vertex before the given vertex number, in the given ring, item (first number is index 0)...
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
Qgis::VectorEditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0),...
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
Counts the features in a QgsVectorLayer in task.
QHash< QString, long long > symbolFeatureCountMap() const
Returns the count for each symbol.
void cancel() override
Notifies the task that it should terminate.
QHash< QString, QgsFeatureIds > symbolFeatureIdMap() const
Returns the QgsFeatureIds for each symbol.
Manages joined fields for a vector layer.
void resolveReferences(QgsProject *project)
Resolves layer IDs of joined layers using given project's available layers.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
void readXml(const QDomNode &layer_node)
Reads joins from project file.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves mVectorJoins to xml under the layer node.
const QgsVectorJoinList & vectorJoins() const
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changes attribute value in joined layers.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
bool containsJoins() const
Quick way to test if there is any join at all.
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap())
Changes attributes' values in joined layers.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features in joined layers.
void joinedFieldsChanged()
Emitted whenever the list of joined fields changes (e.g.
void updateFields(QgsFields &fields)
Updates field map with joined attributes.
bool deleteFeature(QgsFeatureId fid, QgsVectorLayer::DeleteContext *context=nullptr) const
Deletes a feature from joined layers.
Defines left outer join from our vector layer to some other vector layer.
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
QString joinLayerId() const
ID of the joined layer - may be used to resolve reference to the joined layer.
Implementation of threaded rendering for vector layers.
Basic implementation of the labeling interface.
Implementation of map layer temporal properties for vector layers.
void guessDefaultsFromFields(const QgsFields &fields)
Attempts to setup the temporal properties by scanning a set of fields and looking for standard naming...
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
static QString guessFriendlyIdentifierField(const QgsFields &fields, bool *foundFriendly=nullptr)
Given a set of fields, attempts to pick the "most useful" field for user-friendly identification of f...
Represents a vector layer which manages a vector based data sets.
void setLabeling(QgsAbstractVectorLayerLabeling *labeling)
Sets labeling configuration.
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error.
int addExpressionField(const QString &exp, const QgsField &fld)
Add a new field which is calculated by the expression specified.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
Emitted when features are added to the provider.
void setExtent(const QgsRectangle &rect) FINAL
Sets the extent.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addPart(const QList< QgsPointXY > &ring)
Adds a new part polygon to a multipart feature.
QgsRectangle sourceExtent() const FINAL
Returns the extent of all geometries from the source.
void featureBlendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when setFeatureBlendMode() is called.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const FINAL
bool isModified() const override
Returns true if the provider has been modified since the last commit.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const FINAL
void addFeatureRendererGenerator(QgsFeatureRendererGenerator *generator)
Adds a new feature renderer generator to the layer.
Q_DECL_DEPRECATED void setExcludeAttributesWfs(const QSet< QString > &att)
A set of attributes that are not advertised in WFS requests with QGIS server.
Q_INVOKABLE void selectByRect(QgsRectangle &rect, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects features found within the search rectangle (in layer's coordinates)
void removeFieldAlias(int index)
Removes an alias (a display name) for attributes to display in dialogs.
void setAuxiliaryLayer(QgsAuxiliaryLayer *layer=nullptr)
Sets the current auxiliary layer.
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer.
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
Emitted when geometry changes are saved to the provider.
void beforeCommitChanges(bool stopEditing)
Emitted before changes are committed to the data provider.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > fieldConstraintsAndStrength(int fieldIndex) const
Returns a map of constraint with their strength for a specific field of the layer.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
QSet< QgsMapLayerDependency > dependencies() const FINAL
Gets the list of dependencies.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns temporal properties associated with the vector layer.
void mapTipTemplateChanged()
Emitted when the map tip changes.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
QgsDefaultValue defaultValueDefinition(int index) const
Returns the definition of the expression used when calculating the default value for a field.
QgsExpressionContextScope * createExpressionContextScope() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) FINAL
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
QgsVectorLayerFeatureCounter * countSymbolFeatures(bool storeSymbolFids=false)
Count features for symbols.
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
QString constraintExpression(int index) const
Returns the constraint expression for for a specified field index, if set.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
QString capabilitiesString() const
Capabilities for this layer, comma separated and translated.
void deselect(QgsFeatureId featureId)
Deselects feature by its ID.
virtual int listStylesInDatabase(QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError)
Lists all the style in db split into related to the layer and not related to.
void allowCommitChanged()
Emitted whenever the allowCommitChanged() property of this layer changes.
friend class QgsVectorLayerEditBuffer
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
virtual QString loadNamedStyle(const QString &theURI, bool &resultFlag, bool loadFromLocalDb, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Loads a named style from file/local db/datasource db.
void setFieldConstraint(int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthHard)
Sets a constraint for a specified field index.
bool loadAuxiliaryLayer(const QgsAuxiliaryStorage &storage, const QString &key=QString())
Loads the auxiliary layer for this vector layer.
bool deleteFeature(QgsFeatureId fid, DeleteContext *context=nullptr)
Deletes a feature from the layer (but does not commit it).
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Inserts a new vertex before the given vertex number, in the given ring, item (first number is index 0...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QString mapTipTemplate
QString htmlMetadata() const FINAL
Obtain a formatted HTML string containing assorted metadata for this layer.
Q_INVOKABLE QgsRectangle boundingBoxOfSelected() const
Returns the bounding box of the selected features. If there is no selection, QgsRectangle(0,...
QgsFields fields() const FINAL
Returns the list of fields of this layer.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
Q_INVOKABLE QgsFeatureList selectedFeatures() const
Returns a copy of the user-selected features.
QString expressionField(int index) const
Returns the expression used for a given expression field.
bool readSymbology(const QDomNode &layerNode, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) FINAL
void removeFeatureRendererGenerator(const QString &id)
Removes the feature renderer with matching id from the layer.
friend class QgsVectorLayerEditPassthrough
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Sets the simplification settings for fast rendering of features.
void editCommandDestroyed()
Signal emitted, when an edit command is destroyed.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present for a specified field index.
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
Q_DECL_DEPRECATED QSet< QString > excludeAttributesWms() const
A set of attributes that are not advertised in WMS requests with QGIS server.
QgsFeatureIds symbolFeatureIds(const QString &legendKey) const
Ids of features rendered with specified legend key.
const QgsDiagramLayerSettings * diagramLayerSettings() const
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field index.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
virtual QString getStyleFromDatabase(const QString &styleId, QString &msgError)
Returns the named style corresponding to style id provided.
void featuresDeleted(const QgsFeatureIds &fids)
Emitted when features have been deleted.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
void setFieldConfigurationFlags(int index, QgsField::ConfigurationFlags flags)
Sets the configuration flags of the field at given index.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
void setCoordinateSystem()
Setup the coordinate system transformation for the layer.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
Emitted when features are deleted from the provider.
void updateExpressionField(int index, const QString &exp)
Changes the expression used to define an expression based (virtual) field.
~QgsVectorLayer() override
QgsCoordinateReferenceSystem sourceCrs() const FINAL
Returns the coordinate reference system for features in the source.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
bool isAuxiliaryField(int index, int &srcIndex) const
Returns true if the field comes from the auxiliary layer, false otherwise.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer's relations, where the foreign key is on this layer.
Q_DECL_DEPRECATED QSet< QString > excludeAttributesWfs() const
A set of attributes that are not advertised in WFS requests with QGIS server.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void setDefaultValueDefinition(int index, const QgsDefaultValue &definition)
Sets the definition of the expression to use when calculating the default value for a field.
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
void setAllowCommit(bool allowCommit)
Controls, if the layer is allowed to commit changes.
bool setDependencies(const QSet< QgsMapLayerDependency > &layers) FINAL
Sets the list of dependencies.
void symbolFeatureCountMapChanged()
Emitted when the feature count for symbols on this layer has been recalculated.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Qgis::VectorEditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
void setFeatureBlendMode(QPainter::CompositionMode blendMode)
Sets the blending mode used for rendering each feature.
QString constraintDescription(int index) const
Returns the descriptive name for the constraint expression for a specified field index.
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written.
void setProviderEncoding(const QString &encoding)
Sets the text encoding of the data provider.
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props=QVariantMap()) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it).
void resolveReferences(QgsProject *project) FINAL
Resolves references to other layers (kept as layer IDs after reading XML) into layer objects.
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap(), bool skipDefaultValues=false)
Changes attributes' values for a feature (but does not immediately commit the changes).
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
Q_INVOKABLE void invertSelectionInRectangle(QgsRectangle &rect)
Inverts selection of features found within the search rectangle (in layer's coordinates)
void setRenderer(QgsFeatureRenderer *r)
Sets the feature renderer which will be invoked to represent this layer in 2D map views.
Q_INVOKABLE void selectAll()
Select all the features.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
bool readExtentFromXml() const
Returns true if the extent is read from the XML document when data source has no metadata,...
QString dataComment() const
Returns a description for this layer as defined in the data provider.
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError)
Saves named and sld style of the layer to the style table in the db.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
Q_INVOKABLE int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
virtual void updateExtents(bool force=false)
Update the extents for the layer.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
void beforeEditingStarted()
Emitted before editing on this layer is started.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
Emitted when attribute value changes are saved to the provider.
QString subsetString
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
Emitted when attributes are added to the provider.
void setEditFormConfig(const QgsEditFormConfig &editFormConfig)
Sets the editFormConfig (configuration) of the form used to represent this vector layer.
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Emitted when attributes are deleted from the provider.
QString displayExpression
void displayExpressionChanged()
Emitted when the display expression changes.
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
void setEditorWidgetSetup(int index, const QgsEditorWidgetSetup &setup)
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
void setConstraintExpression(int index, const QString &expression, const QString &description=QString())
Sets the constraint expression for the specified field index.
Q_INVOKABLE bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) FINAL
bool updateFeature(QgsFeature &feature, bool skipDefaultValues=false)
Updates an existing feature in the layer, replacing the attributes and geometry for the feature with ...
Q_INVOKABLE bool commitChanges(bool stopEditing=true)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
bool setReadOnly(bool readonly=true)
Makes layer read-only (editing disabled) or not.
QgsField::ConfigurationFlags fieldConfigurationFlags(int index) const
Returns the configuration flags of the field at given index.
void editFormConfigChanged()
Will be emitted whenever the edit form configuration of this layer changes.
Q_INVOKABLE void modifySelection(const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds)
Modifies the current selection on this layer.
void reselect()
Reselects the previous set of selected features.
void select(QgsFeatureId featureId)
Selects feature by its ID.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
long long featureCount() const FINAL
Returns feature count including changes which have not yet been committed If you need only the count ...
virtual bool deleteStyleFromDatabase(const QString &styleId, QString &msgError)
Deletes a style from the database.
void setReadExtentFromXml(bool readExtentFromXml)
Flag allowing to indicate if the extent has to be read from the XML document when data source has no ...
void afterCommitChanges()
Emitted after changes are committed to the data provider.
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
bool readSld(const QDomNode &node, QString &errorMessage) FINAL
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using a list of feature IDs.
QStringList uniqueStringsMatching(int index, const QString &substring, int limit=-1, QgsFeedback *feedback=nullptr) const
Returns unique string values of an attribute which contain a specified subset string.
void raiseError(const QString &msg)
Signals an error related to this vector layer.
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
void supportsEditingChanged()
Emitted when the read only state or the data provider of this layer is changed.
SpatialIndexPresence hasSpatialIndex() const override
void readOnlyChanged()
Emitted when the read only state of this layer is changed.
void removeExpressionField(int index)
Removes an expression field.
virtual void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
static Q_DECL_DEPRECATED void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
void setFieldConfigurationFlag(int index, QgsField::ConfigurationFlag flag, bool active)
Sets the given configuration flag for the field at given index to be active or not.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
Q_INVOKABLE bool deleteSelectedFeatures(int *deletedCount=nullptr, DeleteContext *context=nullptr)
Deletes the selected features.
void setFieldAlias(int index, const QString &aliasString)
Sets an alias (a display name) for attributes to display in dialogs.
friend class QgsVectorLayerFeatureSource
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
Q_DECL_DEPRECATED void setExcludeAttributesWms(const QSet< QString > &att)
A set of attributes that are not advertised in WMS requests with QGIS server.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) FINAL
Reads vector layer specific state from project file Dom node.
FeatureAvailability hasFeatures() const FINAL
Determines if this vector layer has features.
void afterRollBack()
Emitted after changes are rolled back.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const FINAL
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
QList< QgsWeakRelation > weakRelations() const
Returns the layer's weak relations as specified in the layer's style.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
void beforeAddingExpressionField(const QString &fieldName)
Will be emitted, when an expression field is going to be added to this vector layer.
bool deleteAttributes(const QList< int > &attrs)
Deletes a list of attribute fields (but does not commit it)
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
QString sourceName() const FINAL
Returns a friendly display name for the source.
QString attributeAlias(int index) const
Returns the alias of an attribute name or a null string if there is no alias.
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
Q_INVOKABLE void removeSelection()
Clear selection.
bool allowCommit() const
Controls, if the layer is allowed to commit changes.
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
void readCustomSymbology(const QDomElement &element, QString &errorMessage)
Signal emitted whenever the symbology (QML-file) for this layer is being read.
void reload() FINAL
Synchronises with changes in the datasource.
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
bool renameAttribute(int index, const QString &newName)
Renames an attribute field (but does not commit it).
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
Q_INVOKABLE void selectByExpression(const QString &expression, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using an expression.
void beforeRollBack()
Emitted before changes are rolled back.
QgsAttributeList primaryKeyAttributes() const
Returns the list of attributes which make up the layer's primary keys.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const FINAL
Writes vector layer specific state to project file Dom node.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const FINAL
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
QString displayField() const
This is a shorthand for accessing the displayExpression if it is a simple field.
const QgsDiagramRenderer * diagramRenderer() const
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring, QgsFeatureId *featureId=nullptr)
Adds a ring to polygon/multipolygon features.
void setDiagramRenderer(QgsDiagramRenderer *r)
Sets diagram rendering object (takes ownership)
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
QgsEditFormConfig editFormConfig
QList< const QgsFeatureRendererGenerator * > featureRendererGenerators() const
Returns a list of the feature renderer generators owned by the layer.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0),...
QgsGeometry getGeometry(QgsFeatureId fid) const
Queries the layer for the geometry at the given id.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
const QgsVectorSimplifyMethod & simplifyMethod() const
Returns the simplification settings for fast rendering of features.
void beforeModifiedCheck() const
Emitted when the layer is checked for modifications. Use for last-minute additions.
Q_INVOKABLE void invertSelection()
Selects not selected features and deselects selected ones.
QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters &parameters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported,...
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setSimplifyAlgorithm(SimplifyAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
SimplifyHint
Simplification flags for fast rendering of features.
SimplifyAlgorithm
Types of local simplification algorithms that can be used.
void setMaximumScale(float maximumScale)
Sets the maximum scale at which the layer should be simplified.
@ Referencing
The layer is referencing.
@ Referenced
The layer is referenced.
static void writeXml(const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc)
Writes a weak relation infoto an XML structure.
static QgsWeakRelation readXml(const QgsVectorLayer *layer, WeakRelationType type, const QDomNode &node, const QgsPathResolver resolver)
Returns a weak relation for the given layer.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
static QString geometryDisplayString(GeometryType type) SIP_HOLDGIL
Returns a display string for a geometry type.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:39
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:47
@ UnknownCount
Provider returned an unknown feature count.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantEqual(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether they are equal, two NULL values are always treated a...
Definition: qgis.cpp:274
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:127
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
Definition: qgis.cpp:195
#define FALLTHROUGH
Definition: qgis.h:1769
QString qgsEnumValueToKey(const T &value)
Returns the value for the given key of an enum.
Definition: qgis.h:1405
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue)
Returns the value corresponding to the given keys of a flag.
Definition: qgis.h:1460
QMap< QString, QString > QgsStringMap
Definition: qgis.h:1703
QString qgsFlagValueToKeys(const T &value)
Returns the value for the given keys of a flag.
Definition: qgis.h:1448
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true)
Returns the value corresponding to the given key of an enum.
Definition: qgis.h:1418
QVector< QgsPoint > QgsPointSequence
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:463
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
bool saveStyle_t(const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
QString getStyleById_t(const QString &uri, QString styleID, QString &errCause)
bool deleteStyleById_t(const QString &uri, QString styleID, QString &errCause)
QString loadStyle_t(const QString &uri, QString &errCause)
QMap< QgsFeatureId, QgsFeature > QgsFeatureMap
A bundle of parameters controlling aggregate calculation.
Setting options for creating vector data providers.
Context for cascade delete features.
QList< QgsVectorLayer * > handledLayers(bool includeAuxiliaryLayers=true) const
Returns a list of all layers affected by the delete operation.
QMap< QgsVectorLayer *, QgsFeatureIds > mHandledFeatures
QgsFeatureIds handledFeatures(QgsVectorLayer *layer) const
Returns a list of feature IDs from the specified layer affected by the delete operation.
Setting options for loading vector layers.
QgsWkbTypes::Type fallbackWkbType
Fallback geometry type.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
QgsCoordinateTransformContext transformContext
Coordinate transform context.
QgsCoordinateReferenceSystem fallbackCrs
Fallback layer coordinate reference system.