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