QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 
103 #include "diagram/qgsdiagram.h"
104 
105 #ifdef TESTPROVIDERLIB
106 #include <dlfcn.h>
107 #endif
108 
109 typedef bool saveStyle_t(
110  const QString &uri,
111  const QString &qmlStyle,
112  const QString &sldStyle,
113  const QString &styleName,
114  const QString &styleDescription,
115  const QString &uiFileContent,
116  bool useAsDefault,
117  QString &errCause
118 );
119 
120 typedef QString loadStyle_t(
121  const QString &uri,
122  QString &errCause
123 );
124 
125 typedef int listStyles_t(
126  const QString &uri,
127  QStringList &ids,
128  QStringList &names,
129  QStringList &descriptions,
130  QString &errCause
131 );
132 
133 typedef QString getStyleById_t(
134  const QString &uri,
135  QString styleID,
136  QString &errCause
137 );
138 
139 typedef bool deleteStyleById_t(
140  const QString &uri,
141  QString styleID,
142  QString &errCause
143 );
144 
145 
146 QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
147  const QString &baseName,
148  const QString &providerKey,
149  const QgsVectorLayer::LayerOptions &options )
150  : QgsMapLayer( QgsMapLayerType::VectorLayer, baseName, vectorLayerPath )
151  , mTemporalProperties( new QgsVectorLayerTemporalProperties( this ) )
152  , mServerProperties( new QgsVectorLayerServerProperties( this ) )
153  , mAuxiliaryLayer( nullptr )
154  , mAuxiliaryLayerKey( QString() )
155  , mReadExtentFromXml( options.readExtentFromXml )
156 {
158 
159  if ( options.fallbackCrs.isValid() )
160  setCrs( options.fallbackCrs, false );
161  mWkbType = options.fallbackWkbType;
162 
163  setProviderType( providerKey );
164 
165  mGeometryOptions = qgis::make_unique<QgsGeometryOptions>();
166  mActions = new QgsActionManager( this );
167  mConditionalStyles = new QgsConditionalLayerStyles( this );
168  mStoredExpressionManager = new QgsStoredExpressionManager();
169  mStoredExpressionManager->setParent( this );
170 
171  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
172  mJoinBuffer->setParent( this );
173  connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
174 
175  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
176  // if we're given a provider type, try to create and bind one to this layer
177  if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
178  {
179  QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
180  setDataSource( vectorLayerPath, baseName, providerKey, providerOptions, options.loadDefaultStyle );
181  }
182 
183  for ( const QgsField &field : qgis::as_const( mFields ) )
184  {
185  mAttributeAliasMap.insert( field.name(), QString() );
186  }
187 
188  if ( mValid )
189  {
190  mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
191  if ( !mTemporalProperties->isActive() )
192  {
193  // didn't populate temporal properties from provider metadata, so at least try to setup some initially nice
194  // selections
195  mTemporalProperties->guessDefaultsFromFields( mFields );
196  }
197  }
198 
199  connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { triggerRepaint(); } );
200  connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
201 
203 
204  // Default simplify drawing settings
205  QgsSettings settings;
206  mSimplifyMethod.setSimplifyHints( settings.flagValue( QStringLiteral( "qgis/simplifyDrawingHints" ), mSimplifyMethod.simplifyHints(), QgsSettings::NoSection ) );
207  mSimplifyMethod.setSimplifyAlgorithm( settings.enumValue( QStringLiteral( "qgis/simplifyAlgorithm" ), mSimplifyMethod.simplifyAlgorithm() ) );
208  mSimplifyMethod.setThreshold( settings.value( QStringLiteral( "qgis/simplifyDrawingTol" ), mSimplifyMethod.threshold() ).toFloat() );
209  mSimplifyMethod.setForceLocalOptimization( settings.value( QStringLiteral( "qgis/simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ).toBool() );
210  mSimplifyMethod.setMaximumScale( settings.value( QStringLiteral( "qgis/simplifyMaxScale" ), mSimplifyMethod.maximumScale() ).toFloat() );
211 } // QgsVectorLayer ctor
212 
213 
215 {
216  emit willBeDeleted();
217 
218  mValid = false;
219 
220  delete mDataProvider;
221  delete mEditBuffer;
222  delete mJoinBuffer;
223  delete mExpressionFieldBuffer;
224  delete mLabeling;
225  delete mDiagramLayerSettings;
226  delete mDiagramRenderer;
227 
228  delete mActions;
229 
230  delete mRenderer;
231  delete mConditionalStyles;
232  delete mStoredExpressionManager;
233 
234  if ( mFeatureCounter )
235  mFeatureCounter->cancel();
236 }
237 
239 {
241  // We get the data source string from the provider when
242  // possible because some providers may have changed it
243  // directly (memory provider does that).
244  QString dataSource;
245  if ( mDataProvider )
246  {
247  dataSource = mDataProvider->dataSourceUri();
248  options.transformContext = mDataProvider->transformContext();
249  }
250  else
251  {
252  dataSource = source();
253  }
254  QgsVectorLayer *layer = new QgsVectorLayer( dataSource, name(), mProviderKey, options );
255  if ( mDataProvider && layer->dataProvider() )
256  {
257  layer->dataProvider()->handlePostCloneOperations( mDataProvider );
258  }
259  QgsMapLayer::clone( layer );
260 
261  QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
262  const auto constJoins = joins;
263  for ( const QgsVectorLayerJoinInfo &join : constJoins )
264  {
265  // do not copy join information for auxiliary layer
266  if ( !auxiliaryLayer()
267  || ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() ) )
268  layer->addJoin( join );
269  }
270 
271  layer->setProviderEncoding( dataProvider()->encoding() );
273  layer->setMapTipTemplate( mapTipTemplate() );
274  layer->setReadOnly( isReadOnly() );
275  layer->selectByIds( selectedFeatureIds() );
280  layer->setOpacity( opacity() );
282 
283  const auto constActions = actions()->actions();
284  for ( const QgsAction &action : constActions )
285  {
286  layer->actions()->addAction( action );
287  }
288 
289  if ( renderer() )
290  {
291  layer->setRenderer( renderer()->clone() );
292  }
293 
294  if ( labeling() )
295  {
296  layer->setLabeling( labeling()->clone() );
297  }
298  layer->setLabelsEnabled( labelsEnabled() );
299 
300  layer->setSimplifyMethod( simplifyMethod() );
301 
302  if ( diagramRenderer() )
303  {
305  }
306 
307  if ( diagramLayerSettings() )
308  {
310  }
311 
312  for ( int i = 0; i < fields().count(); i++ )
313  {
314  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 ( auxiliaryLayer() )
335  layer->setAuxiliaryLayer( auxiliaryLayer()->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 ( mValid && 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 ( !mValid || !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 ( !mValid )
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 ( !mValid || !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 
933 QString QgsVectorLayer::subsetString() const
934 {
935  if ( !mValid || !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 ( !mValid || !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 ( mValid && 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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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 ( !mValid || !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  if ( !mValid || !mEditBuffer || !mDataProvider )
1373  return QgsGeometry::OperationResult::LayerNotEditable;
1374 
1375  QgsVectorLayerEditUtils utils( this );
1376  return utils.splitFeatures( splitLine, topologicalEditing );
1377 }
1378 
1380 {
1381  if ( !mValid || !mEditBuffer || !mDataProvider )
1382  return -1;
1383 
1384  QgsVectorLayerEditUtils utils( this );
1385  return utils.addTopologicalPoints( geom );
1386 }
1387 
1389 {
1390  return addTopologicalPoints( QgsPoint( p ) );
1391 }
1392 
1394 {
1395  if ( !mValid || !mEditBuffer || !mDataProvider )
1396  return -1;
1397 
1398  QgsVectorLayerEditUtils utils( this );
1399  return utils.addTopologicalPoints( p );
1400 }
1401 
1403 {
1404  if ( mLabeling == labeling )
1405  return;
1406 
1407  delete mLabeling;
1408  mLabeling = labeling;
1409 }
1410 
1412 {
1413  if ( !mValid || !mDataProvider )
1414  {
1415  return false;
1416  }
1417 
1418  // allow editing if provider supports any of the capabilities
1419  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1420  {
1421  return false;
1422  }
1423 
1424  if ( mReadOnly )
1425  {
1426  return false;
1427  }
1428 
1429  if ( mEditBuffer )
1430  {
1431  // editing already underway
1432  return false;
1433  }
1434 
1435  emit beforeEditingStarted();
1436 
1437  mDataProvider->enterUpdateMode();
1438 
1439  if ( mDataProvider->transaction() )
1440  {
1441  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1442 
1443  connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
1444  }
1445  else
1446  {
1447  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1448  }
1449  // forward signals
1450  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
1451  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
1452  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1454  connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
1465 
1466  updateFields();
1467 
1468  emit editingStarted();
1469 
1470  return true;
1471 }
1472 
1474 {
1475  if ( mDataProvider )
1476  mDataProvider->setTransformContext( transformContext );
1477 }
1478 
1480 {
1481  return mDataProvider ? mDataProvider->hasSpatialIndex() : QgsFeatureSource::SpatialIndexUnknown;
1482 }
1483 
1485 {
1486  if ( mRenderer )
1487  if ( !mRenderer->accept( visitor ) )
1488  return false;
1489 
1490  if ( mLabeling )
1491  if ( !mLabeling->accept( visitor ) )
1492  return false;
1493 
1494  return true;
1495 }
1496 
1497 bool QgsVectorLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1498 {
1499  QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsVectorLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1500 
1501  //process provider key
1502  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1503 
1504  if ( pkeyNode.isNull() )
1505  {
1506  mProviderKey.clear();
1507  }
1508  else
1509  {
1510  QDomElement pkeyElt = pkeyNode.toElement();
1511  mProviderKey = pkeyElt.text();
1512  }
1513 
1514  // determine type of vector layer
1515  if ( !mProviderKey.isNull() )
1516  {
1517  // if the provider string isn't empty, then we successfully
1518  // got the stored provider
1519  }
1520  else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
1521  {
1522  mProviderKey = QStringLiteral( "postgres" );
1523  }
1524  else
1525  {
1526  mProviderKey = QStringLiteral( "ogr" );
1527  }
1528 
1529  QgsDataProvider::ProviderOptions options { context.transformContext() };
1530  if ( ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) || !setDataProvider( mProviderKey, options ) )
1531  {
1533  {
1534  QgsDebugMsg( QStringLiteral( "Could not set data provider for layer %1" ).arg( publicSource() ) );
1535  }
1536  const QDomElement elem = layer_node.toElement();
1537 
1538  // for invalid layer sources, we fallback to stored wkbType if available
1539  if ( elem.hasAttribute( QStringLiteral( "wkbType" ) ) )
1540  mWkbType = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "wkbType" ) ), mWkbType );
1541  }
1542 
1543  QDomElement pkeyElem = pkeyNode.toElement();
1544  if ( !pkeyElem.isNull() )
1545  {
1546  QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1547  if ( mDataProvider && !encodingString.isEmpty() )
1548  {
1549  mDataProvider->setEncoding( encodingString );
1550  }
1551  }
1552 
1553  // load vector joins - does not resolve references to layers yet
1554  mJoinBuffer->readXml( layer_node );
1555 
1556  updateFields();
1557 
1558  QString errorMsg;
1559  if ( !readSymbology( layer_node, errorMsg, context ) )
1560  {
1561  return false;
1562  }
1563 
1564  readStyleManager( layer_node );
1565 
1566  QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1567  QDomNodeList depsNodes = depsNode.childNodes();
1568  QSet<QgsMapLayerDependency> sources;
1569  for ( int i = 0; i < depsNodes.count(); i++ )
1570  {
1571  QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1572  sources << QgsMapLayerDependency( source );
1573  }
1574  setDependencies( sources );
1575 
1577  QDomElement legendElem = layer_node.firstChildElement( QStringLiteral( "legend" ) );
1578  if ( !legendElem.isNull() )
1579  legend->readXml( legendElem, context );
1580  setLegend( legend );
1581 
1582  // read extent
1583  if ( mReadExtentFromXml )
1584  {
1585  QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1586  if ( !extentNode.isNull() )
1587  {
1588  mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1589  }
1590  }
1591 
1592  // auxiliary layer
1593  const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
1594  const QDomElement asElem = asNode.toElement();
1595  if ( !asElem.isNull() )
1596  {
1597  mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
1598  }
1599 
1600  // QGIS Server WMS Dimensions
1601  mServerProperties->readXml( layer_node );
1602 
1603  return mValid; // should be true if read successfully
1604 
1605 } // void QgsVectorLayer::readXml
1606 
1607 
1608 void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag )
1609 {
1611  setDataSource( dataSource, baseName, provider, options, loadDefaultStyleFlag );
1612 }
1613 
1614 void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag )
1615 {
1617 
1618  mDataSource = dataSource;
1619  setName( baseName );
1620  setDataProvider( provider, options );
1621 
1622  if ( !mValid )
1623  {
1624  emit dataSourceChanged();
1625  return;
1626  }
1627 
1628  // Always set crs
1630 
1631  // reset style if loading default style, style is missing, or geometry type is has changed (and layer is valid)
1632  if ( !renderer() || !legend() || ( mValid && geomType != geometryType() ) || loadDefaultStyleFlag )
1633  {
1634  bool defaultLoadedFlag = false;
1635 
1636  if ( loadDefaultStyleFlag && isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1637  {
1638  // first try to create a renderer directly from the data provider
1639  std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1640  if ( defaultRenderer )
1641  {
1642  defaultLoadedFlag = true;
1643  setRenderer( defaultRenderer.release() );
1644  }
1645  }
1646 
1647  // else check if there is a default style / propertysheet defined
1648  // for this layer and if so apply it
1649  if ( !defaultLoadedFlag && loadDefaultStyleFlag )
1650  {
1651  loadDefaultStyle( defaultLoadedFlag );
1652  }
1653 
1654  // if the default style failed to load or was disabled use some very basic defaults
1655  if ( !defaultLoadedFlag && isSpatial() )
1656  {
1657  // add single symbol renderer
1659  }
1660 
1662 
1663  if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
1664  {
1665  std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
1666  if ( defaultLabeling )
1667  {
1668  setLabeling( defaultLabeling.release() );
1669  setLabelsEnabled( true );
1670  }
1671  }
1672  }
1673 
1674  emit dataSourceChanged();
1675  triggerRepaint();
1676 }
1677 
1678 QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
1679 {
1680  if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1681  {
1682  // first try to create a renderer directly from the data provider
1683  std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1684  if ( defaultRenderer )
1685  {
1686  resultFlag = true;
1687  setRenderer( defaultRenderer.release() );
1688  return QString();
1689  }
1690  }
1691 
1692  return QgsMapLayer::loadDefaultStyle( resultFlag );
1693 }
1694 
1695 
1696 bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options )
1697 {
1698  mProviderKey = provider;
1699  delete mDataProvider;
1700 
1701  // For Postgres provider primary key unicity is tested at construction time,
1702  // so it has to be set before initializing the provider,
1703  // this manipulation is necessary to preserve default behavior when
1704  // "trust layer metadata" project level option is set and checkPrimaryKeyUnicity
1705  // was not explicitly passed in the uri
1706  if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
1707  {
1708  const QString checkUnicityKey { QStringLiteral( "checkPrimaryKeyUnicity" ) };
1710  if ( ! uri.hasParam( checkUnicityKey ) )
1711  {
1712  uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
1713  mDataSource = uri.uri( false );
1714  }
1715  }
1716 
1717  mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, mDataSource, options ) );
1718  if ( !mDataProvider )
1719  {
1720  mValid = false;
1721  QgsDebugMsgLevel( QStringLiteral( "Unable to get data provider" ), 2 );
1722  return false;
1723  }
1724 
1725  mDataProvider->setParent( this );
1726  connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1727 
1728  QgsDebugMsgLevel( QStringLiteral( "Instantiated the data provider plugin" ), 2 );
1729 
1730  mValid = mDataProvider->isValid();
1731  if ( !mValid )
1732  {
1733  QgsDebugMsgLevel( QStringLiteral( "Invalid provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1734  return false;
1735  }
1736 
1737  if ( mDataProvider->capabilities() & QgsVectorDataProvider::ReadLayerMetadata )
1738  {
1739  setMetadata( mDataProvider->layerMetadata() );
1740  QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
1741  }
1742 
1743  // TODO: Check if the provider has the capability to send fullExtentCalculated
1744  connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
1745 
1746  // get and store the feature type
1747  mWkbType = mDataProvider->wkbType();
1748 
1749  updateFields();
1750 
1751  if ( mProviderKey == QLatin1String( "postgres" ) )
1752  {
1753  // update datasource from data provider computed one
1754  mDataSource = mDataProvider->dataSourceUri( false );
1755 
1756  QgsDebugMsgLevel( QStringLiteral( "Beautifying layer name %1" ).arg( name() ), 3 );
1757 
1758  // adjust the display name for postgres layers
1759  QRegExp reg( R"lit("[^"]+"\."([^"] + )"( \([^)]+\))?)lit" );
1760  if ( reg.indexIn( name() ) >= 0 )
1761  {
1762  QStringList stuff = reg.capturedTexts();
1763  QString lName = stuff[1];
1764 
1765  const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
1766 
1767  QMap<QString, QgsMapLayer *>::const_iterator it;
1768  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1769  ;
1770 
1771  if ( it != layers.constEnd() && stuff.size() > 2 )
1772  {
1773  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1774  }
1775 
1776  if ( !lName.isEmpty() )
1777  setName( lName );
1778  }
1779  QgsDebugMsgLevel( QStringLiteral( "Beautified layer name %1" ).arg( name() ), 3 );
1780  }
1781  else if ( mProviderKey == QLatin1String( "osm" ) )
1782  {
1783  // make sure that the "observer" has been removed from URI to avoid crashes
1784  mDataSource = mDataProvider->dataSourceUri();
1785  }
1786  else if ( provider == QLatin1String( "ogr" ) )
1787  {
1788  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1789  mDataSource = mDataProvider->dataSourceUri();
1790  if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1791  mDataSource.chop( 10 );
1792  }
1793  else if ( provider == QStringLiteral( "memory" ) )
1794  {
1795  // required so that source differs between memory layers
1796  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1797  }
1798 
1799  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::emitDataChanged );
1800  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
1801 
1802  return true;
1803 } // QgsVectorLayer:: setDataProvider
1804 
1805 
1806 
1807 
1808 /* virtual */
1809 bool QgsVectorLayer::writeXml( QDomNode &layer_node,
1810  QDomDocument &document,
1811  const QgsReadWriteContext &context ) const
1812 {
1813  // first get the layer element so that we can append the type attribute
1814 
1815  QDomElement mapLayerNode = layer_node.toElement();
1816 
1817  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1818  {
1819  QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1820  return false;
1821  }
1822 
1823  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "vector" ) );
1824 
1825  // set the geometry type
1826  mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1827  mapLayerNode.setAttribute( QStringLiteral( "wkbType" ), qgsEnumValueToKey( wkbType() ) );
1828 
1829  // add provider node
1830  if ( mDataProvider )
1831  {
1832  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1833  provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1834  QDomText providerText = document.createTextNode( providerType() );
1835  provider.appendChild( providerText );
1836  layer_node.appendChild( provider );
1837  }
1838 
1839  //save joins
1840  mJoinBuffer->writeXml( layer_node, document );
1841 
1842  // dependencies
1843  QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1844  const auto constDependencies = dependencies();
1845  for ( const QgsMapLayerDependency &dep : constDependencies )
1846  {
1847  if ( dep.type() != QgsMapLayerDependency::PresenceDependency )
1848  continue;
1849  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1850  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1851  dependenciesElement.appendChild( depElem );
1852  }
1853  layer_node.appendChild( dependenciesElement );
1854 
1855  // change dependencies
1856  QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1857  for ( const QgsMapLayerDependency &dep : constDependencies )
1858  {
1859  if ( dep.type() != QgsMapLayerDependency::DataDependency )
1860  continue;
1861  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1862  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1863  dataDependenciesElement.appendChild( depElem );
1864  }
1865  layer_node.appendChild( dataDependenciesElement );
1866 
1867  // legend
1868  if ( legend() )
1869  {
1870  QDomElement legendElement = legend()->writeXml( document, context );
1871  if ( !legendElement.isNull() )
1872  layer_node.appendChild( legendElement );
1873  }
1874 
1875  // save expression fields
1876  mExpressionFieldBuffer->writeXml( layer_node, document );
1877 
1878  writeStyleManager( layer_node, document );
1879 
1880  // auxiliary layer
1881  QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
1882  if ( mAuxiliaryLayer )
1883  {
1884  const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
1885  asElem.setAttribute( QStringLiteral( "key" ), pkField );
1886  }
1887  layer_node.appendChild( asElem );
1888 
1889  // save QGIS Server WMS Dimension definitions
1890  mServerProperties->writeXml( layer_node, document );
1891 
1892  // renderer specific settings
1893  QString errorMsg;
1894  return writeSymbology( layer_node, document, errorMsg, context );
1895 }
1896 
1897 QString QgsVectorLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1898 {
1899  QString src( source );
1900 
1901  // TODO: what about postgres, mysql and others, they should not go through writePath()
1902  if ( providerType() == QLatin1String( "spatialite" ) )
1903  {
1904  QgsDataSourceUri uri( src );
1905  QString database = context.pathResolver().writePath( uri.database() );
1906  uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
1907  src = uri.uri();
1908  }
1909  else if ( providerType() == QLatin1String( "ogr" ) )
1910  {
1911  QStringList theURIParts = src.split( '|' );
1912  theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
1913  src = theURIParts.join( QStringLiteral( "|" ) );
1914  }
1915  else if ( providerType() == QLatin1String( "gpx" ) )
1916  {
1917  QStringList theURIParts = src.split( '?' );
1918  theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
1919  src = theURIParts.join( QStringLiteral( "?" ) );
1920  }
1921  else if ( providerType() == QLatin1String( "delimitedtext" ) )
1922  {
1923  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1924  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
1925  urlDest.setQuery( urlSource.query() );
1926  src = QString::fromLatin1( urlDest.toEncoded() );
1927  }
1928  else if ( providerType() == QLatin1String( "memory" ) )
1929  {
1930  // Refetch the source from the provider, because adding fields actually changes the source for this provider.
1931  src = dataProvider()->dataSourceUri();
1932  }
1933  else if ( providerType() == QLatin1String( "virtual" ) )
1934  {
1935  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1936  QStringList theURIParts;
1937 
1938  QUrlQuery query = QUrlQuery( urlSource.query() );
1939  QList<QPair<QString, QString> > queryItems = query.queryItems();
1940 
1941  for ( int i = 0; i < queryItems.size(); i++ )
1942  {
1943  QString key = queryItems.at( i ).first;
1944  QString value = queryItems.at( i ).second;
1945  if ( key == QLatin1String( "layer" ) )
1946  {
1947  // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
1948  theURIParts = value.split( ':' );
1949  theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
1950  theURIParts[1] = context.pathResolver().writePath( theURIParts[1] );
1951  theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
1952  queryItems[i].second = theURIParts.join( QStringLiteral( ":" ) ) ;
1953  }
1954  }
1955 
1956  query.setQueryItems( queryItems );
1957 
1958  QUrl urlDest = QUrl( urlSource );
1959  urlDest.setQuery( query.query() );
1960  src = QString::fromLatin1( urlDest.toEncoded() );
1961  }
1962  else
1963  {
1964  src = context.pathResolver().writePath( src );
1965  }
1966 
1967  return src;
1968 }
1969 
1970 QString QgsVectorLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1971 {
1972  QString src( source );
1973 
1974  if ( provider == QLatin1String( "spatialite" ) )
1975  {
1976  QgsDataSourceUri uri( src );
1977  uri.setDatabase( context.pathResolver().readPath( uri.database() ) );
1978  src = uri.uri();
1979  }
1980  else if ( provider == QLatin1String( "ogr" ) )
1981  {
1982  QStringList theURIParts = src.split( '|' );
1983  theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
1984  src = theURIParts.join( QStringLiteral( "|" ) );
1985  }
1986  else if ( provider == QLatin1String( "gpx" ) )
1987  {
1988  QStringList theURIParts = src.split( '?' );
1989  theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
1990  src = theURIParts.join( QStringLiteral( "?" ) );
1991  }
1992  else if ( provider == QLatin1String( "delimitedtext" ) )
1993  {
1994  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1995 
1996  if ( !src.startsWith( QLatin1String( "file:" ) ) )
1997  {
1998  QUrl file = QUrl::fromLocalFile( src.left( src.indexOf( '?' ) ) );
1999  urlSource.setScheme( QStringLiteral( "file" ) );
2000  urlSource.setPath( file.path() );
2001  }
2002 
2003  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
2004  urlDest.setQuery( urlSource.query() );
2005  src = QString::fromLatin1( urlDest.toEncoded() );
2006  }
2007  else if ( provider == QLatin1String( "virtual" ) )
2008  {
2009  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2010  QStringList theURIParts;
2011 
2012  QUrlQuery query = QUrlQuery( urlSource.query() );
2013  QList<QPair<QString, QString> > queryItems = query.queryItems();
2014 
2015  for ( int i = 0; i < queryItems.size(); i++ )
2016  {
2017  QString key = queryItems.at( i ).first;
2018  QString value = queryItems.at( i ).second;
2019  if ( key == QLatin1String( "layer" ) )
2020  {
2021  // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
2022  theURIParts = value.split( ':' );
2023  theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2024  theURIParts[1] = context.pathResolver().readPath( theURIParts[1] );
2025  theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2026  queryItems[i].second = theURIParts.join( QStringLiteral( ":" ) ) ;
2027  }
2028  }
2029 
2030  query.setQueryItems( queryItems );
2031 
2032  QUrl urlDest = QUrl( urlSource );
2033  urlDest.setQuery( query.query() );
2034  src = QString::fromLatin1( urlDest.toEncoded() );
2035  }
2036  else
2037  {
2038  src = context.pathResolver().readPath( src );
2039  }
2040 
2041  return src;
2042 }
2043 
2044 
2045 
2047 {
2048  QgsMapLayer::resolveReferences( project );
2049  mJoinBuffer->resolveReferences( project );
2050 }
2051 
2052 
2053 bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage,
2054  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2055 {
2056  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Symbology" ) );
2057 
2058  if ( categories.testFlag( Fields ) )
2059  {
2060  if ( !mExpressionFieldBuffer )
2061  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
2062  mExpressionFieldBuffer->readXml( layerNode );
2063 
2064  updateFields();
2065  }
2066 
2067  if ( categories.testFlag( Relations ) )
2068  {
2069 
2070  const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
2071 
2072  // Restore referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2073  QDomNodeList referencedLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencedLayers" ) );
2074  if ( referencedLayersNodeList.size() > 0 )
2075  {
2076  const QDomNodeList relationNodes { referencedLayersNodeList.at( 0 ).childNodes() };
2077  for ( int i = 0; i < relationNodes.length(); ++i )
2078  {
2079  const QDomElement relationElement = relationNodes.at( i ).toElement();
2080  QList<QgsRelation::FieldPair> fieldPairs;
2081  const QDomNodeList fieldPairNodes { relationElement.elementsByTagName( QStringLiteral( "fieldPair" ) ) };
2082  for ( int j = 0; j < fieldPairNodes.length(); ++j )
2083  {
2084  const QDomElement fieldPairElement = fieldPairNodes.at( j ).toElement();
2085  fieldPairs.push_back( { fieldPairElement.attribute( QStringLiteral( "referencing" ) ),
2086  fieldPairElement.attribute( QStringLiteral( "referenced" ) ) } );
2087  }
2088  mWeakRelations.push_back( QgsWeakRelation { relationElement.attribute( QStringLiteral( "id" ) ),
2089  relationElement.attribute( QStringLiteral( "name" ) ),
2090  static_cast<QgsRelation::RelationStrength>( relationElement.attribute( QStringLiteral( "strength" ) ).toInt() ),
2091  // Referencing
2092  id(),
2093  name(),
2094  resolver.writePath( publicSource() ),
2095  providerType(),
2096  // Referenced
2097  relationElement.attribute( QStringLiteral( "layerId" ) ),
2098  relationElement.attribute( QStringLiteral( "layerName" ) ),
2099  relationElement.attribute( QStringLiteral( "dataSource" ) ),
2100  relationElement.attribute( QStringLiteral( "providerKey" ) ),
2101  fieldPairs
2102  } );
2103  }
2104  }
2105 
2106  // Restore referencing layers: relations where "this" is the parent layer (the referenced part where the FK points to)
2107  QDomNodeList referencingLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencingLayers" ) );
2108  if ( referencingLayersNodeList.size() > 0 )
2109  {
2110  const QDomNodeList relationNodes { referencingLayersNodeList.at( 0 ).childNodes() };
2111  for ( int i = 0; i < relationNodes.length(); ++i )
2112  {
2113  const QDomElement relationElement = relationNodes.at( i ).toElement();
2114  QList<QgsRelation::FieldPair> fieldPairs;
2115  const QDomNodeList fieldPairNodes { relationElement.elementsByTagName( QStringLiteral( "fieldPair" ) ) };
2116  for ( int j = 0; j < fieldPairNodes.length(); ++j )
2117  {
2118  const QDomElement fieldPairElement = fieldPairNodes.at( j ).toElement();
2119  fieldPairs.push_back( { fieldPairElement.attribute( QStringLiteral( "referencing" ) ),
2120  fieldPairElement.attribute( QStringLiteral( "referenced" ) ) } );
2121  }
2122  mWeakRelations.push_back( QgsWeakRelation { relationElement.attribute( QStringLiteral( "id" ) ),
2123  relationElement.attribute( QStringLiteral( "name" ) ),
2124  static_cast<QgsRelation::RelationStrength>( relationElement.attribute( QStringLiteral( "strength" ) ).toInt() ),
2125  // Referencing
2126  relationElement.attribute( QStringLiteral( "layerId" ) ),
2127  relationElement.attribute( QStringLiteral( "layerName" ) ),
2128  relationElement.attribute( QStringLiteral( "dataSource" ) ),
2129  relationElement.attribute( QStringLiteral( "providerKey" ) ),
2130  // Referenced
2131  id(),
2132  name(),
2133  resolver.writePath( publicSource() ),
2134  providerType(),
2135  fieldPairs
2136  } );
2137  }
2138  }
2139  }
2140 
2141  QDomElement layerElement = layerNode.toElement();
2142 
2143  readCommonStyle( layerElement, context, categories );
2144 
2145  readStyle( layerNode, errorMessage, context, categories );
2146 
2147  if ( categories.testFlag( MapTips ) )
2148  mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
2149 
2150  if ( categories.testFlag( LayerConfiguration ) )
2151  mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
2152 
2153  // Try to migrate pre QGIS 3.0 display field property
2154  QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
2155  if ( mFields.lookupField( displayField ) < 0 )
2156  {
2157  // if it's not a field, it's a maptip
2158  if ( mMapTipTemplate.isEmpty() && categories.testFlag( MapTips ) )
2159  mMapTipTemplate = displayField;
2160  }
2161  else
2162  {
2163  if ( mDisplayExpression.isEmpty() && categories.testFlag( LayerConfiguration ) )
2164  mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
2165  }
2166 
2167  // process the attribute actions
2168  if ( categories.testFlag( Actions ) )
2169  mActions->readXml( layerNode );
2170 
2171  if ( categories.testFlag( Fields ) )
2172  {
2173  mAttributeAliasMap.clear();
2174  QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
2175  if ( !aliasesNode.isNull() )
2176  {
2177  QDomElement aliasElem;
2178 
2179  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
2180  for ( int i = 0; i < aliasNodeList.size(); ++i )
2181  {
2182  aliasElem = aliasNodeList.at( i ).toElement();
2183 
2184  QString field;
2185  if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
2186  {
2187  field = aliasElem.attribute( QStringLiteral( "field" ) );
2188  }
2189  else
2190  {
2191  int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
2192 
2193  if ( index >= 0 && index < fields().count() )
2194  field = fields().at( index ).name();
2195  }
2196 
2197  QString alias;
2198 
2199  if ( !aliasElem.attribute( QStringLiteral( "name" ) ).isEmpty() )
2200  {
2201  //if it has alias
2202  alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral( "name" ) ) );
2203  QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + aliasElem.attribute( QStringLiteral( "name" ) ), 3 );
2204  }
2205  else
2206  {
2207  //if it has no alias, it should be the fields translation
2208  alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), field );
2209  QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + field, 3 );
2210  //if it gets the exact field value, there has been no translation (or not even translation loaded) - so no alias should be generated;
2211  if ( alias == aliasElem.attribute( QStringLiteral( "field" ) ) )
2212  alias.clear();
2213  }
2214 
2215  QgsDebugMsgLevel( "field " + field + " origalias " + aliasElem.attribute( QStringLiteral( "name" ) ) + " trans " + alias, 3 );
2216  mAttributeAliasMap.insert( field, alias );
2217  }
2218  }
2219 
2220  // default expressions
2221  mDefaultExpressionMap.clear();
2222  QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
2223  if ( !defaultsNode.isNull() )
2224  {
2225  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
2226  for ( int i = 0; i < defaultNodeList.size(); ++i )
2227  {
2228  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
2229 
2230  QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
2231  QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
2232  bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
2233  if ( field.isEmpty() || expression.isEmpty() )
2234  continue;
2235 
2236  mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
2237  }
2238  }
2239 
2240  // constraints
2241  mFieldConstraints.clear();
2242  mFieldConstraintStrength.clear();
2243  QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
2244  if ( !constraintsNode.isNull() )
2245  {
2246  QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2247  for ( int i = 0; i < constraintNodeList.size(); ++i )
2248  {
2249  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2250 
2251  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2252  int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
2253  if ( field.isEmpty() || constraints == 0 )
2254  continue;
2255 
2256  mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
2257 
2258  int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
2259  int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
2260  int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
2261 
2262  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
2263  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
2264  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
2265  }
2266  }
2267  mFieldConstraintExpressions.clear();
2268  QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
2269  if ( !constraintExpressionsNode.isNull() )
2270  {
2271  QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2272  for ( int i = 0; i < constraintNodeList.size(); ++i )
2273  {
2274  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2275 
2276  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2277  QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
2278  QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
2279  if ( field.isEmpty() || exp.isEmpty() )
2280  continue;
2281 
2282  mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
2283  }
2284  }
2285 
2286  updateFields();
2287 
2288  //Attributes excluded from WMS and WFS
2289  mExcludeAttributesWMS.clear();
2290  QDomNode excludeWMSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWMS" ) );
2291  if ( !excludeWMSNode.isNull() )
2292  {
2293  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2294  for ( int i = 0; i < attributeNodeList.size(); ++i )
2295  {
2296  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
2297  }
2298  }
2299 
2300  mExcludeAttributesWFS.clear();
2301  QDomNode excludeWFSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWFS" ) );
2302  if ( !excludeWFSNode.isNull() )
2303  {
2304  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2305  for ( int i = 0; i < attributeNodeList.size(); ++i )
2306  {
2307  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
2308  }
2309  }
2310 
2311  // Load editor widget configuration
2312  QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
2313  QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
2314  for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
2315  {
2316  const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
2317  const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
2318 
2319  QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
2320 
2321  const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
2322  const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
2323  const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
2324  QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
2325  if ( widgetType == QStringLiteral( "ValueRelation" ) )
2326  {
2327  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() );
2328  }
2329  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
2330  mFieldWidgetSetups[fieldName] = setup;
2331  }
2332  }
2333 
2334  if ( categories.testFlag( GeometryOptions ) )
2335  mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral( "geometryOptions" ) ) );
2336 
2337  if ( categories.testFlag( Forms ) )
2338  mEditFormConfig.readXml( layerNode, context );
2339 
2340  if ( categories.testFlag( AttributeTable ) )
2341  {
2342  mAttributeTableConfig.readXml( layerNode );
2343  mConditionalStyles->readXml( layerNode, context );
2344  mStoredExpressionManager->readXml( layerNode );
2345  }
2346 
2347  if ( categories.testFlag( CustomProperties ) )
2348  readCustomProperties( layerNode, QStringLiteral( "variable" ) );
2349 
2350  QDomElement mapLayerNode = layerNode.toElement();
2351  if ( categories.testFlag( LayerConfiguration )
2352  && mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
2353  mReadOnly = true;
2354 
2355  updateFields();
2356 
2357  return true;
2358 }
2359 
2360 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage,
2361  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2362 {
2363  bool result = true;
2364  emit readCustomSymbology( node.toElement(), errorMessage );
2365 
2366  // we must try to restore a renderer if our geometry type is unknown
2367  // as this allows the renderer to be correctly restored even for layers
2368  // with broken sources
2369  if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2370  {
2371  // try renderer v2 first
2372  if ( categories.testFlag( Symbology ) )
2373  {
2374  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
2375  if ( !rendererElement.isNull() )
2376  {
2377  QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
2378  if ( r )
2379  {
2380  setRenderer( r );
2381  }
2382  else
2383  {
2384  result = false;
2385  }
2386  }
2387  // make sure layer has a renderer - if none exists, fallback to a default renderer
2388  if ( isSpatial() && !renderer() )
2389  {
2391  }
2392  }
2393 
2394  // read labeling definition
2395  if ( categories.testFlag( Labeling ) )
2396  {
2397  QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
2399  if ( labelingElement.isNull() ||
2400  ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
2401  {
2402  // make sure we have custom properties for labeling for 2.x projects
2403  // (custom properties should be already loaded when reading the whole layer from XML,
2404  // but when reading style, custom properties are not read)
2405  readCustomProperties( node, QStringLiteral( "labeling" ) );
2406 
2407  // support for pre-QGIS 3 labeling configurations written in custom properties
2408  labeling = readLabelingFromCustomProperties();
2409  }
2410  else
2411  {
2412  labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
2413  }
2414  setLabeling( labeling );
2415 
2416  if ( node.toElement().hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
2417  mLabelsEnabled = node.toElement().attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
2418  else
2419  mLabelsEnabled = true;
2420  }
2421 
2422  if ( categories.testFlag( Symbology ) )
2423  {
2424  // get and set the blend mode if it exists
2425  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
2426  if ( !blendModeNode.isNull() )
2427  {
2428  QDomElement e = blendModeNode.toElement();
2429  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2430  }
2431 
2432  // get and set the feature blend mode if it exists
2433  QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
2434  if ( !featureBlendModeNode.isNull() )
2435  {
2436  QDomElement e = featureBlendModeNode.toElement();
2437  setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2438  }
2439  }
2440 
2441  // get and set the layer transparency and scale visibility if they exists
2442  if ( categories.testFlag( Rendering ) )
2443  {
2444  QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
2445  if ( !layerTransparencyNode.isNull() )
2446  {
2447  QDomElement e = layerTransparencyNode.toElement();
2448  setOpacity( 1.0 - e.text().toInt() / 100.0 );
2449  }
2450  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
2451  if ( !layerOpacityNode.isNull() )
2452  {
2453  QDomElement e = layerOpacityNode.toElement();
2454  setOpacity( e.text().toDouble() );
2455  }
2456 
2457  const bool hasScaleBasedVisibiliy { node.attributes().namedItem( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).nodeValue() == '1' };
2458  setScaleBasedVisibility( hasScaleBasedVisibiliy );
2459  bool ok;
2460  const double maxScale { node.attributes().namedItem( QStringLiteral( "maxScale" ) ).nodeValue().toDouble( &ok ) };
2461  if ( ok )
2462  {
2463  setMaximumScale( maxScale );
2464  }
2465  const double minScale { node.attributes().namedItem( QStringLiteral( "minScale" ) ).nodeValue().toDouble( &ok ) };
2466  if ( ok )
2467  {
2468  setMinimumScale( minScale );
2469  }
2470  }
2471 
2472  if ( categories.testFlag( Rendering ) )
2473  {
2474  QDomElement e = node.toElement();
2475 
2476  // get the simplification drawing settings
2477  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
2478  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
2479  mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
2480  mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
2481  mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
2482  }
2483 
2484  //diagram renderer and diagram layer settings
2485  if ( categories.testFlag( Diagrams ) )
2486  {
2487  delete mDiagramRenderer;
2488  mDiagramRenderer = nullptr;
2489  QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
2490  if ( !singleCatDiagramElem.isNull() )
2491  {
2492  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2493  mDiagramRenderer->readXml( singleCatDiagramElem, context );
2494  }
2495  QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
2496  if ( !linearDiagramElem.isNull() )
2497  {
2498  if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
2499  {
2500  // fix project from before QGIS 3.0
2501  int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
2502  if ( idx >= 0 && idx < mFields.count() )
2503  linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
2504  }
2505 
2506  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2507  mDiagramRenderer->readXml( linearDiagramElem, context );
2508  }
2509 
2510  if ( mDiagramRenderer )
2511  {
2512  QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
2513  if ( !diagramSettingsElem.isNull() )
2514  {
2515  bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
2516  bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
2517  bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
2518  if ( oldXPos || oldYPos || oldShow )
2519  {
2520  // fix project from before QGIS 3.0
2522  if ( oldXPos )
2523  {
2524  int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
2525  if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
2526  ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
2527  }
2528  if ( oldYPos )
2529  {
2530  int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
2531  if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
2532  ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
2533  }
2534  if ( oldShow )
2535  {
2536  int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
2537  if ( showColumn >= 0 && showColumn < mFields.count() )
2538  ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
2539  }
2540  QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
2542  {
2543  { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
2544  { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
2545  { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
2546  };
2547  ddp.writeXml( propertiesElem, defs );
2548  diagramSettingsElem.appendChild( propertiesElem );
2549  }
2550 
2551  delete mDiagramLayerSettings;
2552  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2553  mDiagramLayerSettings->readXml( diagramSettingsElem );
2554  }
2555  }
2556  }
2557  // end diagram
2558  }
2559  return result;
2560 }
2561 
2562 
2563 bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2564  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2565 {
2566  QDomElement layerElement = node.toElement();
2567  writeCommonStyle( layerElement, doc, context, categories );
2568 
2569  ( void )writeStyle( node, doc, errorMessage, context, categories );
2570 
2571  if ( categories.testFlag( GeometryOptions ) )
2572  mGeometryOptions->writeXml( node );
2573 
2574 
2575  // Relation information for both referenced and referencing sides
2576  if ( categories.testFlag( Relations ) )
2577  {
2578 
2579  const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
2580 
2581  // Store referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2582  QDomElement referencedLayersElement = doc.createElement( QStringLiteral( "referencedLayers" ) );
2583  node.appendChild( referencedLayersElement );
2584 
2585  const auto constReferencingRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
2586  for ( const auto &rel : constReferencingRelations )
2587  {
2588 
2589  QDomElement relationElement = doc.createElement( QStringLiteral( "relation" ) );
2590  referencedLayersElement.appendChild( relationElement );
2591 
2592  relationElement.setAttribute( QStringLiteral( "id" ), rel.id() );
2593  relationElement.setAttribute( QStringLiteral( "name" ), rel.name() );
2594  relationElement.setAttribute( QStringLiteral( "strength" ), rel.strength() );
2595  relationElement.setAttribute( QStringLiteral( "layerId" ), rel.referencedLayer()->id() );
2596  relationElement.setAttribute( QStringLiteral( "layerName" ), rel.referencedLayer()->name() );
2597  relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( rel.referencedLayer()->publicSource() ) );
2598  relationElement.setAttribute( QStringLiteral( "providerKey" ), rel.referencedLayer()->providerType() );
2599 
2600  const QList<QgsRelation::FieldPair> constFieldPairs { rel.fieldPairs() };
2601  for ( const QgsRelation::FieldPair &fp : constFieldPairs )
2602  {
2603  QDomElement fieldPair = doc.createElement( QStringLiteral( "fieldPair" ) );
2604  relationElement.appendChild( fieldPair );
2605  fieldPair.setAttribute( QStringLiteral( "referenced" ), fp.referencedField() );
2606  fieldPair.setAttribute( QStringLiteral( "referencing" ), fp.referencingField() );
2607  }
2608 
2609  }
2610 
2611  // Store referencing layers: relations where "this" is the parent layer (the referenced part where the FK points to)
2612  QDomElement referencingLayersElement = doc.createElement( QStringLiteral( "referencingLayers" ) );
2613  node.appendChild( referencingLayersElement );
2614 
2615  const auto constReferencedRelations { QgsProject::instance()->relationManager()->referencedRelations( this ) };
2616  for ( const auto &rel : constReferencedRelations )
2617  {
2618 
2619  QDomElement relationElement = doc.createElement( QStringLiteral( "relation" ) );
2620  referencingLayersElement.appendChild( relationElement );
2621 
2622  relationElement.setAttribute( QStringLiteral( "id" ), rel.id() );
2623  relationElement.setAttribute( QStringLiteral( "name" ), rel.name() );
2624  relationElement.setAttribute( QStringLiteral( "strength" ), rel.strength() );
2625  relationElement.setAttribute( QStringLiteral( "layerId" ), rel.referencingLayer()->id() );
2626  relationElement.setAttribute( QStringLiteral( "layerName" ), rel.referencingLayer()->name() );
2627  relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( rel.referencingLayer()->publicSource() ) );
2628  relationElement.setAttribute( QStringLiteral( "providerKey" ), rel.referencingLayer()->providerType() );
2629 
2630  const QList<QgsRelation::FieldPair> constFieldPairs { rel.fieldPairs() };
2631  for ( const QgsRelation::FieldPair &fp : constFieldPairs )
2632  {
2633  QDomElement fieldPair = doc.createElement( QStringLiteral( "fieldPair" ) );
2634  relationElement.appendChild( fieldPair );
2635  fieldPair.setAttribute( QStringLiteral( "referenced" ), fp.referencedField() );
2636  fieldPair.setAttribute( QStringLiteral( "referencing" ), fp.referencingField() );
2637  }
2638 
2639  }
2640  }
2641 
2642  if ( categories.testFlag( Fields ) )
2643  {
2644  QDomElement fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2645  node.appendChild( fieldConfigurationElement );
2646 
2647  int index = 0;
2648  for ( const QgsField &field : qgis::as_const( mFields ) )
2649  {
2650  QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2651  fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2652 
2653  fieldConfigurationElement.appendChild( fieldElement );
2654 
2655  QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
2656 
2657  // TODO : wrap this part in an if to only save if it was user-modified
2658  QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2659  fieldElement.appendChild( editWidgetElement );
2660  editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2661  QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2662 
2663  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2664  editWidgetElement.appendChild( editWidgetConfigElement );
2665  // END TODO : wrap this part in an if to only save if it was user-modified
2666 
2667  ++index;
2668  }
2669 
2670  //attribute aliases
2671  QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2672  for ( const QgsField &field : qgis::as_const( mFields ) )
2673  {
2674  QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2675  aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2676  aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2677  aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2678  aliasElem.appendChild( aliasEntryElem );
2679  }
2680  node.appendChild( aliasElem );
2681 
2682  //exclude attributes WMS
2683  QDomElement excludeWMSElem = doc.createElement( QStringLiteral( "excludeAttributesWMS" ) );
2684  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2685  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2686  {
2687  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2688  QDomText attrText = doc.createTextNode( *attWMSIt );
2689  attrElem.appendChild( attrText );
2690  excludeWMSElem.appendChild( attrElem );
2691  }
2692  node.appendChild( excludeWMSElem );
2693 
2694  //exclude attributes WFS
2695  QDomElement excludeWFSElem = doc.createElement( QStringLiteral( "excludeAttributesWFS" ) );
2696  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2697  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2698  {
2699  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2700  QDomText attrText = doc.createTextNode( *attWFSIt );
2701  attrElem.appendChild( attrText );
2702  excludeWFSElem.appendChild( attrElem );
2703  }
2704  node.appendChild( excludeWFSElem );
2705 
2706  //default expressions
2707  QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2708  for ( const QgsField &field : qgis::as_const( mFields ) )
2709  {
2710  QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2711  defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2712  defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
2713  defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2714  defaultsElem.appendChild( defaultElem );
2715  }
2716  node.appendChild( defaultsElem );
2717 
2718  // constraints
2719  QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2720  for ( const QgsField &field : qgis::as_const( mFields ) )
2721  {
2722  QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2723  constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2724  constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2725  constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2726  constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2727  constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2728  constraintsElem.appendChild( constraintElem );
2729  }
2730  node.appendChild( constraintsElem );
2731 
2732  // constraint expressions
2733  QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2734  for ( const QgsField &field : qgis::as_const( mFields ) )
2735  {
2736  QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2737  constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2738  constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2739  constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2740  constraintExpressionsElem.appendChild( constraintExpressionElem );
2741  }
2742  node.appendChild( constraintExpressionsElem );
2743 
2744  // save expression fields
2745  if ( !mExpressionFieldBuffer )
2746  {
2747  // can happen when saving style on a invalid layer
2749  dummy.writeXml( node, doc );
2750  }
2751  else
2752  {
2753  mExpressionFieldBuffer->writeXml( node, doc );
2754  }
2755  }
2756 
2757  // add attribute actions
2758  if ( categories.testFlag( Actions ) )
2759  mActions->writeXml( node );
2760 
2761  if ( categories.testFlag( AttributeTable ) )
2762  {
2763  mAttributeTableConfig.writeXml( node );
2764  mConditionalStyles->writeXml( node, doc, context );
2765  mStoredExpressionManager->writeXml( node );
2766  }
2767 
2768  if ( categories.testFlag( Forms ) )
2769  mEditFormConfig.writeXml( node, context );
2770 
2771  // save readonly state
2772  if ( categories.testFlag( LayerConfiguration ) )
2773  node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2774 
2775  // save preview expression
2776  if ( categories.testFlag( LayerConfiguration ) )
2777  {
2778  QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2779  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2780  prevExpElem.appendChild( prevExpText );
2781  node.appendChild( prevExpElem );
2782  }
2783 
2784  // save map tip
2785  if ( categories.testFlag( MapTips ) )
2786  {
2787  QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2788  QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2789  mapTipElem.appendChild( mapTipText );
2790  node.toElement().appendChild( mapTipElem );
2791  }
2792 
2793  return true;
2794 }
2795 
2796 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2797  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2798 {
2799  QDomElement mapLayerNode = node.toElement();
2800 
2801  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2802 
2803  // we must try to write the renderer if our geometry type is unknown
2804  // as this allows the renderer to be correctly restored even for layers
2805  // with broken sources
2806  if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2807  {
2808  if ( categories.testFlag( Symbology ) )
2809  {
2810  if ( mRenderer )
2811  {
2812  QDomElement rendererElement = mRenderer->save( doc, context );
2813  node.appendChild( rendererElement );
2814  }
2815  }
2816 
2817  if ( categories.testFlag( Labeling ) )
2818  {
2819  if ( mLabeling )
2820  {
2821  QDomElement labelingElement = mLabeling->save( doc, context );
2822  node.appendChild( labelingElement );
2823  }
2824  mapLayerNode.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2825  }
2826 
2827  // save the simplification drawing settings
2828  if ( categories.testFlag( Rendering ) )
2829  {
2830  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2831  mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2832  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2833  mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2834  mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2835  }
2836 
2837  //save customproperties
2838  if ( categories.testFlag( CustomProperties ) )
2839  {
2840  writeCustomProperties( node, doc );
2841  }
2842 
2843  if ( categories.testFlag( Symbology ) )
2844  {
2845  // add the blend mode field
2846  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2847  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2848  blendModeElem.appendChild( blendModeText );
2849  node.appendChild( blendModeElem );
2850 
2851  // add the feature blend mode field
2852  QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2853  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2854  featureBlendModeElem.appendChild( featureBlendModeText );
2855  node.appendChild( featureBlendModeElem );
2856  }
2857 
2858  // add the layer opacity and scale visibility
2859  if ( categories.testFlag( Rendering ) )
2860  {
2861  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
2862  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
2863  layerOpacityElem.appendChild( layerOpacityText );
2864  node.appendChild( layerOpacityElem );
2865  mapLayerNode.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
2866  mapLayerNode.setAttribute( QStringLiteral( "maxScale" ), maximumScale() );
2867  mapLayerNode.setAttribute( QStringLiteral( "minScale" ), minimumScale() );
2868  }
2869 
2870  if ( categories.testFlag( Diagrams ) && mDiagramRenderer )
2871  {
2872  mDiagramRenderer->writeXml( mapLayerNode, doc, context );
2873  if ( mDiagramLayerSettings )
2874  mDiagramLayerSettings->writeXml( mapLayerNode, doc );
2875  }
2876  }
2877  return true;
2878 }
2879 
2880 bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
2881 {
2882  // get the Name element
2883  QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2884  if ( nameElem.isNull() )
2885  {
2886  errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2887  }
2888 
2889  if ( isSpatial() )
2890  {
2891  QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
2892  if ( !r )
2893  return false;
2894 
2895  setRenderer( r );
2896 
2897  // labeling
2898  readSldLabeling( node );
2899  }
2900  return true;
2901 }
2902 
2903 bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsStringMap &props ) const
2904 {
2905  Q_UNUSED( errorMessage )
2906 
2907  QgsStringMap localProps = QgsStringMap( props );
2908  if ( hasScaleBasedVisibility() )
2909  {
2911  }
2912 
2913  if ( isSpatial() )
2914  {
2915  // store the Name element
2916  QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
2917  nameNode.appendChild( doc.createTextNode( name() ) );
2918  node.appendChild( nameNode );
2919 
2920  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
2921  node.appendChild( userStyleElem );
2922 
2923  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
2924  nameElem.appendChild( doc.createTextNode( name() ) );
2925 
2926  userStyleElem.appendChild( nameElem );
2927 
2928  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
2929  userStyleElem.appendChild( featureTypeStyleElem );
2930 
2931  mRenderer->toSld( doc, featureTypeStyleElem, localProps );
2932  if ( labelsEnabled() )
2933  {
2934  mLabeling->toSld( featureTypeStyleElem, localProps );
2935  }
2936  }
2937  return true;
2938 }
2939 
2940 
2941 bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
2942 {
2943  if ( !mEditBuffer || !mDataProvider )
2944  {
2945  return false;
2946  }
2947 
2948  if ( mGeometryOptions->isActive() )
2949  mGeometryOptions->apply( geom );
2950 
2951  updateExtents();
2952 
2953  bool result = mEditBuffer->changeGeometry( fid, geom );
2954 
2955  if ( result )
2956  {
2957  updateExtents();
2958  if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
2959  updateDefaultValues( fid );
2960  }
2961  return result;
2962 }
2963 
2964 
2965 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
2966 {
2967  bool result = false;
2968 
2969  switch ( fields().fieldOrigin( field ) )
2970  {
2971  case QgsFields::OriginJoin:
2972  result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2973  if ( result )
2974  emit attributeValueChanged( fid, field, newValue );
2975  break;
2976 
2978  case QgsFields::OriginEdit:
2980  {
2981  if ( mEditBuffer && mDataProvider )
2982  result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2983  break;
2984  }
2985 
2987  break;
2988  }
2989 
2990  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
2991  updateDefaultValues( fid );
2992 
2993  return result;
2994 }
2995 
2996 bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
2997 {
2998  bool result = true;
2999 
3000  QgsAttributeMap newValuesJoin;
3001  QgsAttributeMap oldValuesJoin;
3002 
3003  QgsAttributeMap newValuesNotJoin;
3004  QgsAttributeMap oldValuesNotJoin;
3005 
3006  for ( auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
3007  {
3008  const int field = it.key();
3009  const QVariant newValue = it.value();
3010  QVariant oldValue;
3011 
3012  if ( oldValues.contains( field ) )
3013  oldValue = oldValues[field];
3014 
3015  switch ( fields().fieldOrigin( field ) )
3016  {
3017  case QgsFields::OriginJoin:
3018  newValuesJoin[field] = newValue;
3019  oldValuesJoin[field] = oldValue;
3020  break;
3021 
3023  case QgsFields::OriginEdit:
3025  {
3026  newValuesNotJoin[field] = newValue;
3027  oldValuesNotJoin[field] = oldValue;
3028  break;
3029  }
3030 
3032  break;
3033  }
3034  }
3035 
3036  if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
3037  {
3038  result = mJoinBuffer->changeAttributeValues( fid, newValuesJoin, oldValuesJoin );
3039  }
3040 
3041  if ( ! newValuesNotJoin.isEmpty() && mEditBuffer && mDataProvider )
3042  {
3043  result &= mEditBuffer->changeAttributeValues( fid, newValues, oldValues );
3044  }
3045 
3046  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3047  {
3048  updateDefaultValues( fid );
3049  }
3050 
3051  return result;
3052 }
3053 
3055 {
3056  if ( !mEditBuffer || !mDataProvider )
3057  return false;
3058 
3059  return mEditBuffer->addAttribute( field );
3060 }
3061 
3063 {
3064  if ( attIndex < 0 || attIndex >= fields().count() )
3065  return;
3066 
3067  QString name = fields().at( attIndex ).name();
3068  mFields[ attIndex ].setAlias( QString() );
3069  if ( mAttributeAliasMap.contains( name ) )
3070  {
3071  mAttributeAliasMap.remove( name );
3072  updateFields();
3073  mEditFormConfig.setFields( mFields );
3074  emit layerModified();
3075  }
3076 }
3077 
3078 bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
3079 {
3080  if ( index < 0 || index >= fields().count() )
3081  return false;
3082 
3083  switch ( mFields.fieldOrigin( index ) )
3084  {
3086  {
3087  if ( mExpressionFieldBuffer )
3088  {
3089  int oi = mFields.fieldOriginIndex( index );
3090  mExpressionFieldBuffer->renameExpression( oi, newName );
3091  updateFields();
3092  return true;
3093  }
3094  else
3095  {
3096  return false;
3097  }
3098  }
3099 
3101  case QgsFields::OriginEdit:
3102 
3103  if ( !mEditBuffer || !mDataProvider )
3104  return false;
3105 
3106  return mEditBuffer->renameAttribute( index, newName );
3107 
3108  case QgsFields::OriginJoin:
3110  return false;
3111 
3112  }
3113 
3114  return false; // avoid warning
3115 }
3116 
3117 void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
3118 {
3119  if ( attIndex < 0 || attIndex >= fields().count() )
3120  return;
3121 
3122  QString name = fields().at( attIndex ).name();
3123 
3124  mAttributeAliasMap.insert( name, aliasString );
3125  mFields[ attIndex ].setAlias( aliasString );
3126  mEditFormConfig.setFields( mFields );
3127  emit layerModified(); // TODO[MD]: should have a different signal?
3128 }
3129 
3130 QString QgsVectorLayer::attributeAlias( int index ) const
3131 {
3132  if ( index < 0 || index >= fields().count() )
3133  return QString();
3134 
3135  return fields().at( index ).alias();
3136 }
3137 
3138 QString QgsVectorLayer::attributeDisplayName( int index ) const
3139 {
3140  if ( index >= 0 && index < mFields.count() )
3141  return mFields.at( index ).displayName();
3142  else
3143  return QString();
3144 }
3145 
3147 {
3148  return mAttributeAliasMap;
3149 }
3150 
3152 {
3153  if ( index < 0 || index >= fields().count() )
3154  return false;
3155 
3156  if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
3157  {
3158  removeExpressionField( index );
3159  return true;
3160  }
3161 
3162  if ( !mEditBuffer || !mDataProvider )
3163  return false;
3164 
3165  return mEditBuffer->deleteAttribute( index );
3166 }
3167 
3168 bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
3169 {
3170  bool deleted = false;
3171 
3172  // Remove multiple occurrences of same attribute
3173  QList<int> attrList = qgis::setToList( qgis::listToSet( attrs ) );
3174 
3175  std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
3176 
3177  for ( int attr : qgis::as_const( attrList ) )
3178  {
3179  if ( deleteAttribute( attr ) )
3180  {
3181  deleted = true;
3182  }
3183  }
3184 
3185  return deleted;
3186 }
3187 
3188 bool QgsVectorLayer::deleteFeatureCascade( QgsFeatureId fid, QgsVectorLayer::DeleteContext *context )
3189 {
3190  if ( !mEditBuffer )
3191  return false;
3192 
3193  if ( context && context->cascade )
3194  {
3195  if ( context->mHandledFeatures.contains( this ) )
3196  {
3197  QgsFeatureIds handledFeatureIds = context->mHandledFeatures.value( this );
3198  if ( handledFeatureIds.contains( fid ) )
3199  {
3200  // avoid endless recursion
3201  return false;
3202  }
3203  else
3204  {
3205  // add feature id
3206  handledFeatureIds << fid;
3207  context->mHandledFeatures.insert( this, handledFeatureIds );
3208  }
3209  }
3210  else
3211  {
3212  // add layer and feature id
3213  context->mHandledFeatures.insert( this, QgsFeatureIds() << fid );
3214  }
3215 
3216  const QList<QgsRelation> relations = context->project->relationManager()->referencedRelations( this );
3217 
3218  for ( const QgsRelation &relation : relations )
3219  {
3220  //check if composition (and not association)
3221  if ( relation.strength() == QgsRelation::Composition )
3222  {
3223  //get features connected over this relation
3224  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( getFeature( fid ) );
3225  QgsFeatureIds childFeatureIds;
3226  QgsFeature childFeature;
3227  while ( relatedFeaturesIt.nextFeature( childFeature ) )
3228  {
3229  childFeatureIds.insert( childFeature.id() );
3230  }
3231  if ( childFeatureIds.count() > 0 )
3232  {
3233  relation.referencingLayer()->startEditing();
3234  relation.referencingLayer()->deleteFeatures( childFeatureIds, context );
3235  }
3236  }
3237  }
3238  }
3239 
3240  if ( mJoinBuffer->containsJoins() )
3241  mJoinBuffer->deleteFeature( fid, context );
3242 
3243  bool res = mEditBuffer->deleteFeature( fid );
3244 
3245  return res;
3246 }
3247 
3249 {
3250  if ( !mEditBuffer )
3251  return false;
3252 
3253  bool res = deleteFeatureCascade( fid, context );
3254 
3255  if ( res )
3256  {
3257  mSelectedFeatureIds.remove( fid ); // remove it from selection
3258  updateExtents();
3259  }
3260 
3261  return res;
3262 }
3263 
3265 {
3266  bool res = true;
3267  const auto constFids = fids;
3268  for ( QgsFeatureId fid : constFids )
3269  res = deleteFeatureCascade( fid, context ) && res;
3270 
3271  if ( res )
3272  {
3273  mSelectedFeatureIds.subtract( fids ); // remove it from selection
3274  updateExtents();
3275  }
3276 
3277  return res;
3278 }
3279 
3281 {
3282  return mFields;
3283 }
3284 
3286 {
3287  QgsAttributeList pkAttributesList;
3288  if ( !mDataProvider )
3289  return pkAttributesList;
3290 
3291  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
3292  for ( int i = 0; i < mFields.count(); ++i )
3293  {
3294  if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
3295  providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
3296  pkAttributesList << i;
3297  }
3298 
3299  return pkAttributesList;
3300 }
3301 
3303 {
3304  if ( ! mDataProvider )
3305  return -1;
3306  return mDataProvider->featureCount() +
3307  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
3308 }
3309 
3311 {
3312  const QgsFeatureIds deletedFeatures( mEditBuffer ? mEditBuffer->deletedFeatureIds() : QgsFeatureIds() );
3313  const QgsFeatureMap addedFeatures( mEditBuffer ? mEditBuffer->addedFeatures() : QgsFeatureMap() );
3314 
3315  if ( mEditBuffer && !deletedFeatures.empty() )
3316  {
3317  if ( addedFeatures.size() > deletedFeatures.size() )
3318  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3319  else
3320  return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
3321  }
3322 
3323  if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider && mDataProvider->empty() )
3324  return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
3325  else
3326  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3327 }
3328 
3330 {
3331  mCommitErrors.clear();
3332 
3333  if ( !mDataProvider )
3334  {
3335  mCommitErrors << tr( "ERROR: no provider" );
3336  return false;
3337  }
3338 
3339  if ( !mEditBuffer )
3340  {
3341  mCommitErrors << tr( "ERROR: layer not editable" );
3342  return false;
3343  }
3344 
3345  emit beforeCommitChanges();
3346 
3347  if ( !mAllowCommit )
3348  return false;
3349 
3350  bool success = mEditBuffer->commitChanges( mCommitErrors );
3351 
3352  if ( success )
3353  {
3354  delete mEditBuffer;
3355  mEditBuffer = nullptr;
3356  undoStack()->clear();
3357  emit editingStopped();
3358  }
3359  else
3360  {
3361  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QStringLiteral( "\n " ) ) ) );
3362  }
3363 
3364  updateFields();
3365  mDataProvider->updateExtents();
3366 
3367  mDataProvider->leaveUpdateMode();
3368 
3369  triggerRepaint();
3370 
3371  return success;
3372 }
3373 
3374 QStringList QgsVectorLayer::commitErrors() const
3375 {
3376  return mCommitErrors;
3377 }
3378 
3379 bool QgsVectorLayer::rollBack( bool deleteBuffer )
3380 {
3381  if ( !mEditBuffer )
3382  {
3383  return false;
3384  }
3385 
3386  if ( !mDataProvider )
3387  {
3388  mCommitErrors << tr( "ERROR: no provider" );
3389  return false;
3390  }
3391 
3392  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
3393  !mEditBuffer->mAddedFeatures.isEmpty() ||
3394  !mEditBuffer->mChangedGeometries.isEmpty();
3395 
3396  emit beforeRollBack();
3397 
3398  mEditBuffer->rollBack();
3399 
3400  emit afterRollBack();
3401 
3402  if ( isModified() )
3403  {
3404  // new undo stack roll back method
3405  // old method of calling every undo could cause many canvas refreshes
3406  undoStack()->setIndex( 0 );
3407  }
3408 
3409  updateFields();
3410 
3411  if ( deleteBuffer )
3412  {
3413  delete mEditBuffer;
3414  mEditBuffer = nullptr;
3415  undoStack()->clear();
3416  }
3417  emit editingStopped();
3418 
3419  if ( rollbackExtent )
3420  updateExtents();
3421 
3422  mDataProvider->leaveUpdateMode();
3423 
3424  triggerRepaint();
3425  return true;
3426 }
3427 
3429 {
3430  return mSelectedFeatureIds.size();
3431 }
3432 
3434 {
3435  return mSelectedFeatureIds;
3436 }
3437 
3439 {
3440  QgsFeatureList features;
3441  features.reserve( mSelectedFeatureIds.count() );
3442  QgsFeature f;
3443 
3444  if ( mSelectedFeatureIds.count() <= 8 )
3445  {
3446  // for small amount of selected features, fetch them directly
3447  // because request with FilterFids would go iterate over the whole layer
3448  const auto constMSelectedFeatureIds = mSelectedFeatureIds;
3449  for ( QgsFeatureId fid : constMSelectedFeatureIds )
3450  {
3451  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
3452  features << f;
3453  }
3454  }
3455  else
3456  {
3458 
3459  while ( it.nextFeature( f ) )
3460  {
3461  features.push_back( f );
3462  }
3463  }
3464 
3465  return features;
3466 }
3467 
3469 {
3470  if ( mSelectedFeatureIds.isEmpty() )
3471  return QgsFeatureIterator();
3472 
3475 
3476  if ( mSelectedFeatureIds.count() == 1 )
3477  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
3478  else
3479  request.setFilterFids( mSelectedFeatureIds );
3480 
3481  return getFeatures( request );
3482 }
3483 
3485 {
3486  if ( !mEditBuffer || !mDataProvider )
3487  return false;
3488 
3489  if ( mGeometryOptions->isActive() )
3490  {
3491  for ( auto feature = features.begin(); feature != features.end(); ++feature )
3492  {
3493  QgsGeometry geom = feature->geometry();
3494  mGeometryOptions->apply( geom );
3495  feature->setGeometry( geom );
3496  }
3497  }
3498 
3499  bool res = mEditBuffer->addFeatures( features );
3500  updateExtents();
3501 
3502  if ( res && mJoinBuffer->containsJoins() )
3503  res = mJoinBuffer->addFeatures( features );
3504 
3505  return res;
3506 }
3507 
3509 {
3510  // if layer is not spatial, it has not CRS!
3511  setCrs( ( isSpatial() && mDataProvider ) ? mDataProvider->crs() : QgsCoordinateReferenceSystem() );
3512 }
3513 
3515 {
3517  if ( exp.isField() )
3518  {
3519  return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
3520  }
3521 
3522  return QString();
3523 }
3524 
3525 void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
3526 {
3527  if ( mDisplayExpression == displayExpression )
3528  return;
3529 
3530  mDisplayExpression = displayExpression;
3531  emit displayExpressionChanged();
3532 }
3533 
3534 QString QgsVectorLayer::displayExpression() const
3535 {
3536  if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
3537  {
3538  return mDisplayExpression;
3539  }
3540  else
3541  {
3542  QString idxName;
3543 
3544  // Check the fields and keep the first one that matches.
3545  // We assume that the user has organized the data with the
3546  // more "interesting" field names first. As such, name should
3547  // be selected before oldname, othername, etc.
3548  // This candidates list is a prioritized list of candidates ranked by "interestingness"!
3549  // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
3550  // but adding hardcoded localized variants of the strings is encouraged.
3551  static QStringList sCandidates{ QStringLiteral( "name" ),
3552  QStringLiteral( "title" ),
3553  QStringLiteral( "heibt" ),
3554  QStringLiteral( "desc" ),
3555  QStringLiteral( "nom" ),
3556  QStringLiteral( "street" ),
3557  QStringLiteral( "road" ),
3558  QStringLiteral( "id" )};
3559  for ( const QString &candidate : sCandidates )
3560  {
3561  for ( const QgsField &field : qgis::as_const( mFields ) )
3562  {
3563  QString fldName = field.name();
3564  if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
3565  {
3566  idxName = fldName;
3567  break;
3568  }
3569  }
3570 
3571  if ( !idxName.isEmpty() )
3572  break;
3573  }
3574 
3575  if ( !idxName.isNull() )
3576  {
3577  return QgsExpression::quotedColumnRef( idxName );
3578  }
3579  else
3580  {
3581  return QgsExpression::quotedColumnRef( mFields.at( 0 ).name() );
3582  }
3583  }
3584 }
3585 
3587 {
3588  return ( mEditBuffer && mDataProvider );
3589 }
3590 
3592 {
3595 }
3596 
3597 bool QgsVectorLayer::isReadOnly() const
3598 {
3599  return mReadOnly;
3600 }
3601 
3602 bool QgsVectorLayer::setReadOnly( bool readonly )
3603 {
3604  // exit if the layer is in editing mode
3605  if ( readonly && mEditBuffer )
3606  return false;
3607 
3608  mReadOnly = readonly;
3609  emit readOnlyChanged();
3610  return true;
3611 }
3612 
3614 {
3615  emit beforeModifiedCheck();
3616  return mEditBuffer && mEditBuffer->isModified();
3617 }
3618 
3619 bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
3620 {
3621  bool auxiliaryField = false;
3622  srcIndex = -1;
3623 
3624  if ( !auxiliaryLayer() )
3625  return auxiliaryField;
3626 
3627  if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
3628  {
3629  const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
3630 
3631  if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
3632  auxiliaryField = true;
3633  }
3634 
3635  return auxiliaryField;
3636 }
3637 
3639 {
3640  // we must allow setting a renderer if our geometry type is unknown
3641  // as this allows the renderer to be correctly set even for layers
3642  // with broken sources
3643  if ( !isSpatial() && mWkbType != QgsWkbTypes::Unknown )
3644  return;
3645 
3646  if ( r != mRenderer )
3647  {
3648  delete mRenderer;
3649  mRenderer = r;
3650  mSymbolFeatureCounted = false;
3651  mSymbolFeatureCountMap.clear();
3652  mSymbolFeatureIdMap.clear();
3653 
3654  emit rendererChanged();
3655  emit styleChanged();
3656  }
3657 }
3658 
3659 void QgsVectorLayer::beginEditCommand( const QString &text )
3660 {
3661  if ( !mDataProvider )
3662  {
3663  return;
3664  }
3665  if ( mDataProvider->transaction() )
3666  {
3667  QString ignoredError;
3668  mDataProvider->transaction()->createSavepoint( ignoredError );
3669  }
3670  undoStack()->beginMacro( text );
3671  mEditCommandActive = true;
3672  emit editCommandStarted( text );
3673 }
3674 
3676 {
3677  if ( !mDataProvider )
3678  {
3679  return;
3680  }
3681  undoStack()->endMacro();
3682  mEditCommandActive = false;
3683  if ( !mDeletedFids.isEmpty() )
3684  {
3685  emit featuresDeleted( mDeletedFids );
3686  mDeletedFids.clear();
3687  }
3688  emit editCommandEnded();
3689 }
3690 
3692 {
3693  if ( !mDataProvider )
3694  {
3695  return;
3696  }
3697  undoStack()->endMacro();
3698  undoStack()->undo();
3699 
3700  // it's not directly possible to pop the last command off the stack (the destroyed one)
3701  // and delete, so we add a dummy obsolete command to force this to occur.
3702  // Pushing the new command deletes the destroyed one, and since the new
3703  // command is obsolete it's automatically deleted by the undo stack.
3704  std::unique_ptr< QUndoCommand > command = qgis::make_unique< QUndoCommand >();
3705  command->setObsolete( true );
3706  undoStack()->push( command.release() );
3707 
3708  mEditCommandActive = false;
3709  mDeletedFids.clear();
3710  emit editCommandDestroyed();
3711 }
3712 
3714 {
3715  return mJoinBuffer->addJoin( joinInfo );
3716 }
3717 
3718 
3719 bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
3720 {
3721  return mJoinBuffer->removeJoin( joinLayerId );
3722 }
3723 
3724 const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
3725 {
3726  return mJoinBuffer->vectorJoins();
3727 }
3728 
3729 int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
3730 {
3731  emit beforeAddingExpressionField( fld.name() );
3732  mExpressionFieldBuffer->addExpression( exp, fld );
3733  updateFields();
3734  int idx = mFields.indexFromName( fld.name() );
3735  emit attributeAdded( idx );
3736  return idx;
3737 }
3738 
3740 {
3741  emit beforeRemovingExpressionField( index );
3742  int oi = mFields.fieldOriginIndex( index );
3743  mExpressionFieldBuffer->removeExpression( oi );
3744  updateFields();
3745  emit attributeDeleted( index );
3746 }
3747 
3748 QString QgsVectorLayer::expressionField( int index ) const
3749 {
3750  int oi = mFields.fieldOriginIndex( index );
3751  if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
3752  return QString();
3753 
3754  return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
3755 }
3756 
3757 void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
3758 {
3759  int oi = mFields.fieldOriginIndex( index );
3760  mExpressionFieldBuffer->updateExpression( oi, exp );
3761 }
3762 
3764 {
3765  if ( !mDataProvider )
3766  return;
3767 
3768  QgsFields oldFields = mFields;
3769 
3770  mFields = mDataProvider->fields();
3771 
3772  // added / removed fields
3773  if ( mEditBuffer )
3774  mEditBuffer->updateFields( mFields );
3775 
3776  // joined fields
3777  if ( mJoinBuffer->containsJoins() )
3778  mJoinBuffer->updateFields( mFields );
3779 
3780  if ( mExpressionFieldBuffer )
3781  mExpressionFieldBuffer->updateFields( mFields );
3782 
3783  // set aliases and default values
3784  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
3785  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
3786  {
3787  int index = mFields.lookupField( aliasIt.key() );
3788  if ( index < 0 )
3789  continue;
3790 
3791  mFields[ index ].setAlias( aliasIt.value() );
3792  }
3793 
3794  // Update default values
3795  mDefaultValueOnUpdateFields.clear();
3796  QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
3797  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
3798  {
3799  int index = mFields.lookupField( defaultIt.key() );
3800  if ( index < 0 )
3801  continue;
3802 
3803  mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
3804  if ( defaultIt.value().applyOnUpdate() )
3805  mDefaultValueOnUpdateFields.insert( index );
3806  }
3807 
3808  QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
3809  for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
3810  {
3811  int index = mFields.lookupField( constraintIt.key() );
3812  if ( index < 0 )
3813  continue;
3814 
3815  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3816 
3817  // always keep provider constraints intact
3818  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
3820  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
3822  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
3824  mFields[ index ].setConstraints( constraints );
3825  }
3826 
3827  QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
3828  for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
3829  {
3830  int index = mFields.lookupField( constraintExpIt.key() );
3831  if ( index < 0 )
3832  continue;
3833 
3834  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3835 
3836  // always keep provider constraints intact
3838  continue;
3839 
3840  constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
3841  mFields[ index ].setConstraints( constraints );
3842  }
3843 
3844  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
3845  for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
3846  {
3847  int index = mFields.lookupField( constraintStrengthIt.key().first );
3848  if ( index < 0 )
3849  continue;
3850 
3851  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3852 
3853  // always keep provider constraints intact
3855  continue;
3856 
3857  constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
3858  mFields[ index ].setConstraints( constraints );
3859  }
3860 
3861  auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
3862  for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
3863  {
3864  int index = mFields.indexOf( fieldWidgetIterator.key() );
3865  if ( index < 0 )
3866  continue;
3867 
3868  mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
3869  }
3870 
3871  if ( oldFields != mFields )
3872  {
3873  emit updatedFields();
3874  mEditFormConfig.setFields( mFields );
3875  }
3876 }
3877 
3878 
3879 QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
3880 {
3881  if ( index < 0 || index >= mFields.count() || !mDataProvider )
3882  return QVariant();
3883 
3884  QString expression = mFields.at( index ).defaultValueDefinition().expression();
3885  if ( expression.isEmpty() )
3886  return mDataProvider->defaultValue( index );
3887 
3888  QgsExpressionContext *evalContext = context;
3889  std::unique_ptr< QgsExpressionContext > tempContext;
3890  if ( !evalContext )
3891  {
3892  // no context passed, so we create a default one
3894  evalContext = tempContext.get();
3895  }
3896 
3897  if ( feature.isValid() )
3898  {
3900  featScope->setFeature( feature );
3901  featScope->setFields( feature.fields() );
3902  evalContext->appendScope( featScope );
3903  }
3904 
3905  QVariant val;
3906  QgsExpression exp( expression );
3907  exp.prepare( evalContext );
3908  if ( exp.hasEvalError() )
3909  {
3910  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
3911  }
3912  else
3913  {
3914  val = exp.evaluate( evalContext );
3915  }
3916 
3917  if ( feature.isValid() )
3918  {
3919  delete evalContext->popScope();
3920  }
3921 
3922  return val;
3923 }
3924 
3926 {
3927  if ( index < 0 || index >= mFields.count() )
3928  return;
3929 
3930  if ( definition.isValid() )
3931  {
3932  mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
3933  }
3934  else
3935  {
3936  mDefaultExpressionMap.remove( mFields.at( index ).name() );
3937  }
3938  updateFields();
3939 }
3940 
3942 {
3943  if ( index < 0 || index >= mFields.count() )
3944  return QgsDefaultValue();
3945  else
3946  return mFields.at( index ).defaultValueDefinition();
3947 }
3948 
3949 QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
3950 {
3951  QSet<QVariant> uniqueValues;
3952  if ( !mDataProvider )
3953  {
3954  return uniqueValues;
3955  }
3956 
3957  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3958  switch ( origin )
3959  {
3961  return uniqueValues;
3962 
3963  case QgsFields::OriginProvider: //a provider field
3964  {
3965  uniqueValues = mDataProvider->uniqueValues( index, limit );
3966 
3967  if ( mEditBuffer )
3968  {
3969  QSet<QString> vals;
3970  const auto constUniqueValues = uniqueValues;
3971  for ( const QVariant &v : constUniqueValues )
3972  {
3973  vals << v.toString();
3974  }
3975 
3976  QgsFeatureMap added = mEditBuffer->addedFeatures();
3977  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3978  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3979  {
3980  addedIt.next();
3981  QVariant v = addedIt.value().attribute( index );
3982  if ( v.isValid() )
3983  {
3984  QString vs = v.toString();
3985  if ( !vals.contains( vs ) )
3986  {
3987  vals << vs;
3988  uniqueValues << v;
3989  }
3990  }
3991  }
3992 
3993  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3994  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3995  {
3996  it.next();
3997  QVariant v = it.value().value( index );
3998  if ( v.isValid() )
3999  {
4000  QString vs = v.toString();
4001  if ( !vals.contains( vs ) )
4002  {
4003  vals << vs;
4004  uniqueValues << v;
4005  }
4006  }
4007  }
4008  }
4009 
4010  return uniqueValues;
4011  }
4012 
4013  case QgsFields::OriginEdit:
4014  // the layer is editable, but in certain cases it can still be avoided going through all features
4015  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
4016  mEditBuffer->mAddedFeatures.isEmpty() &&
4017  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
4018  mEditBuffer->mChangedAttributeValues.isEmpty() )
4019  {
4020  uniqueValues = mDataProvider->uniqueValues( index, limit );
4021  return uniqueValues;
4022  }
4023  FALLTHROUGH
4024  //we need to go through each feature
4025  case QgsFields::OriginJoin:
4027  {
4028  QgsAttributeList attList;
4029  attList << index;
4030 
4033  .setSubsetOfAttributes( attList ) );
4034 
4035  QgsFeature f;
4036  QVariant currentValue;
4037  QHash<QString, QVariant> val;
4038  while ( fit.nextFeature( f ) )
4039  {
4040  currentValue = f.attribute( index );
4041  val.insert( currentValue.toString(), currentValue );
4042  if ( limit >= 0 && val.size() >= limit )
4043  {
4044  break;
4045  }
4046  }
4047 
4048  return qgis::listToSet( val.values() );
4049  }
4050  }
4051 
4052  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
4053  return uniqueValues;
4054 }
4055 
4056 QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
4057 {
4058  QStringList results;
4059  if ( !mDataProvider )
4060  {
4061  return results;
4062  }
4063 
4064  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4065  switch ( origin )
4066  {
4068  return results;
4069 
4070  case QgsFields::OriginProvider: //a provider field
4071  {
4072  results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4073 
4074  if ( mEditBuffer )
4075  {
4076  QgsFeatureMap added = mEditBuffer->addedFeatures();
4077  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4078  while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4079  {
4080  addedIt.next();
4081  QVariant v = addedIt.value().attribute( index );
4082  if ( v.isValid() )
4083  {
4084  QString vs = v.toString();
4085  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4086  {
4087  results << vs;
4088  }
4089  }
4090  }
4091 
4092  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4093  while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4094  {
4095  it.next();
4096  QVariant v = it.value().value( index );
4097  if ( v.isValid() )
4098  {
4099  QString vs = v.toString();
4100  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4101  {
4102  results << vs;
4103  }
4104  }
4105  }
4106  }
4107 
4108  return results;
4109  }
4110 
4111  case QgsFields::OriginEdit:
4112  // the layer is editable, but in certain cases it can still be avoided going through all features
4113  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
4114  mEditBuffer->mAddedFeatures.isEmpty() &&
4115  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
4116  mEditBuffer->mChangedAttributeValues.isEmpty() )
4117  {
4118  return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4119  }
4120  FALLTHROUGH
4121  //we need to go through each feature
4122  case QgsFields::OriginJoin:
4124  {
4125  QgsAttributeList attList;
4126  attList << index;
4127 
4128  QgsFeatureRequest request;
4129  request.setSubsetOfAttributes( attList );
4131  QString fieldName = mFields.at( index ).name();
4132  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
4133  QgsFeatureIterator fit = getFeatures( request );
4134 
4135  QgsFeature f;
4136  QString currentValue;
4137  while ( fit.nextFeature( f ) )
4138  {
4139  currentValue = f.attribute( index ).toString();
4140  if ( !results.contains( currentValue ) )
4141  results << currentValue;
4142 
4143  if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
4144  {
4145  break;
4146  }
4147  }
4148 
4149  return results;
4150  }
4151  }
4152 
4153  Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
4154  return results;
4155 }
4156 
4157 QVariant QgsVectorLayer::minimumValue( int index ) const
4158 {
4159  return minimumOrMaximumValue( index, true );
4160 }
4161 
4162 QVariant QgsVectorLayer::maximumValue( int index ) const
4163 {
4164  return minimumOrMaximumValue( index, false );
4165 }
4166 
4167 QVariant QgsVectorLayer::minimumOrMaximumValue( int index, bool minimum ) const
4168 {
4169  if ( !mDataProvider )
4170  {
4171  return QVariant();
4172  }
4173 
4174  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4175 
4176  switch ( origin )
4177  {
4179  return QVariant();
4180 
4181  case QgsFields::OriginProvider: //a provider field
4182  {
4183  QVariant val = minimum ? mDataProvider->minimumValue( index ) : mDataProvider->maximumValue( index );
4184  if ( mEditBuffer )
4185  {
4186  QgsFeatureMap added = mEditBuffer->addedFeatures();
4187  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4188  while ( addedIt.hasNext() )
4189  {
4190  addedIt.next();
4191  QVariant v = addedIt.value().attribute( index );
4192  if ( ( v.isValid() && minimum && qgsVariantLessThan( v, val ) )
4193  || ( v.isValid() && !minimum && qgsVariantGreaterThan( v, val ) ) )
4194  {
4195  val = v;
4196  }
4197  }
4198 
4199  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4200  while ( it.hasNext() )
4201  {
4202  it.next();
4203  QVariant v = it.value().value( index );
4204  if ( ( v.isValid() && minimum && qgsVariantLessThan( v, val ) )
4205  || ( v.isValid() && !minimum && qgsVariantGreaterThan( v, val ) ) )
4206  {
4207  val = v;
4208  }
4209  }
4210  }
4211  return val;
4212  }
4213 
4214  case QgsFields::OriginEdit:
4215  {
4216  // the layer is editable, but in certain cases it can still be avoided going through all features
4217  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
4218  mEditBuffer->mAddedFeatures.isEmpty() &&
4219  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
4220  mEditBuffer->mChangedAttributeValues.isEmpty() )
4221  {
4222  return minimum ? mDataProvider->minimumValue( index ) : mDataProvider->maximumValue( index );
4223  }
4224  }
4225  FALLTHROUGH
4226  // no choice but to go through all features
4228  case QgsFields::OriginJoin:
4229  {
4230  // we need to go through each feature
4231  QgsAttributeList attList;
4232  attList << index;
4233 
4236  .setSubsetOfAttributes( attList ) );
4237 
4238  QgsFeature f;
4239  QVariant value;
4240  QVariant currentValue;
4241  bool firstValue = true;
4242  while ( fit.nextFeature( f ) )
4243  {
4244  currentValue = f.attribute( index );
4245  if ( currentValue.isNull() )
4246  continue;
4247  if ( firstValue )
4248  {
4249  value = currentValue;
4250  firstValue = false;
4251  }
4252  else
4253  {
4254  if ( ( minimum && qgsVariantLessThan( currentValue, value ) ) || ( !minimum && qgsVariantGreaterThan( currentValue, value ) ) )
4255  {
4256  value = currentValue;
4257  }
4258  }
4259  }
4260  return value;
4261  }
4262  }
4263 
4264  Q_ASSERT_X( false, "QgsVectorLayer::minimumOrMaximum()", "Unknown source of the field!" );
4265  return QVariant();
4266 }
4267 
4268 QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
4270  bool *ok, QgsFeatureIds *fids ) const
4271 {
4272  if ( ok )
4273  *ok = false;
4274 
4275  if ( !mDataProvider )
4276  {
4277  return QVariant();
4278  }
4279 
4280  // test if we are calculating based on a field
4281  int attrIndex = mFields.lookupField( fieldOrExpression );
4282  if ( attrIndex >= 0 )
4283  {
4284  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
4285  // to the provider itself
4286  QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
4287  if ( origin == QgsFields::OriginProvider )
4288  {
4289  bool providerOk = false;
4290  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk, fids );
4291  if ( providerOk )
4292  {
4293  // provider handled calculation
4294  if ( ok )
4295  *ok = true;
4296  return val;
4297  }
4298  }
4299  }
4300 
4301  // fallback to using aggregate calculator to determine aggregate
4302  QgsAggregateCalculator c( this );
4303  if ( fids )
4304  c.setFidsFilter( *fids );
4305  c.setParameters( parameters );
4306  return c.calculate( aggregate, fieldOrExpression, context, ok );
4307 }
4308 
4309 void QgsVectorLayer::setFeatureBlendMode( QPainter::CompositionMode featureBlendMode )
4310 {
4311  if ( mFeatureBlendMode == featureBlendMode )
4312  return;
4313 
4314  mFeatureBlendMode = featureBlendMode;
4316  emit styleChanged();
4317 }
4318 
4319 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
4320 {
4321  return mFeatureBlendMode;
4322 }
4323 
4324 void QgsVectorLayer::setOpacity( double opacity )
4325 {
4326  if ( qgsDoubleNear( mLayerOpacity, opacity ) )
4327  return;
4328  mLayerOpacity = opacity;
4329  emit opacityChanged( opacity );
4330  emit styleChanged();
4331 }
4332 
4333 double QgsVectorLayer::opacity() const
4334 {
4335  return mLayerOpacity;
4336 }
4337 
4338 
4339 
4340 void QgsVectorLayer::readSldLabeling( const QDomNode &node )
4341 {
4342  setLabeling( nullptr ); // start with no labeling
4343  setLabelsEnabled( false );
4344 
4345  QDomElement element = node.toElement();
4346  if ( element.isNull() )
4347  return;
4348 
4349  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
4350  if ( userStyleElem.isNull() )
4351  {
4352  QgsDebugMsgLevel( QStringLiteral( "Info: UserStyle element not found." ), 4 );
4353  return;
4354  }
4355 
4356  QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
4357  if ( featTypeStyleElem.isNull() )
4358  {
4359  QgsDebugMsgLevel( QStringLiteral( "Info: FeatureTypeStyle element not found." ), 4 );
4360  return;
4361  }
4362 
4363  // create empty FeatureTypeStyle element to merge TextSymbolizer's Rule's from all FeatureTypeStyle's
4364  QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode( false ).toElement();
4365 
4366  // use the RuleRenderer when more rules are present or the rule
4367  // has filters or min/max scale denominators set,
4368  // otherwise use the Simple labeling
4369  bool needRuleBasedLabeling = false;
4370  int ruleCount = 0;
4371 
4372  while ( !featTypeStyleElem.isNull() )
4373  {
4374  QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
4375  while ( !ruleElem.isNull() )
4376  {
4377  // test rule children element to check if we need to create RuleRenderer
4378  // and if the rule has a symbolizer
4379  bool hasTextSymbolizer = false;
4380  bool hasRuleBased = false;
4381  QDomElement ruleChildElem = ruleElem.firstChildElement();
4382  while ( !ruleChildElem.isNull() )
4383  {
4384  // rule has filter or min/max scale denominator, use the RuleRenderer
4385  if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
4386  ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
4387  ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4388  {
4389  hasRuleBased = true;
4390  }
4391  // rule has a renderer symbolizer, not a text symbolizer
4392  else if ( ruleChildElem.localName() == QLatin1String( "TextSymbolizer" ) )
4393  {
4394  QgsDebugMsgLevel( QStringLiteral( "Info: TextSymbolizer element found" ), 4 );
4395  hasTextSymbolizer = true;
4396  }
4397 
4398  ruleChildElem = ruleChildElem.nextSiblingElement();
4399  }
4400 
4401  if ( hasTextSymbolizer )
4402  {
4403  ruleCount++;
4404 
4405  // append a clone of all Rules to the merged FeatureTypeStyle element
4406  mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
4407 
4408  if ( hasRuleBased )
4409  {
4410  QgsDebugMsgLevel( QStringLiteral( "Info: Filter or Min/MaxScaleDenominator element found: need a RuleBasedLabeling" ), 4 );
4411  needRuleBasedLabeling = true;
4412  }
4413  }
4414 
4415  // more rules present, use the RuleRenderer
4416  if ( ruleCount > 1 )
4417  {
4418  QgsDebugMsgLevel( QStringLiteral( "Info: More Rule elements found: need a RuleBasedLabeling" ), 4 );
4419  needRuleBasedLabeling = true;
4420  }
4421 
4422  // not use the rule based labeling if no rules with textSymbolizer
4423  if ( ruleCount == 0 )
4424  {
4425  needRuleBasedLabeling = false;
4426  }
4427 
4428  ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
4429  }
4430  featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral( "FeatureTypeStyle" ) );
4431  }
4432 
4433  if ( ruleCount == 0 )
4434  {
4435  QgsDebugMsgLevel( QStringLiteral( "Info: No TextSymbolizer element." ), 4 );
4436  return;
4437  }
4438 
4439  QDomElement ruleElem = mergedFeatTypeStyle.firstChildElement( QStringLiteral( "Rule" ) );
4440 
4441  if ( needRuleBasedLabeling )
4442  {
4443  QgsDebugMsgLevel( QStringLiteral( "Info: rule based labeling" ), 4 );
4444  QgsRuleBasedLabeling::Rule *rootRule = new QgsRuleBasedLabeling::Rule( nullptr );
4445  while ( !ruleElem.isNull() )
4446  {
4447 
4448  QString label, description, filterExp;
4449  int scaleMinDenom = 0, scaleMaxDenom = 0;
4450  QgsPalLayerSettings settings;
4451 
4452  // retrieve the Rule element child nodes
4453  QDomElement childElem = ruleElem.firstChildElement();
4454  while ( !childElem.isNull() )
4455  {
4456  if ( childElem.localName() == QLatin1String( "Name" ) )
4457  {
4458  // <se:Name> tag contains the rule identifier,
4459  // so prefer title tag for the label property value
4460  if ( label.isEmpty() )
4461  label = childElem.firstChild().nodeValue();
4462  }
4463  else if ( childElem.localName() == QLatin1String( "Description" ) )
4464  {
4465  // <se:Description> can contains a title and an abstract
4466  QDomElement titleElem = childElem.firstChildElement( QStringLiteral( "Title" ) );
4467  if ( !titleElem.isNull() )
4468  {
4469  label = titleElem.firstChild().nodeValue();
4470  }
4471 
4472  QDomElement abstractElem = childElem.firstChildElement( QStringLiteral( "Abstract" ) );
4473  if ( !abstractElem.isNull() )
4474  {
4475  description = abstractElem.firstChild().nodeValue();
4476  }
4477  }
4478  else if ( childElem.localName() == QLatin1String( "Abstract" ) )
4479  {
4480  // <sld:Abstract> (v1.0)
4481  description = childElem.firstChild().nodeValue();
4482  }
4483  else if ( childElem.localName() == QLatin1String( "Title" ) )
4484  {
4485  // <sld:Title> (v1.0)
4486  label = childElem.firstChild().nodeValue();
4487  }
4488  else if ( childElem.localName() == QLatin1String( "Filter" ) )
4489  {
4490  QgsExpression *filter = QgsOgcUtils::expressionFromOgcFilter( childElem );
4491  if ( filter )
4492  {
4493  if ( filter->hasParserError() )
4494  {
4495  QgsDebugMsgLevel( QStringLiteral( "SLD Filter parsing error: %1" ).arg( filter->parserErrorString() ), 3 );
4496  }
4497  else
4498  {
4499  filterExp = filter->expression();
4500  }
4501  delete filter;
4502  }
4503  }
4504  else if ( childElem.localName() == QLatin1String( "MinScaleDenominator" ) )
4505  {
4506  bool ok;
4507  int v = childElem.firstChild().nodeValue().toInt( &ok );
4508  if ( ok )
4509  scaleMinDenom = v;
4510  }
4511  else if ( childElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4512  {
4513  bool ok;
4514  int v = childElem.firstChild().nodeValue().toInt( &ok );
4515  if ( ok )
4516  scaleMaxDenom = v;
4517  }
4518  else if ( childElem.localName() == QLatin1String( "TextSymbolizer" ) )
4519  {
4520  readSldTextSymbolizer( childElem, settings );
4521  }
4522 
4523  childElem = childElem.nextSiblingElement();
4524  }
4525 
4526  QgsRuleBasedLabeling::Rule *ruleLabeling = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings( settings ), scaleMinDenom, scaleMaxDenom, filterExp, label );
4527  rootRule->appendChild( ruleLabeling );
4528 
4529  ruleElem = ruleElem.nextSiblingElement();
4530  }
4531 
4532  setLabeling( new QgsRuleBasedLabeling( rootRule ) );
4533  setLabelsEnabled( true );
4534  }
4535  else
4536  {
4537  QgsDebugMsgLevel( QStringLiteral( "Info: simple labeling" ), 4 );
4538  // retrieve the TextSymbolizer element child node
4539  QDomElement textSymbolizerElem = ruleElem.firstChildElement( QStringLiteral( "TextSymbolizer" ) );
4541  if ( readSldTextSymbolizer( textSymbolizerElem, s ) )
4542  {
4544  setLabelsEnabled( true );
4545  }
4546  }
4547 }
4548 
4549 bool QgsVectorLayer::readSldTextSymbolizer( const QDomNode &node, QgsPalLayerSettings &settings ) const
4550 {
4551  if ( node.localName() != QLatin1String( "TextSymbolizer" ) )
4552  {
4553  QgsDebugMsgLevel( QStringLiteral( "Not a TextSymbolizer element: %1" ).arg( node.localName() ), 3 );
4554  return false;
4555  }
4556  QDomElement textSymbolizerElem = node.toElement();
4557  // Label
4558  QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
4559  if ( !labelElem.isNull() )
4560  {
4561  QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
4562  if ( !propertyNameElem.isNull() )
4563  {
4564  // set labeling defaults
4565 
4566  // label attribute
4567  QString labelAttribute = propertyNameElem.text();
4568  settings.fieldName = labelAttribute;
4569  settings.isExpression = false;
4570 
4571  int fieldIndex = mFields.lookupField( labelAttribute );
4572  if ( fieldIndex == -1 )
4573  {
4574  // label attribute is not in columns, check if it is an expression
4575  QgsExpression exp( labelAttribute );
4576  if ( !exp.hasEvalError() )
4577  {
4578  settings.isExpression = true;
4579  }
4580  else
4581  {
4582  QgsDebugMsgLevel( QStringLiteral( "SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
4583  }
4584  }
4585  }
4586  else
4587  {
4588  QgsDebugMsgLevel( QStringLiteral( "Info: PropertyName element not found." ), 4 );
4589  return false;
4590  }
4591  }
4592  else
4593  {
4594  QgsDebugMsgLevel( QStringLiteral( "Info: Label element not found." ), 4 );
4595  return false;
4596  }
4597 
4599  if ( textSymbolizerElem.hasAttribute( QStringLiteral( "uom" ) ) )
4600  {
4601  sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( textSymbolizerElem.attribute( QStringLiteral( "uom" ) ) );
4602  }
4603 
4604  QString fontFamily = QStringLiteral( "Sans-Serif" );
4605  int fontPointSize = 10;
4607  int fontWeight = -1;
4608  bool fontItalic = false;
4609  bool fontUnderline = false;
4610 
4611  // Font
4612  QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
4613  if ( !fontElem.isNull() )
4614  {
4615  QgsStringMap fontSvgParams = QgsSymbolLayerUtils::getSvgParameterList( fontElem );
4616  for ( QgsStringMap::iterator it = fontSvgParams.begin(); it != fontSvgParams.end(); ++it )
4617  {
4618  QgsDebugMsgLevel( QStringLiteral( "found fontSvgParams %1: %2" ).arg( it.key(), it.value() ), 4 );
4619 
4620  if ( it.key() == QLatin1String( "font-family" ) )
4621  {
4622  fontFamily = it.value();
4623  }
4624  else if ( it.key() == QLatin1String( "font-style" ) )
4625  {
4626  fontItalic = ( it.value() == QLatin1String( "italic" ) ) || ( it.value() == QLatin1String( "Italic" ) );
4627  }
4628  else if ( it.key() == QLatin1String( "font-size" ) )
4629  {
4630  bool ok;
4631  int fontSize = it.value().toInt( &ok );
4632  if ( ok )
4633  {
4634  fontPointSize = fontSize;
4635  fontUnitSize = sldUnitSize;
4636  }
4637  }
4638  else if ( it.key() == QLatin1String( "font-weight" ) )
4639  {
4640  if ( ( it.value() == QLatin1String( "bold" ) ) || ( it.value() == QLatin1String( "Bold" ) ) )
4641  fontWeight = QFont::Bold;
4642  }
4643  else if ( it.key() == QLatin1String( "font-underline" ) )
4644  {
4645  fontUnderline = ( it.value() == QLatin1String( "underline" ) ) || ( it.value() == QLatin1String( "Underline" ) );
4646  }
4647  }
4648  }
4649 
4650  QgsTextFormat format;
4651  QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
4652  font.setUnderline( fontUnderline );
4653  format.setFont( font );
4654  format.setSize( fontPointSize );
4655  format.setSizeUnit( fontUnitSize );
4656 
4657  // Fill
4658  QDomElement fillElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) );
4659  QColor textColor;
4660  Qt::BrushStyle textBrush = Qt::SolidPattern;
4661  QgsSymbolLayerUtils::fillFromSld( fillElem, textBrush, textColor );
4662  if ( textColor.isValid() )
4663  {
4664  QgsDebugMsgLevel( QStringLiteral( "Info: textColor %1." ).arg( QVariant( textColor ).toString() ), 4 );
4665  format.setColor( textColor );
4666  }
4667 
4668  QgsTextBufferSettings bufferSettings;
4669 
4670  // Halo
4671  QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
4672  if ( !haloElem.isNull() )
4673  {
4674  bufferSettings.setEnabled( true );
4675  bufferSettings.setSize( 1 );
4676 
4677  QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
4678  if ( !radiusElem.isNull() )
4679  {
4680  bool ok;
4681  double bufferSize = radiusElem.text().toDouble( &ok );
4682  if ( ok )
4683  {
4684  bufferSettings.setSize( bufferSize );
4685  bufferSettings.setSizeUnit( sldUnitSize );
4686  }
4687  }
4688 
4689  QDomElement haloFillElem = haloElem.firstChildElement( QStringLiteral( "Fill" ) );
4690  QColor bufferColor;
4691  Qt::BrushStyle bufferBrush = Qt::SolidPattern;
4692  QgsSymbolLayerUtils::fillFromSld( haloFillElem, bufferBrush, bufferColor );
4693  if ( bufferColor.isValid() )
4694  {
4695  QgsDebugMsgLevel( QStringLiteral( "Info: bufferColor %1." ).arg( QVariant( bufferColor ).toString() ), 4 );
4696  bufferSettings.setColor( bufferColor );
4697  }
4698  }
4699 
4700  // LabelPlacement
4701  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
4702  if ( !labelPlacementElem.isNull() )
4703  {
4704  // PointPlacement
4705  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
4706  if ( !pointPlacementElem.isNull() )
4707  {
4710  {
4712  }
4713 
4714  QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
4715  if ( !displacementElem.isNull() )
4716  {
4717  QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
4718  if ( !displacementXElem.isNull() )
4719  {
4720  bool ok;
4721  double xOffset = displacementXElem.text().toDouble( &ok );
4722  if ( ok )
4723  {
4724  settings.xOffset = xOffset;
4725  settings.offsetUnits = sldUnitSize;
4726  }
4727  }
4728  QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
4729  if ( !displacementYElem.isNull() )
4730  {
4731  bool ok;
4732  double yOffset = displacementYElem.text().toDouble( &ok );
4733  if ( ok )
4734  {
4735  settings.yOffset = yOffset;
4736  settings.offsetUnits = sldUnitSize;
4737  }
4738  }
4739  }
4740  QDomElement anchorPointElem = pointPlacementElem.firstChildElement( QStringLiteral( "AnchorPoint" ) );
4741  if ( !anchorPointElem.isNull() )
4742  {
4743  QDomElement anchorPointXElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointX" ) );
4744  if ( !anchorPointXElem.isNull() )
4745  {
4746  bool ok;
4747  double xOffset = anchorPointXElem.text().toDouble( &ok );
4748  if ( ok )
4749  {
4750  settings.xOffset = xOffset;
4751  settings.offsetUnits = sldUnitSize;
4752  }
4753  }
4754  QDomElement anchorPointYElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointY" ) );
4755  if ( !anchorPointYElem.isNull() )
4756  {
4757  bool ok;
4758  double yOffset = anchorPointYElem.text().toDouble( &ok );
4759  if ( ok )
4760  {
4761  settings.yOffset = yOffset;
4762  settings.offsetUnits = sldUnitSize;
4763  }
4764  }
4765  }
4766 
4767  QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
4768  if ( !rotationElem.isNull() )
4769  {
4770  bool ok;
4771  double rotation = rotationElem.text().toDouble( &ok );
4772  if ( ok )
4773  {
4774  settings.angleOffset = 360 - rotation;
4775  }
4776  }
4777  }
4778  else
4779  {
4780  // PointPlacement
4781  QDomElement linePlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "LinePlacement" ) );
4782  if ( !linePlacementElem.isNull() )
4783  {
4785  }
4786  }
4787  }
4788 
4789  // read vendor options
4790  QgsStringMap vendorOptions;
4791  QDomElement vendorOptionElem = textSymbolizerElem.firstChildElement( QStringLiteral( "VendorOption" ) );
4792  while ( !vendorOptionElem.isNull() && vendorOptionElem.localName() == QLatin1String( "VendorOption" ) )
4793  {
4794  QString optionName = vendorOptionElem.attribute( QStringLiteral( "name" ) );
4795  QString optionValue;
4796  if ( vendorOptionElem.firstChild().nodeType() == QDomNode::TextNode )
4797  {
4798  optionValue = vendorOptionElem.firstChild().nodeValue();
4799  }
4800  else
4801  {
4802  if ( vendorOptionElem.firstChild().nodeType() == QDomNode::ElementNode &&
4803  vendorOptionElem.firstChild().localName() == QLatin1String( "Literal" ) )
4804  {
4805  QgsDebugMsg( vendorOptionElem.firstChild().localName() );
4806  optionValue = vendorOptionElem.firstChild().firstChild().nodeValue();
4807  }
4808  else
4809  {
4810  QgsDebugMsg( QStringLiteral( "unexpected child of %1 named %2" ).arg( vendorOptionElem.localName(), optionName ) );
4811  }
4812  }
4813 
4814  if ( !optionName.isEmpty() && !optionValue.isEmpty() )
4815  {
4816  vendorOptions[ optionName ] = optionValue;
4817  }
4818 
4819  vendorOptionElem = vendorOptionElem.nextSiblingElement();
4820  }
4821  if ( !vendorOptions.isEmpty() )
4822  {
4823  for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
4824  {
4825  if ( it.key() == QLatin1String( "underlineText" ) && it.value() == QLatin1String( "true" ) )
4826  {
4827  font.setUnderline( true );
4828  format.setFont( font );
4829  }
4830  else if ( it.key() == QLatin1String( "strikethroughText" ) && it.value() == QLatin1String( "true" ) )
4831  {
4832  font.setStrikeOut( true );
4833  format.setFont( font );
4834  }
4835  else if ( it.key() == QLatin1String( "maxDisplacement" ) )
4836  {
4838  }
4839  else if ( it.key() == QLatin1String( "followLine" ) && it.value() == QLatin1String( "true" ) )
4840  {
4842  {
4844  }
4845  else
4846  {
4848  }
4849  }
4850  else if ( it.key() == QLatin1String( "maxAngleDelta" ) )
4851  {
4852  bool ok;
4853  double angle = it.value().toDouble( &ok );
4854  if ( ok )
4855  {
4856  settings.maxCurvedCharAngleIn = angle;
4857  settings.maxCurvedCharAngleOut = angle;
4858  }
4859  }
4860  // miscellaneous options
4861  else if ( it.key() == QLatin1String( "conflictResolution" ) && it.value() == QLatin1String( "false" ) )
4862  {
4863  settings.displayAll = true;
4864  }
4865  else if ( it.key() == QLatin1String( "forceLeftToRight" ) && it.value() == QLatin1String( "false" ) )
4866  {
4868  }
4869  else if ( it.key() == QLatin1String( "group" ) && it.value() == QLatin1String( "yes" ) )
4870  {
4871  settings.mergeLines = true;
4872  }
4873  else if ( it.key() == QLatin1String( "labelAllGroup" ) && it.value() == QLatin1String( "true" ) )
4874  {
4875  settings.mergeLines = true;
4876  }
4877  }
4878  }
4879 
4880  format.setBuffer( bufferSettings );
4881  settings.setFormat( format );
4882  return true;
4883 }
4884 
4886 {
4887  return mEditFormConfig;
4888 }
4889 
4891 {
4892  if ( mEditFormConfig == editFormConfig )
4893  return;
4894 
4895  mEditFormConfig = editFormConfig;
4896  mEditFormConfig.onRelationsLoaded();
4897  emit editFormConfigChanged();
4898 }
4899 
4900 QString QgsVectorLayer::mapTipTemplate() const
4901 {
4902  return mMapTipTemplate;
4903 }
4904 
4905 void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
4906 {
4907  if ( mMapTipTemplate == mapTip )
4908  return;
4909 
4910  mMapTipTemplate = mapTip;
4911  emit mapTipTemplateChanged();
4912 }
4913 
4915 {
4916  QgsAttributeTableConfig config = mAttributeTableConfig;
4917 
4918  if ( config.isEmpty() )
4919  config.update( fields() );
4920 
4921  return config;
4922 }
4923 
4925 {
4926  if ( mAttributeTableConfig != attributeTableConfig )
4927  {
4928  mAttributeTableConfig = attributeTableConfig;
4929  emit configChanged();
4930  }
4931 }
4932 
4934 {
4936 }
4937 
4939 {
4941 }
4942 
4944 {
4945  if ( !mDiagramLayerSettings )
4946  mDiagramLayerSettings = new QgsDiagramLayerSettings();
4947  *mDiagramLayerSettings = s;
4948 }
4949 
4951 {
4952  QgsLayerMetadataFormatter htmlFormatter( metadata() );
4953  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
4954 
4955  // Begin Provider section
4956  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
4957  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
4958 
4959  // name
4960  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
4961 
4962  // local path
4963  QVariantMap uriComponents = QgsProviderRegistry::instance()->decodeUri( mProviderKey, publicSource() );
4964  QString path;
4965  if ( uriComponents.contains( QStringLiteral( "path" ) ) )
4966  {
4967  path = uriComponents[QStringLiteral( "path" )].toString();
4968  if ( QFile::exists( path ) )
4969  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" );
4970  }
4971  if ( uriComponents.contains( QStringLiteral( "url" ) ) )
4972  {
4973  const QString url = uriComponents[QStringLiteral( "url" )].toString();
4974  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" );
4975  }
4976 
4977  // data source
4978  if ( publicSource() != path )
4979  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>%1" ).arg( publicSource() ) + QStringLiteral( "</td></tr>\n" );
4980 
4981  // storage type
4982  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
4983 
4984  // comment
4985  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
4986 
4987  // encoding
4988  const QgsVectorDataProvider *provider = dataProvider();
4989  if ( provider )
4990  {
4991  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + provider->encoding() + QStringLiteral( "</td></tr>\n" );
4992  }
4993 
4994  if ( isSpatial() )
4995  {
4996  // geom type
4998  if ( type < 0 || type > QgsWkbTypes::NullGeometry )
4999  {
5000  QgsDebugMsgLevel( QStringLiteral( "Invalid vector type" ), 2 );
5001  }
5002  else
5003  {
5004  QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
5006  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
5007  }
5008 
5009  // EPSG
5010  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" );
5011  if ( crs().isValid() )
5012  {
5013  myMetadata += crs().userFriendlyIdentifier( QgsCoordinateReferenceSystem::FullString ) + QStringLiteral( " - " );
5014  if ( crs().isGeographic() )
5015  myMetadata += tr( "Geographic" );
5016  else
5017  myMetadata += tr( "Projected" );
5018  }
5019  myMetadata += QLatin1String( "</td></tr>\n" );
5020 
5021  // Extent
5022  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
5023 
5024  // unit
5025  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
5026 
5027  }
5028 
5029  // feature count
5030  QLocale locale = QLocale();
5031  locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
5032  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
5033  + tr( "Feature count" ) + QStringLiteral( "</td><td>" )
5034  + ( featureCount() == -1 ? tr( "unknown" ) : locale.toString( static_cast<qlonglong>( featureCount() ) ) )
5035  + QStringLiteral( "</td></tr>\n" );
5036 
5037  // End Provider section
5038  myMetadata += QLatin1String( "</table>\n<br><br>" );
5039 
5040  // identification section
5041  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
5042  myMetadata += htmlFormatter.identificationSectionHtml( );
5043  myMetadata += QLatin1String( "<br><br>\n" );
5044 
5045  // extent section
5046  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
5047  myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
5048  myMetadata += QLatin1String( "<br><br>\n" );
5049 
5050  // Start the Access section
5051  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
5052  myMetadata += htmlFormatter.accessSectionHtml( );
5053  myMetadata += QLatin1String( "<br><br>\n" );
5054 
5055  // Fields section
5056  myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
5057 
5058  // primary key
5059  QgsAttributeList pkAttrList = primaryKeyAttributes();
5060  if ( !pkAttrList.isEmpty() )
5061  {
5062  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
5063  const auto constPkAttrList = pkAttrList;
5064  for ( int idx : constPkAttrList )
5065  {
5066  myMetadata += fields().at( idx ).name() + ' ';
5067  }
5068  myMetadata += QLatin1String( "</td></tr>\n" );
5069  }
5070 
5071  const QgsFields myFields = fields();
5072 
5073  // count fields
5074  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
5075 
5076  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
5077  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" );
5078 
5079  for ( int i = 0; i < myFields.size(); ++i )
5080  {
5081  QgsField myField = myFields.at( i );
5082  QString rowClass;
5083  if ( i % 2 )
5084  rowClass = QStringLiteral( "class=\"odd-row\"" );
5085  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" );
5086  }
5087 
5088  //close field list
5089  myMetadata += QLatin1String( "</table>\n<br><br>" );
5090 
5091  // Start the contacts section
5092  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
5093  myMetadata += htmlFormatter.contactsSectionHtml( );
5094  myMetadata += QLatin1String( "<br><br>\n" );
5095 
5096  // Start the links section
5097  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
5098  myMetadata += htmlFormatter.linksSectionHtml( );
5099  myMetadata += QLatin1String( "<br><br>\n" );
5100 
5101  // Start the history section
5102  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
5103  myMetadata += htmlFormatter.historySectionHtml( );
5104  myMetadata += QLatin1String( "<br><br>\n" );
5105 
5106  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
5107  return myMetadata;
5108 }
5109 
5110 void QgsVectorLayer::invalidateSymbolCountedFlag()
5111 {
5112  mSymbolFeatureCounted = false;
5113 }
5114 
5115 void QgsVectorLayer::onFeatureCounterCompleted()
5116 {
5117  onSymbolsCounted();
5118  mFeatureCounter = nullptr;
5119 }
5120 
5121 void QgsVectorLayer::onFeatureCounterTerminated()
5122 {
5123  mFeatureCounter = nullptr;
5124 }
5125 
5126 void QgsVectorLayer::onJoinedFieldsChanged()
5127 {
5128  // some of the fields of joined layers have changed -> we need to update this layer's fields too
5129  updateFields();
5130 }
5131 
5132 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
5133 {
5134  if ( mEditCommandActive )
5135  mDeletedFids << fid;
5136  else
5137  emit featuresDeleted( QgsFeatureIds() << fid );
5138 
5139  emit featureDeleted( fid );
5140 }
5141 
5142 void QgsVectorLayer::onRelationsLoaded()
5143 {
5144  mEditFormConfig.onRelationsLoaded();
5145 }
5146 
5147 void QgsVectorLayer::onSymbolsCounted()
5148 {
5149  if ( mFeatureCounter )
5150  {
5151  mSymbolFeatureCounted = true;
5152  mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
5153  mSymbolFeatureIdMap = mFeatureCounter->symbolFeatureIdMap();
5155  }
5156 }
5157 
5158 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
5159 {
5160  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
5161 }
5162 
5163 QList<QgsWeakRelation> QgsVectorLayer::weakRelations() const
5164 {
5165  return mWeakRelations;
5166 }
5167 
5168 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
5169 {
5170  return QgsProviderRegistry::instance()->listStyles( mProviderKey, mDataSource, ids, names, descriptions, msgError );
5171 }
5172 
5173 QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
5174 {
5175  return QgsProviderRegistry::instance()->getStyleById( mProviderKey, mDataSource, styleId, msgError );
5176 }
5177 
5178 bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
5179 {
5180  return QgsProviderRegistry::instance()->deleteStyleById( mProviderKey, mDataSource, styleId, msgError );
5181 }
5182 
5183 
5184 void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
5185  bool useAsDefault, const QString &uiFileContent, QString &msgError )
5186 {
5187 
5188  QString sldStyle, qmlStyle;
5189  QDomDocument qmlDocument, sldDocument;
5190  QgsReadWriteContext context;
5191  exportNamedStyle( qmlDocument, msgError, context );
5192  if ( !msgError.isNull() )
5193  {
5194  return;
5195  }
5196  qmlStyle = qmlDocument.toString();
5197 
5198  this->exportSldStyle( sldDocument, msgError );
5199  if ( !msgError.isNull() )
5200  {
5201  return;
5202  }
5203  sldStyle = sldDocument.toString();
5204 
5206  mDataSource, qmlStyle, sldStyle, name,
5207  description, uiFileContent, useAsDefault, msgError );
5208 }
5209 
5210 
5211 
5212 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, QgsMapLayer::StyleCategories categories )
5213 {
5214  return loadNamedStyle( theURI, resultFlag, false, categories );
5215 }
5216 
5217 bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
5218 {
5219  bool rc = false;
5220 
5221  QString joinKey = mAuxiliaryLayerKey;
5222  if ( !key.isEmpty() )
5223  joinKey = key;
5224 
5225  if ( storage.isValid() && !joinKey.isEmpty() )
5226  {
5227  QgsAuxiliaryLayer *alayer = nullptr;
5228 
5229  int idx = fields().lookupField( joinKey );
5230 
5231  if ( idx >= 0 )
5232  {
5233  alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
5234 
5235  if ( alayer )
5236  {
5237  setAuxiliaryLayer( alayer );
5238  rc = true;
5239  }
5240  }
5241  }
5242 
5243  return rc;
5244 }
5245 
5247 {
5248  mAuxiliaryLayerKey.clear();
5249 
5250  if ( mAuxiliaryLayer )
5251  removeJoin( mAuxiliaryLayer->id() );
5252 
5253  if ( alayer )
5254  {
5255  addJoin( alayer->joinInfo() );
5256 
5257  if ( !alayer->isEditable() )
5258  alayer->startEditing();
5259 
5260  mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
5261  }
5262 
5263  mAuxiliaryLayer.reset( alayer );
5264  if ( mAuxiliaryLayer )
5265  mAuxiliaryLayer->setParent( this );
5266  updateFields();
5267 }
5268 
5270 {
5271  return mAuxiliaryLayer.get();
5272 }
5273 
5275 {
5276  return mAuxiliaryLayer.get();
5277 }
5278 
5279 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories )
5280 {
5281  QgsDataSourceUri dsUri( theURI );
5282  QString returnMessage;
5283  QString qml, errorMsg;
5284  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
5285  {
5287  }
5288  if ( !qml.isEmpty() )
5289  {
5290  QDomDocument myDocument( QStringLiteral( "qgis" ) );
5291  myDocument.setContent( qml );
5292  resultFlag = importNamedStyle( myDocument, errorMsg );
5293  returnMessage = QObject::tr( "Loaded from Provider" );
5294  }
5295  else
5296  {
5297  returnMessage = QgsMapLayer::loadNamedStyle( theURI, resultFlag, categories );
5298  }
5299 
5300  if ( resultFlag )
5301  emit styleLoaded( categories );
5302 
5303  return returnMessage;
5304 }
5305 
5306 QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
5307 {
5308  if ( mDataProvider )
5309  return mDataProvider->dependencies() + mDependencies;
5310  return mDependencies;
5311 }
5312 
5313 void QgsVectorLayer::emitDataChanged()
5314 {
5315  if ( mDataChangedFired )
5316  return;
5317 
5318  updateExtents(); // reset cached extent to reflect data changes
5319 
5320  mDataChangedFired = true;
5321  emit dataChanged();
5322  mDataChangedFired = false;
5323 }
5324 
5325 bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
5326 {
5327  QSet<QgsMapLayerDependency> deps;
5328  const auto constODeps = oDeps;
5329  for ( const QgsMapLayerDependency &dep : constODeps )
5330  {
5331  if ( dep.origin() == QgsMapLayerDependency::FromUser )
5332  deps << dep;
5333  }
5334 
5335  QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
5336 
5337  // disconnect layers that are not present in the list of dependencies anymore
5338  for ( const QgsMapLayerDependency &dep : qgis::as_const( mDependencies ) )
5339  {
5340  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5341  if ( !lyr )
5342  continue;
5343  disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5344  disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5345  disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5346  disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5348  }
5349 
5350  // assign new dependencies
5351  if ( mDataProvider )
5352  mDependencies = mDataProvider->dependencies() + deps;
5353  else
5354  mDependencies = deps;
5355  emit dependenciesChanged();
5356 
5357  // connect to new layers
5358  for ( const QgsMapLayerDependency &dep : qgis::as_const( mDependencies ) )
5359  {
5360  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5361  if ( !lyr )
5362  continue;
5363  connect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5364  connect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5365  connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5366  connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5368  }
5369 
5370  // if new layers are present, emit a data change
5371  if ( ! toAdd.isEmpty() )
5372  emitDataChanged();
5373 
5374  return true;
5375 }
5376 
5377 QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
5378 {
5379  if ( fieldIndex < 0 || fieldIndex >= mFields.count() || !mDataProvider )
5380  return nullptr;
5381 
5382  QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
5383 
5384  // make sure provider constraints are always present!
5385  if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
5386  {
5387  constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
5388  }
5389 
5390  return constraints;
5391 }
5392 
5393 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
5394 {
5395  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
5396 
5397  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
5398  return m;
5399 
5400  QString name = mFields.at( fieldIndex ).name();
5401 
5402  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
5403  for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
5404  {
5405  if ( conIt.key().first == name )
5406  {
5407  m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
5408  }
5409  }
5410 
5411  return m;
5412 }
5413 
5415 {
5416  if ( index < 0 || index >= mFields.count() )
5417  return;
5418 
5419  QString name = mFields.at( index ).name();
5420 
5421  // add constraint to existing constraints
5422  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
5423  constraints |= constraint;
5424  mFieldConstraints.insert( name, constraints );
5425 
5426  mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
5427 
5428  updateFields();
5429 }
5430 
5432 {
5433  if ( index < 0 || index >= mFields.count() )
5434  return;
5435 
5436  QString name = mFields.at( index ).name();
5437 
5438  // remove constraint from existing constraints
5439  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
5440  constraints &= ~constraint;
5441  mFieldConstraints.insert( name, constraints );
5442 
5443  mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
5444 
5445  updateFields();
5446 }
5447 
5448 QString QgsVectorLayer::constraintExpression( int index ) const
5449 {
5450  if ( index < 0 || index >= mFields.count() )
5451  return QString();
5452 
5453  return mFields.at( index ).constraints().constraintExpression();
5454 }
5455 
5456 QString QgsVectorLayer::constraintDescription( int index ) const
5457 {
5458  if ( index < 0 || index >= mFields.count() )
5459  return QString();
5460 
5461  return mFields.at( index ).constraints().constraintDescription();
5462 }
5463 
5464 void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
5465 {
5466  if ( index < 0 || index >= mFields.count() )
5467  return;
5468 
5469  if ( expression.isEmpty() )
5470  {
5471  mFieldConstraintExpressions.remove( mFields.at( index ).name() );
5472  }
5473  else
5474  {
5475  mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
5476  }
5477  updateFields();
5478 }
5479 
5481 {
5482  if ( index < 0 || index >= mFields.count() )
5483  return;
5484 
5485  if ( setup.isNull() )
5486  mFieldWidgetSetups.remove( mFields.at( index ).name() );
5487  else
5488  mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
5489  updateFields();
5490 }
5491 
5493 {
5494 
5495  if ( index < 0 || index >= mFields.count() )
5496  return QgsEditorWidgetSetup();
5497 
5498  return mFields.at( index ).editorWidgetSetup();
5499 }
5500 
5501 QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
5502 {
5504  if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
5505  {
5506  if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() )
5507  {
5508  // try to load from custom properties
5509  QgsPalLayerSettings settings;
5510  settings.readFromLayerCustomProperties( this );
5511  labeling = new QgsVectorLayerSimpleLabeling( settings );
5512  }
5513 
5514  // also clear old-style labeling config
5515  removeCustomProperty( QStringLiteral( "labeling" ) );
5516  const auto constCustomPropertyKeys = customPropertyKeys();
5517  for ( const QString &key : constCustomPropertyKeys )
5518  {
5519  if ( key.startsWith( QLatin1String( "labeling/" ) ) )
5520  removeCustomProperty( key );
5521  }
5522  }
5523 
5524  return labeling;
5525 }
5526 
5528 {
5529  return mAllowCommit;
5530 }
5531 
5532 void QgsVectorLayer::setAllowCommit( bool allowCommit )
5533 {
5534  if ( mAllowCommit == allowCommit )
5535  return;
5536 
5537  mAllowCommit = allowCommit;
5538  emit allowCommitChanged();
5539 }
5540 
5542 {
5543  return mGeometryOptions.get();
5544 }
5545 
5546 void QgsVectorLayer::setReadExtentFromXml( bool readExtentFromXml )
5547 {
5548  mReadExtentFromXml = readExtentFromXml;
5549 }
5550 
5552 {
5553  return mReadExtentFromXml;
5554 }
5555 
5556 void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
5557 {
5559  if ( tr && mEditBuffer )
5560  {
5561  qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
5562  }
5563 }
5564 
5565 QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers() const
5566 {
5567  QList<QgsVectorLayer *> layers;
5568  QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
5569  for ( i = mHandledFeatures.begin(); i != mHandledFeatures.end(); ++i )
5570  layers.append( i.key() );
5571  return layers;
5572 }
5573 
5575 {
5576  return mHandledFeatures[layer];
5577 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsVectorLayer::setRenderer
void setRenderer(QgsFeatureRenderer *r)
Sets renderer which will be invoked to represent this layer.
Definition: qgsvectorlayer.cpp:3638
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:107
QgsVectorLayerFeatureCounter
Definition: qgsvectorlayerfeaturecounter.h:33
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:1963
qgsEnumKeyToValue
T qgsEnumKeyToValue(const QString &key, const T &defaultValue)
Returns the value corresponding to the given key of an enum.
Definition: qgis.h:518
QgsTextBufferSettings::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
Definition: qgstextbuffersettings.cpp:72
QgsVectorLayer::LayerOptions::loadDefaultStyle
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
Definition: qgsvectorlayer.h:449
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsProject::relationManager
QgsRelationManager relationManager
Definition: qgsproject.h:103
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:88
QgsVectorLayer::addFeatures
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
Definition: qgsvectorlayer.cpp:3484
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:5173
QgsFields::FieldOrigin
FieldOrigin
Definition: qgsfields.h:48
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:5546
QgsVectorSimplifyMethod::setForceLocalOptimization
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
Definition: qgsvectorsimplifymethod.h:92
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:1619
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:5184
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
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:4319
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
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:4938
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:619
QgsVectorLayer::symbolFeatureIds
QgsFeatureIds symbolFeatureIds(const QString &legendKey) const
Ids of features rendered with specified legend key.
Definition: qgsvectorlayer.cpp:759
QgsDataSourceUri
Definition: qgsdatasourceuri.h:35
qgspallabeling.h
QgsPalLayerSettings::PerimeterCurved
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
Definition: qgspallabeling.h:229
QgsOgcUtils::expressionFromOgcFilter
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
Definition: qgsogcutils.cpp:1635
QgsAggregateCalculator
Utility class for calculating aggregates for a field (or expression) over the features from a vector ...
Definition: qgsaggregatecalculator.h:44
QgsVectorDataProvider::CreateRenderer
@ CreateRenderer
Provider can create feature renderers using backend-specific formatting information....
Definition: qgsvectordataprovider.h:97
QgsCoordinateTransformContext
Definition: qgscoordinatetransformcontext.h:57
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
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:802
QgsTextFormat::setFont
void setFont(const QFont &font)
Sets the font used for rendering text.
Definition: qgstextformat.cpp:76
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:80
QgsMapLayer::configChanged
void configChanged()
Emitted whenever the configuration is changed.
QgsRuleBasedLabeling::Rule
Definition: qgsrulebasedlabeling.h:52
QgsUnitTypes::RenderUnit
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:166
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:333
QgsDefaultValue
The QgsDefaultValue class provides a container for managing client side default values for fields.
Definition: qgsdefaultvalue.h:48
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:4056
QgsPalLayerSettings::AroundPoint
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
Definition: qgspallabeling.h:222
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:627
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:104
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:49
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:159
QgsVectorLayer::updateFields
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
Definition: qgsvectorlayer.cpp:3763
QgsReadWriteContext
Definition: qgsreadwritecontext.h:34
QgsFeatureRequest::ExactIntersect
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
Definition: qgsfeaturerequest.h:109
QgsPalLayerSettings::maxCurvedCharAngleOut
double maxCurvedCharAngleOut
Maximum angle between outside curved label characters (valid range -20.0 to -95.0)
Definition: qgspallabeling.h:817
QgsExpression::evalErrorString
QString evalErrorString() const
Returns evaluation error.
Definition: qgsexpression.cpp:379
qgsrectangle.h
qgsweakrelation.h
QgsAuxiliaryLayer
Definition: qgsauxiliarystorage.h:60
QgsEditorWidgetSetup
Definition: qgseditorwidgetsetup.h:28
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:145
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.
QgsMapLayerType::VectorLayer
@ VectorLayer
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:37
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:1316
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:4905
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:522
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:3130
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:3925
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
qgssinglesymbolrenderer.h
QgsMapLayer::isValid
bool isValid() const
Returns the status of the layer.
Definition: qgsmaplayer.cpp:656
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:205
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:3347
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:1703
QgsVectorLayer::RemoveFromSelection
@ RemoveFromSelection
Remove from current selection.
Definition: qgsvectorlayer.h:415
QgsTextBufferSettings::setEnabled
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
Definition: qgstextbuffersettings.cpp:52
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:867
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:91
QgsFieldConstraints
Definition: qgsfieldconstraints.h:32
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:1572
QgsVectorDataProvider::encoding
QString encoding() const
Returns the encoding which is used for accessing data.
Definition: qgsvectordataprovider.cpp:214
QgsVectorDataProvider::fields
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QgsLayerMetadataFormatter
Class for metadata formatter.
Definition: qgslayermetadataformatter.h:33
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:87
QgsVectorSimplifyMethod::SimplifyHint
SimplifyHint
Simplification flags for fast rendering of features.
Definition: qgsvectorsimplifymethod.h:50
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:232
QgsVectorLayer::DeleteContext
Context for cascade delete features.
Definition: qgsvectorlayer.h:510
QgsConditionalLayerStyles::writeXml
bool writeXml(QDomNode &node, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes the condition styles state to a DOM node.
Definition: qgsconditionalstyle.cpp:55
QgsVectorLayer::splitParts
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
Definition: qgsvectorlayer.cpp:1353
QgsVectorLayer::LayerOptions::transformContext
QgsCoordinateTransformContext transformContext
Coordinate transform context.
Definition: qgsvectorlayer.h:461
QgsMapLayer::importNamedStyle
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
Definition: qgsmaplayer.cpp:1034
QgsExpression::rootNode
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Definition: qgsexpression.cpp:1074
qgsvectorlayerrenderer.h
QgsExpressionNodeColumnRef
An expression node which takes it value from a feature's field.
Definition: qgsexpressionnodeimpl.h:400
QgsFeatureSink::addFeature
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())
Adds a single feature to the sink.
Definition: qgsfeaturesink.cpp:20
QgsVectorLayer::splitFeatures
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
Definition: qgsvectorlayer.cpp:1365
QgsRectangle::xMaximum
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsProject::pathResolver
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
Definition: qgsproject.cpp:2590
QgsUnitTypes::RenderPoints
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:172
QgsPalLayerSettings::upsidedownLabels
UpsideDownLabels upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
Definition: qgspallabeling.h:883
QgsVectorLayer::beforeEditingStarted
void beforeEditingStarted()
Emitted before editing on this layer is started.
QgsMapLayerType
QgsMapLayerType
Definition: qgsmaplayer.h:67
QgsVectorLayer::addExpressionField
int addExpressionField(const QString &exp, const QgsField &fld)
Add a new field which is calculated by the expression specified.
Definition: qgsvectorlayer.cpp:3729
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Definition: qgsfields.h:44
QgsVectorLayer::featureCount
long featureCount() const FINAL
Returns feature count including changes which have not yet been committed If you need only the count ...
Definition: qgsvectorlayer.cpp:3302
QgsProviderRegistry::listStyles
int listStyles(const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Lists stored layer styles in the provider defined by providerKey and uri.
Definition: qgsproviderregistry.cpp:502
QgsMapLayer::writeCustomProperties
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
Definition: qgsmaplayer.cpp:632
QgsEditorWidgetSetup::config
QVariantMap config() const
Definition: qgseditorwidgetsetup.h:64
QgsExpressionContextUtils::layerScope
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Definition: qgsexpressioncontextutils.cpp:264
QgsVectorLayer::geometryOptions
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
Definition: qgsvectorlayer.cpp:5541
QgsVectorLayer::dependencies
QSet< QgsMapLayerDependency > dependencies() const FINAL
Gets the list of dependencies.
Definition: qgsvectorlayer.cpp:5306
QgsVectorLayerServerProperties
Definition: qgsvectorlayerserverproperties.h:38
QgsVectorLayer::isAuxiliaryField
bool isAuxiliaryField(int index, int &srcIndex) const
Returns true if the field comes from the auxiliary layer, false otherwise.
Definition: qgsvectorlayer.cpp:3619
QgsVectorLayer::opacityChanged
void opacityChanged(double opacity)
Emitted when the layer's opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
QgsVectorLayerEditBuffer::mDeletedAttributeIds
QgsAttributeList mDeletedAttributeIds
Deleted attributes fields which are not committed. The list is kept sorted.
Definition: qgsvectorlayereditbuffer.h:296
QgsMapLayerLegend
Definition: qgsmaplayerlegend.h:45
qgsfeature.h
QgsPalLayerSettings::yOffset
double yOffset
Vertical offset of label.
Definition: qgspallabeling.h:783
QgsVectorLayer::attributeDeleted
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
QgsMapLayer::AttributeTable
@ AttributeTable
Attribute table settings: choice and order of columns, conditional styling.
Definition: qgsmaplayer.h:165
QgsFieldConstraints::constraintExpression
QString constraintExpression() const
Returns the constraint expression for the field, if set.
Definition: qgsfieldconstraints.cpp:67
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsVectorSimplifyMethod::simplifyAlgorithm
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
Definition: qgsvectorsimplifymethod.h:79
QgsVectorLayer::loadNamedStyle
virtual QString loadNamedStyle(const QString &theURI, bool &resultFlag, bool loadFromLocalDb, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Loads a named style from file/local db/datasource db.
Definition: qgsvectorlayer.cpp:5279
QgsVectorLayer::beforeCommitChanges
void beforeCommitChanges()
Emitted before changes are committed to the data provider.
QgsVectorLayer::setAllowCommit
void setAllowCommit(bool allowCommit)
Controls, if the layer is allowed to commit changes.
Definition: qgsvectorlayer.cpp:5532
QgsVectorLayer::aggregate
QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters &parameters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr) const
Calculates an aggregated value from the layer's features.
Definition: qgsvectorlayer.cpp:4268
qgis.h
QgsVectorLayer::constraintExpression
QString constraintExpression(int index) const
Returns the constraint expression for for a specified field index, if set.
Definition: qgsvectorlayer.cpp:5448
QgsVectorDataProvider::empty
virtual bool empty() const
Returns true if the layer does not contain any feature.
Definition: qgsvectordataprovider.cpp:49
QgsVectorLayer::selectByRect
Q_INVOKABLE void selectByRect(QgsRectangle &rect, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects features found within the search rectangle (in layer's coordinates)
Definition: qgsvectorlayer.cpp:441
QgsGeometryOptions
Definition: qgsgeometryoptions.h:35
QgsRenderContext
Definition: qgsrendercontext.h:57
QgsPalLayerSettings::mergeLines
bool mergeLines
true if connected line features with identical label text should be merged prior to generating label ...
Definition: qgspallabeling.h:895
QgsMapLayerLegend::writeXml
virtual QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml()
<