QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 "qgsrendercontext.h"
71 #include "qgsvectordataprovider.h"
77 #include "qgsvectorlayerlabeling.h"
78 #include "qgsvectorlayerrenderer.h"
81 #include "qgspoint.h"
82 #include "qgsrenderer.h"
83 #include "qgssymbollayer.h"
85 #include "qgsdiagramrenderer.h"
86 #include "qgsstyle.h"
87 #include "qgspallabeling.h"
88 #include "qgssimplifymethod.h"
90 #include "qgsexpressioncontext.h"
91 #include "qgsfeedback.h"
92 #include "qgsxmlutils.h"
93 #include "qgsunittypes.h"
94 #include "qgstaskmanager.h"
95 #include "qgstransaction.h"
96 #include "qgsauxiliarystorage.h"
97 #include "qgsgeometryoptions.h"
99 
100 #include "diagram/qgsdiagram.h"
101 
102 #ifdef TESTPROVIDERLIB
103 #include <dlfcn.h>
104 #endif
105 
106 typedef bool saveStyle_t(
107  const QString &uri,
108  const QString &qmlStyle,
109  const QString &sldStyle,
110  const QString &styleName,
111  const QString &styleDescription,
112  const QString &uiFileContent,
113  bool useAsDefault,
114  QString &errCause
115 );
116 
117 typedef QString loadStyle_t(
118  const QString &uri,
119  QString &errCause
120 );
121 
122 typedef int listStyles_t(
123  const QString &uri,
124  QStringList &ids,
125  QStringList &names,
126  QStringList &descriptions,
127  QString &errCause
128 );
129 
130 typedef QString getStyleById_t(
131  const QString &uri,
132  QString styleID,
133  QString &errCause
134 );
135 
136 typedef bool deleteStyleById_t(
137  const QString &uri,
138  QString styleID,
139  QString &errCause
140 );
141 
142 
143 QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
144  const QString &baseName,
145  const QString &providerKey,
146  const QgsVectorLayer::LayerOptions &options )
147  : QgsMapLayer( QgsMapLayerType::VectorLayer, baseName, vectorLayerPath )
148  , mServerProperties( new QgsVectorLayerServerProperties( this ) )
149  , mAuxiliaryLayer( nullptr )
150  , mAuxiliaryLayerKey( QString() )
151  , mReadExtentFromXml( options.readExtentFromXml )
152 {
154 
155  if ( options.fallbackCrs.isValid() )
156  setCrs( options.fallbackCrs, false );
157  mWkbType = options.fallbackWkbType;
158 
159  setProviderType( providerKey );
160 
161  mGeometryOptions = qgis::make_unique<QgsGeometryOptions>();
162  mActions = new QgsActionManager( this );
163  mConditionalStyles = new QgsConditionalLayerStyles( this );
164  mStoredExpressionManager = new QgsStoredExpressionManager();
165  mStoredExpressionManager->setParent( this );
166 
167  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
168  mJoinBuffer->setParent( this );
169  connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
170 
171  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
172  // if we're given a provider type, try to create and bind one to this layer
173  if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
174  {
175  QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
176  setDataSource( vectorLayerPath, baseName, providerKey, providerOptions, options.loadDefaultStyle );
177  }
178 
179  connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { triggerRepaint(); } );
180  connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
181 
183 
184  // Default simplify drawing settings
185  QgsSettings settings;
186  mSimplifyMethod.setSimplifyHints( settings.flagValue( QStringLiteral( "qgis/simplifyDrawingHints" ), mSimplifyMethod.simplifyHints(), QgsSettings::NoSection ) );
187  mSimplifyMethod.setSimplifyAlgorithm( settings.enumValue( QStringLiteral( "qgis/simplifyAlgorithm" ), mSimplifyMethod.simplifyAlgorithm() ) );
188  mSimplifyMethod.setThreshold( settings.value( QStringLiteral( "qgis/simplifyDrawingTol" ), mSimplifyMethod.threshold() ).toFloat() );
189  mSimplifyMethod.setForceLocalOptimization( settings.value( QStringLiteral( "qgis/simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ).toBool() );
190  mSimplifyMethod.setMaximumScale( settings.value( QStringLiteral( "qgis/simplifyMaxScale" ), mSimplifyMethod.maximumScale() ).toFloat() );
191 
192 } // QgsVectorLayer ctor
193 
194 
196 {
197  emit willBeDeleted();
198 
199  mValid = false;
200 
201  delete mDataProvider;
202  delete mEditBuffer;
203  delete mJoinBuffer;
204  delete mExpressionFieldBuffer;
205  delete mLabeling;
206  delete mDiagramLayerSettings;
207  delete mDiagramRenderer;
208 
209  delete mActions;
210 
211  delete mRenderer;
212  delete mConditionalStyles;
213  delete mStoredExpressionManager;
214 
215  if ( mFeatureCounter )
216  mFeatureCounter->cancel();
217 }
218 
220 {
222  if ( mDataProvider )
223  {
224  options.transformContext = mDataProvider->transformContext();
225  }
226  QgsVectorLayer *layer = new QgsVectorLayer( source(), name(), mProviderKey, options );
227  if ( mDataProvider && layer->dataProvider() )
228  {
229  layer->dataProvider()->handlePostCloneOperations( mDataProvider );
230  }
231  QgsMapLayer::clone( layer );
232 
233  QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
234  const auto constJoins = joins;
235  for ( const QgsVectorLayerJoinInfo &join : constJoins )
236  {
237  // do not copy join information for auxiliary layer
238  if ( !auxiliaryLayer()
239  || ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() ) )
240  layer->addJoin( join );
241  }
242 
243  layer->setProviderEncoding( dataProvider()->encoding() );
245  layer->setMapTipTemplate( mapTipTemplate() );
246  layer->setReadOnly( isReadOnly() );
247  layer->selectByIds( selectedFeatureIds() );
252  layer->setOpacity( opacity() );
254 
255  const auto constActions = actions()->actions();
256  for ( const QgsAction &action : constActions )
257  {
258  layer->actions()->addAction( action );
259  }
260 
261  if ( renderer() )
262  {
263  layer->setRenderer( renderer()->clone() );
264  }
265 
266  if ( labeling() )
267  {
268  layer->setLabeling( labeling()->clone() );
269  }
270  layer->setLabelsEnabled( labelsEnabled() );
271 
272  layer->setSimplifyMethod( simplifyMethod() );
273 
274  if ( diagramRenderer() )
275  {
277  }
278 
279  if ( diagramLayerSettings() )
280  {
282  }
283 
284  for ( int i = 0; i < fields().count(); i++ )
285  {
286  layer->setFieldAlias( i, attributeAlias( i ) );
287  layer->setEditorWidgetSetup( i, editorWidgetSetup( i ) );
290 
291  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> constraints = fieldConstraintsAndStrength( i );
292  auto constraintIt = constraints.constBegin();
293  for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
294  {
295  layer->setFieldConstraint( i, constraintIt.key(), constraintIt.value() );
296  }
297 
299  {
300  layer->addExpressionField( expressionField( i ), fields().at( i ) );
301  }
302  }
303 
304  layer->setEditFormConfig( editFormConfig() );
305 
306  if ( auxiliaryLayer() )
307  layer->setAuxiliaryLayer( auxiliaryLayer()->clone( layer ) );
308 
309  return layer;
310 }
311 
313 {
314  if ( mDataProvider )
315  {
316  return mDataProvider->storageType();
317  }
318  return QString();
319 }
320 
321 
323 {
324  if ( mDataProvider )
325  {
326  return mDataProvider->capabilitiesString();
327  }
328  return QString();
329 }
330 
332 {
333  if ( mDataProvider )
334  {
335  return mDataProvider->dataComment();
336  }
337  return QString();
338 }
339 
341 {
342  return crs();
343 }
344 
346 {
347  return name();
348 }
349 
351 {
352  if ( mDataProvider )
353  {
354  mDataProvider->reloadData();
355  updateFields();
356  }
357 }
358 
360 {
361  return new QgsVectorLayerRenderer( this, rendererContext );
362 }
363 
364 
365 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int m )
366 {
368  {
369  p.setPen( QColor( 50, 100, 120, 200 ) );
370  p.setBrush( QColor( 200, 200, 210, 120 ) );
371  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
372  }
373  else if ( type == QgsVectorLayer::Cross )
374  {
375  p.setPen( QColor( 255, 0, 0 ) );
376  p.drawLine( x - m, y + m, x + m, y - m );
377  p.drawLine( x - m, y - m, x + m, y + m );
378  }
379 }
380 
382 {
383  mSelectedFeatureIds.insert( fid );
384  mPreviousSelectedFeatureIds.clear();
385 
386  emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
387 }
388 
389 void QgsVectorLayer::select( const QgsFeatureIds &featureIds )
390 {
391  mSelectedFeatureIds.unite( featureIds );
392  mPreviousSelectedFeatureIds.clear();
393 
394  emit selectionChanged( featureIds, QgsFeatureIds(), false );
395 }
396 
398 {
399  mSelectedFeatureIds.remove( fid );
400  mPreviousSelectedFeatureIds.clear();
401 
402  emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
403 }
404 
405 void QgsVectorLayer::deselect( const QgsFeatureIds &featureIds )
406 {
407  mSelectedFeatureIds.subtract( featureIds );
408  mPreviousSelectedFeatureIds.clear();
409 
410  emit selectionChanged( QgsFeatureIds(), featureIds, false );
411 }
412 
414 {
415  // normalize the rectangle
416  rect.normalize();
417 
418  QgsFeatureIds newSelection;
419 
421  .setFilterRect( rect )
423  .setNoAttributes() );
424 
425  QgsFeature feat;
426  while ( features.nextFeature( feat ) )
427  {
428  newSelection << feat.id();
429  }
430  features.close();
431 
432  selectByIds( newSelection, behavior );
433 }
434 
435 void QgsVectorLayer::selectByExpression( const QString &expression, QgsVectorLayer::SelectBehavior behavior )
436 {
437  QgsFeatureIds newSelection;
438 
440 
441  if ( behavior == SetSelection || behavior == AddToSelection )
442  {
444  .setExpressionContext( context )
446  .setNoAttributes();
447 
448  QgsFeatureIterator features = getFeatures( request );
449 
450  if ( behavior == AddToSelection )
451  {
452  newSelection = selectedFeatureIds();
453  }
454  QgsFeature feat;
455  while ( features.nextFeature( feat ) )
456  {
457  newSelection << feat.id();
458  }
459  features.close();
460  }
461  else if ( behavior == IntersectSelection || behavior == RemoveFromSelection )
462  {
463  QgsExpression exp( expression );
464  exp.prepare( &context );
465 
466  QgsFeatureIds oldSelection = selectedFeatureIds();
467  QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
468 
469  //refine request
470  if ( !exp.needsGeometry() )
472  request.setSubsetOfAttributes( exp.referencedColumns(), fields() );
473 
474  QgsFeatureIterator features = getFeatures( request );
475  QgsFeature feat;
476  while ( features.nextFeature( feat ) )
477  {
478  context.setFeature( feat );
479  bool matches = exp.evaluate( &context ).toBool();
480 
481  if ( matches && behavior == IntersectSelection )
482  {
483  newSelection << feat.id();
484  }
485  else if ( !matches && behavior == RemoveFromSelection )
486  {
487  newSelection << feat.id();
488  }
489  }
490  }
491 
492  selectByIds( newSelection );
493 }
494 
496 {
497  QgsFeatureIds newSelection;
498 
499  switch ( behavior )
500  {
501  case SetSelection:
502  newSelection = ids;
503  break;
504 
505  case AddToSelection:
506  newSelection = mSelectedFeatureIds + ids;
507  break;
508 
509  case RemoveFromSelection:
510  newSelection = mSelectedFeatureIds - ids;
511  break;
512 
513  case IntersectSelection:
514  newSelection = mSelectedFeatureIds.intersect( ids );
515  break;
516  }
517 
518  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
519  mSelectedFeatureIds = newSelection;
520  mPreviousSelectedFeatureIds.clear();
521 
522  emit selectionChanged( newSelection, deselectedFeatures, true );
523 }
524 
525 void QgsVectorLayer::modifySelection( const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds )
526 {
527  QgsFeatureIds intersectingIds = selectIds & deselectIds;
528  if ( !intersectingIds.isEmpty() )
529  {
530  QgsDebugMsgLevel( QStringLiteral( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." ), 3 );
531  }
532 
533  mSelectedFeatureIds -= deselectIds;
534  mSelectedFeatureIds += selectIds;
535  mPreviousSelectedFeatureIds.clear();
536 
537  emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
538 }
539 
541 {
543  ids.subtract( mSelectedFeatureIds );
544  selectByIds( ids );
545 }
546 
548 {
550 }
551 
553 {
554  // normalize the rectangle
555  rect.normalize();
556 
558  .setFilterRect( rect )
560  .setNoAttributes() );
561 
562  QgsFeatureIds selectIds;
563  QgsFeatureIds deselectIds;
564 
565  QgsFeature fet;
566  while ( fit.nextFeature( fet ) )
567  {
568  if ( mSelectedFeatureIds.contains( fet.id() ) )
569  {
570  deselectIds << fet.id();
571  }
572  else
573  {
574  selectIds << fet.id();
575  }
576  }
577 
578  modifySelection( selectIds, deselectIds );
579 }
580 
582 {
583  if ( mSelectedFeatureIds.isEmpty() )
584  return;
585 
586  const QgsFeatureIds previous = mSelectedFeatureIds;
588  mPreviousSelectedFeatureIds = previous;
589 }
590 
592 {
593  if ( mPreviousSelectedFeatureIds.isEmpty() || !mSelectedFeatureIds.empty() )
594  return;
595 
596  selectByIds( mPreviousSelectedFeatureIds );
597 }
598 
600 {
601  return mDataProvider;
602 }
603 
605 {
606  return mDataProvider;
607 }
608 
609 void QgsVectorLayer::setProviderEncoding( const QString &encoding )
610 {
611  if ( mValid && mDataProvider && mDataProvider->encoding() != encoding )
612  {
613  mDataProvider->setEncoding( encoding );
614  updateFields();
615  }
616 }
617 
619 {
620  delete mDiagramRenderer;
621  mDiagramRenderer = r;
622  emit rendererChanged();
623  emit styleChanged();
624 }
625 
627 {
628  return QgsWkbTypes::geometryType( mWkbType );
629 }
630 
632 {
633  return mWkbType;
634 }
635 
637 {
638  if ( !mValid || !isSpatial() || mSelectedFeatureIds.isEmpty() ) //no selected features
639  {
640  return QgsRectangle( 0, 0, 0, 0 );
641  }
642 
643  QgsRectangle r, retval;
644  retval.setMinimal();
645 
646  QgsFeature fet;
647  if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
648  {
650  .setFilterFids( mSelectedFeatureIds )
651  .setNoAttributes() );
652 
653  while ( fit.nextFeature( fet ) )
654  {
655  if ( !fet.hasGeometry() )
656  continue;
657  r = fet.geometry().boundingBox();
658  retval.combineExtentWith( r );
659  }
660  }
661  else
662  {
664  .setNoAttributes() );
665 
666  while ( fit.nextFeature( fet ) )
667  {
668  if ( mSelectedFeatureIds.contains( fet.id() ) )
669  {
670  if ( fet.hasGeometry() )
671  {
672  r = fet.geometry().boundingBox();
673  retval.combineExtentWith( r );
674  }
675  }
676  }
677  }
678 
679  if ( retval.width() == 0.0 || retval.height() == 0.0 )
680  {
681  // If all of the features are at the one point, buffer the
682  // rectangle a bit. If they are all at zero, do something a bit
683  // more crude.
684 
685  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
686  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
687  {
688  retval.set( -1.0, -1.0, 1.0, 1.0 );
689  }
690  }
691 
692  return retval;
693 }
694 
696 {
697  return mLabelsEnabled && static_cast< bool >( mLabeling );
698 }
699 
701 {
702  mLabelsEnabled = enabled;
703 }
704 
706 {
707  if ( !mDiagramRenderer || !mDiagramLayerSettings )
708  return false;
709 
710  QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
711  if ( !settingList.isEmpty() )
712  {
713  return settingList.at( 0 ).enabled;
714  }
715  return false;
716 }
717 
718 long QgsVectorLayer::featureCount( const QString &legendKey ) const
719 {
720  if ( !mSymbolFeatureCounted )
721  return -1;
722 
723  return mSymbolFeatureCountMap.value( legendKey, -1 );
724 }
725 
726 QgsFeatureIds QgsVectorLayer::symbolFeatureIds( const QString &legendKey ) const
727 {
728  if ( !mSymbolFeatureCounted )
729  return QgsFeatureIds();
730 
731  return mSymbolFeatureIdMap.value( legendKey, QgsFeatureIds() );
732 }
733 
735 {
736  if ( mSymbolFeatureCounted || mFeatureCounter )
737  return mFeatureCounter;
738 
739  mSymbolFeatureCountMap.clear();
740  mSymbolFeatureIdMap.clear();
741 
742  if ( !mValid )
743  {
744  QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer" ), 3 );
745  return mFeatureCounter;
746  }
747  if ( !mDataProvider )
748  {
749  QgsDebugMsgLevel( QStringLiteral( "invoked with null mDataProvider" ), 3 );
750  return mFeatureCounter;
751  }
752  if ( !mRenderer )
753  {
754  QgsDebugMsgLevel( QStringLiteral( "invoked with null mRenderer" ), 3 );
755  return mFeatureCounter;
756  }
757 
758  if ( !mFeatureCounter )
759  {
760  mFeatureCounter = new QgsVectorLayerFeatureCounter( this );
761  connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted );
762  connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated );
763 
764  QgsApplication::taskManager()->addTask( mFeatureCounter );
765  }
766 
767  return mFeatureCounter;
768 }
769 
771 {
772  // do not update extent by default when trust project option is activated
773  if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.isNull() ) )
774  mValidExtent = false;
775 }
776 
778 {
780  mValidExtent = true;
781 }
782 
783 void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
784 {
785  if ( !mDefaultValueOnUpdateFields.isEmpty() )
786  {
787  if ( !feature.isValid() )
788  feature = getFeature( fid );
789 
790  int size = mFields.size();
791  for ( int idx : qgis::as_const( mDefaultValueOnUpdateFields ) )
792  {
793  if ( idx < 0 || idx >= size )
794  continue;
795 
796  feature.setAttribute( idx, defaultValue( idx, feature ) );
797  updateFeature( feature, true );
798  }
799  }
800 }
801 
803 {
804  QgsRectangle rect;
805  rect.setMinimal();
806 
807  if ( !isSpatial() )
808  return rect;
809 
810  if ( !mValidExtent && mLazyExtent && mDataProvider && !mDataProvider->hasMetadata() && mReadExtentFromXml && !mXmlExtent.isNull() )
811  {
812  mExtent = mXmlExtent;
813  mValidExtent = true;
814  mLazyExtent = false;
815  }
816 
817  if ( !mValidExtent && mLazyExtent && mDataProvider && mDataProvider->isValid() )
818  {
819  // get the extent
820  QgsRectangle mbr = mDataProvider->extent();
821 
822  // show the extent
823  QgsDebugMsgLevel( QStringLiteral( "Extent of layer: %1" ).arg( mbr.toString() ), 3 );
824  // store the extent
825  mValidExtent = true;
826  mExtent = mbr;
827 
828  mLazyExtent = false;
829  }
830 
831  if ( mValidExtent )
832  return QgsMapLayer::extent();
833 
834  if ( !mValid || !mDataProvider )
835  {
836  QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
837  return rect;
838  }
839 
840  if ( !mEditBuffer ||
841  ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() ) ||
842  QgsDataSourceUri( mDataProvider->dataSourceUri() ).useEstimatedMetadata() )
843  {
844  mDataProvider->updateExtents();
845 
846  // get the extent of the layer from the provider
847  // but only when there are some features already
848  if ( mDataProvider->featureCount() != 0 )
849  {
850  QgsRectangle r = mDataProvider->extent();
851  rect.combineExtentWith( r );
852  }
853 
854  if ( mEditBuffer )
855  {
856  for ( QgsFeatureMap::const_iterator it = mEditBuffer->mAddedFeatures.constBegin(); it != mEditBuffer->mAddedFeatures.constEnd(); ++it )
857  {
858  if ( it->hasGeometry() )
859  {
860  QgsRectangle r = it->geometry().boundingBox();
861  rect.combineExtentWith( r );
862  }
863  }
864  }
865  }
866  else
867  {
869  .setNoAttributes() );
870 
871  QgsFeature fet;
872  while ( fit.nextFeature( fet ) )
873  {
874  if ( fet.hasGeometry() && fet.geometry().type() != QgsWkbTypes::UnknownGeometry )
875  {
876  QgsRectangle bb = fet.geometry().boundingBox();
877  rect.combineExtentWith( bb );
878  }
879  }
880  }
881 
882  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
883  {
884  // special case when there are no features in provider nor any added
885  rect = QgsRectangle(); // use rectangle with zero coordinates
886  }
887 
888  mValidExtent = true;
889  mExtent = rect;
890 
891  // Send this (hopefully) up the chain to the map canvas
892  emit recalculateExtents();
893 
894  return rect;
895 }
896 
898 {
899  return extent();
900 }
901 
902 QString QgsVectorLayer::subsetString() const
903 {
904  if ( !mValid || !mDataProvider )
905  {
906  QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
907  return QString();
908  }
909  return mDataProvider->subsetString();
910 }
911 
912 bool QgsVectorLayer::setSubsetString( const QString &subset )
913 {
914  if ( !mValid || !mDataProvider || mEditBuffer )
915  {
916  QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
917  return false;
918  }
919 
920  if ( subset == mDataProvider->subsetString() )
921  return true;
922 
923  bool res = mDataProvider->setSubsetString( subset );
924 
925  // get the updated data source string from the provider
926  mDataSource = mDataProvider->dataSourceUri();
927  updateExtents();
928  updateFields();
929 
930  if ( res )
931  {
932  emit subsetStringChanged();
933  triggerRepaint();
934  }
935 
936  return res;
937 }
938 
940 {
941  if ( mValid && mDataProvider && !mEditBuffer && ( isSpatial() && geometryType() != QgsWkbTypes::PointGeometry ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
942  {
943  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
944 
945  // check maximum scale at which generalisation should be carried out
946  return !( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale );
947  }
948  return false;
949 }
950 
952 {
953  return mConditionalStyles;
954 }
955 
957 {
958  if ( !mValid || !mDataProvider )
959  return QgsFeatureIterator();
960 
961  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
962 }
963 
965 {
966  QgsFeature feature;
968  if ( feature.isValid() )
969  return feature.geometry();
970  else
971  return QgsGeometry();
972 }
973 
974 bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
975 {
976  if ( !mValid || !mEditBuffer || !mDataProvider )
977  return false;
978 
979 
980  if ( mGeometryOptions->isActive() )
981  {
982  QgsGeometry geom = feature.geometry();
983  mGeometryOptions->apply( geom );
984  feature.setGeometry( geom );
985  }
986 
987  bool success = mEditBuffer->addFeature( feature );
988 
989  if ( success )
990  {
991  updateExtents();
992 
993  if ( mJoinBuffer->containsJoins() )
994  success = mJoinBuffer->addFeature( feature );
995  }
996 
997  return success;
998 }
999 
1000 bool QgsVectorLayer::updateFeature( QgsFeature &updatedFeature, bool skipDefaultValues )
1001 {
1002  if ( !mEditBuffer || !mDataProvider )
1003  {
1004  return false;
1005  }
1006 
1007  QgsFeature currentFeature = getFeature( updatedFeature.id() );
1008  if ( currentFeature.isValid() )
1009  {
1010  bool hasChanged = false;
1011  bool hasError = false;
1012 
1013  if ( ( updatedFeature.hasGeometry() || currentFeature.hasGeometry() ) && !updatedFeature.geometry().equals( currentFeature.geometry() ) )
1014  {
1015  QgsGeometry geometry = updatedFeature.geometry();
1016  if ( changeGeometry( updatedFeature.id(), geometry, true ) )
1017  {
1018  hasChanged = true;
1019  updatedFeature.setGeometry( geometry );
1020  }
1021  else
1022  {
1023  QgsDebugMsgLevel( QStringLiteral( "geometry of feature %1 could not be changed." ).arg( updatedFeature.id() ), 3 );
1024  }
1025  }
1026 
1027  QgsAttributes fa = updatedFeature.attributes();
1028  QgsAttributes ca = currentFeature.attributes();
1029 
1030  for ( int attr = 0; attr < fa.count(); ++attr )
1031  {
1032  if ( fa.at( attr ) != ca.at( attr ) )
1033  {
1034  if ( changeAttributeValue( updatedFeature.id(), attr, fa.at( attr ), ca.at( attr ), true ) )
1035  {
1036  hasChanged = true;
1037  }
1038  else
1039  {
1040  QgsDebugMsgLevel( QStringLiteral( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.id() ), 3 );
1041  hasError = true;
1042  }
1043  }
1044  }
1045  if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() && !skipDefaultValues )
1046  updateDefaultValues( updatedFeature.id(), updatedFeature );
1047 
1048  return !hasError;
1049  }
1050  else
1051  {
1052  QgsDebugMsgLevel( QStringLiteral( "feature %1 could not be retrieved" ).arg( updatedFeature.id() ), 3 );
1053  return false;
1054  }
1055 }
1056 
1057 
1058 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1059 {
1060  if ( !mValid || !mEditBuffer || !mDataProvider )
1061  return false;
1062 
1063  QgsVectorLayerEditUtils utils( this );
1064  bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
1065  if ( result )
1066  updateExtents();
1067  return result;
1068 }
1069 
1070 
1071 bool QgsVectorLayer::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
1072 {
1073  if ( !mValid || !mEditBuffer || !mDataProvider )
1074  return false;
1075 
1076  QgsVectorLayerEditUtils utils( this );
1077  bool result = utils.insertVertex( point, atFeatureId, beforeVertex );
1078  if ( result )
1079  updateExtents();
1080  return result;
1081 }
1082 
1083 
1084 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1085 {
1086  if ( !mValid || !mEditBuffer || !mDataProvider )
1087  return false;
1088 
1089  QgsVectorLayerEditUtils utils( this );
1090  bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
1091 
1092  if ( result )
1093  updateExtents();
1094  return result;
1095 }
1096 
1097 bool QgsVectorLayer::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
1098 {
1099  if ( !mValid || !mEditBuffer || !mDataProvider )
1100  return false;
1101 
1102  QgsVectorLayerEditUtils utils( this );
1103  bool result = utils.moveVertex( p, atFeatureId, atVertex );
1104 
1105  if ( result )
1106  updateExtents();
1107  return result;
1108 }
1109 
1111 {
1112  if ( !mValid || !mEditBuffer || !mDataProvider )
1114 
1115  QgsVectorLayerEditUtils utils( this );
1116  EditResult result = utils.deleteVertex( featureId, vertex );
1117 
1118  if ( result == Success )
1119  updateExtents();
1120  return result;
1121 }
1122 
1123 
1125 {
1126  if ( !mValid || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1127  {
1128  return false;
1129  }
1130 
1131  if ( !isEditable() )
1132  {
1133  return false;
1134  }
1135 
1136  int deleted = 0;
1137  int count = mSelectedFeatureIds.size();
1138  // Make a copy since deleteFeature modifies mSelectedFeatureIds
1139  QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1140  const auto constSelectedFeatures = selectedFeatures;
1141  for ( QgsFeatureId fid : constSelectedFeatures )
1142  {
1143  deleted += deleteFeature( fid ); // removes from selection
1144  }
1145 
1146  triggerRepaint();
1147  updateExtents();
1148 
1149  if ( deletedCount )
1150  {
1151  *deletedCount = deleted;
1152  }
1153 
1154  return deleted == count;
1155 }
1156 
1157 static const QgsPointSequence vectorPointXY2pointSequence( const QVector<QgsPointXY> &points )
1158 {
1159  QgsPointSequence pts;
1160  pts.reserve( points.size() );
1161  QVector<const QgsPointXY>::iterator it = points.constBegin();
1162  while ( it != points.constEnd() )
1163  {
1164  pts.append( QgsPoint( *it ) );
1165  it++;
1166  }
1167  return pts;
1168 }
1169 QgsGeometry::OperationResult QgsVectorLayer::addRing( const QVector<QgsPointXY> &ring, QgsFeatureId *featureId )
1170 {
1171  return addRing( vectorPointXY2pointSequence( ring ), featureId );
1172 }
1173 
1175 {
1176  if ( !mValid || !mEditBuffer || !mDataProvider )
1177  return QgsGeometry::OperationResult::LayerNotEditable;
1178 
1179  QgsVectorLayerEditUtils utils( this );
1180  QgsGeometry::OperationResult result = QgsGeometry::OperationResult::AddRingNotInExistingFeature;
1181 
1182  //first try with selected features
1183  if ( !mSelectedFeatureIds.isEmpty() )
1184  {
1185  result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1186  }
1187 
1188  if ( result != QgsGeometry::OperationResult::Success )
1189  {
1190  //try with all intersecting features
1191  result = utils.addRing( ring, QgsFeatureIds(), featureId );
1192  }
1193 
1194  return result;
1195 }
1196 
1198 {
1199  if ( !mValid || !mEditBuffer || !mDataProvider )
1200  {
1201  delete ring;
1202  return QgsGeometry::OperationResult::LayerNotEditable;
1203  }
1204 
1205  if ( !ring )
1206  {
1207  return QgsGeometry::OperationResult::InvalidInputGeometryType;
1208  }
1209 
1210  if ( !ring->isClosed() )
1211  {
1212  delete ring;
1213  return QgsGeometry::OperationResult::AddRingNotClosed;
1214  }
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( static_cast< QgsCurve * >( ring->clone() ), mSelectedFeatureIds, featureId );
1223  }
1224 
1225  if ( result != QgsGeometry::OperationResult::Success )
1226  {
1227  //try with all intersecting features
1228  result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), QgsFeatureIds(), featureId );
1229  }
1230 
1231  delete ring;
1232  return result;
1233 }
1234 
1235 QgsGeometry::OperationResult QgsVectorLayer::addPart( const QList<QgsPointXY> &points )
1236 {
1237  QgsPointSequence pts;
1238  pts.reserve( points.size() );
1239  for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd() ; ++it )
1240  {
1241  pts.append( QgsPoint( *it ) );
1242  }
1243  return addPart( pts );
1244 }
1245 
1246 QgsGeometry::OperationResult QgsVectorLayer::addPart( const QVector<QgsPointXY> &points )
1247 {
1248  return addPart( vectorPointXY2pointSequence( points ) );
1249 }
1250 
1252 {
1253  if ( !mValid || !mEditBuffer || !mDataProvider )
1254  return QgsGeometry::OperationResult::LayerNotEditable;
1255 
1256  //number of selected features must be 1
1257 
1258  if ( mSelectedFeatureIds.empty() )
1259  {
1260  QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1261  return QgsGeometry::OperationResult::SelectionIsEmpty;
1262  }
1263  else if ( mSelectedFeatureIds.size() > 1 )
1264  {
1265  QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1266  return QgsGeometry::OperationResult::SelectionIsGreaterThanOne;
1267  }
1268 
1269  QgsVectorLayerEditUtils utils( this );
1270  QgsGeometry::OperationResult result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1271 
1272  if ( result == QgsGeometry::OperationResult::Success )
1273  updateExtents();
1274  return result;
1275 }
1276 
1278 {
1279  if ( !mValid || !mEditBuffer || !mDataProvider )
1280  return QgsGeometry::OperationResult::LayerNotEditable;
1281 
1282  //number of selected features must be 1
1283 
1284  if ( mSelectedFeatureIds.empty() )
1285  {
1286  QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1287  return QgsGeometry::OperationResult::SelectionIsEmpty;
1288  }
1289  else if ( mSelectedFeatureIds.size() > 1 )
1290  {
1291  QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1292  return QgsGeometry::OperationResult::SelectionIsGreaterThanOne;
1293  }
1294 
1295  QgsVectorLayerEditUtils utils( this );
1296  QgsGeometry::OperationResult result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1297 
1298  if ( result == QgsGeometry::OperationResult::Success )
1299  updateExtents();
1300  return result;
1301 }
1302 
1303 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1304 {
1305  if ( !mValid || !mEditBuffer || !mDataProvider )
1306  return QgsGeometry::OperationResult::LayerNotEditable;
1307 
1308  QgsVectorLayerEditUtils utils( this );
1309  int result = utils.translateFeature( featureId, dx, dy );
1310 
1311  if ( result == QgsGeometry::OperationResult::Success )
1312  updateExtents();
1313  return result;
1314 }
1315 
1316 QgsGeometry::OperationResult QgsVectorLayer::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1317 {
1318  return splitParts( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1319 }
1321 {
1322  if ( !mValid || !mEditBuffer || !mDataProvider )
1323  return QgsGeometry::OperationResult::LayerNotEditable;
1324 
1325  QgsVectorLayerEditUtils utils( this );
1326  return utils.splitParts( splitLine, topologicalEditing );
1327 }
1328 QgsGeometry::OperationResult QgsVectorLayer::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1329 {
1330  return splitFeatures( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1331 }
1332 
1334 {
1335  if ( !mValid || !mEditBuffer || !mDataProvider )
1336  return QgsGeometry::OperationResult::LayerNotEditable;
1337 
1338  QgsVectorLayerEditUtils utils( this );
1339  return utils.splitFeatures( splitLine, topologicalEditing );
1340 }
1341 
1343 {
1344  if ( !mValid || !mEditBuffer || !mDataProvider )
1345  return -1;
1346 
1347  QgsVectorLayerEditUtils utils( this );
1348  return utils.addTopologicalPoints( geom );
1349 }
1350 
1352 {
1353  return addTopologicalPoints( QgsPoint( p ) );
1354 }
1355 
1357 {
1358  if ( !mValid || !mEditBuffer || !mDataProvider )
1359  return -1;
1360 
1361  QgsVectorLayerEditUtils utils( this );
1362  return utils.addTopologicalPoints( p );
1363 }
1364 
1366 {
1367  if ( mLabeling == labeling )
1368  return;
1369 
1370  delete mLabeling;
1371  mLabeling = labeling;
1372 }
1373 
1375 {
1376  if ( !mValid || !mDataProvider )
1377  {
1378  return false;
1379  }
1380 
1381  // allow editing if provider supports any of the capabilities
1382  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1383  {
1384  return false;
1385  }
1386 
1387  if ( mReadOnly )
1388  {
1389  return false;
1390  }
1391 
1392  if ( mEditBuffer )
1393  {
1394  // editing already underway
1395  return false;
1396  }
1397 
1398  emit beforeEditingStarted();
1399 
1400  mDataProvider->enterUpdateMode();
1401 
1402  if ( mDataProvider->transaction() )
1403  {
1404  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1405 
1406  connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
1407  }
1408  else
1409  {
1410  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1411  }
1412  // forward signals
1413  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
1414  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
1415  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1417  connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
1428 
1429  updateFields();
1430 
1431  emit editingStarted();
1432 
1433  return true;
1434 }
1435 
1437 {
1438  if ( mDataProvider )
1439  mDataProvider->setTransformContext( transformContext );
1440 }
1441 
1443 {
1444  if ( mRenderer )
1445  if ( !mRenderer->accept( visitor ) )
1446  return false;
1447 
1448  if ( mLabeling )
1449  if ( !mLabeling->accept( visitor ) )
1450  return false;
1451 
1452  return true;
1453 }
1454 
1455 bool QgsVectorLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1456 {
1457  QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsVectorLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1458 
1459  //process provider key
1460  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1461 
1462  if ( pkeyNode.isNull() )
1463  {
1464  mProviderKey.clear();
1465  }
1466  else
1467  {
1468  QDomElement pkeyElt = pkeyNode.toElement();
1469  mProviderKey = pkeyElt.text();
1470  }
1471 
1472  // determine type of vector layer
1473  if ( !mProviderKey.isNull() )
1474  {
1475  // if the provider string isn't empty, then we successfully
1476  // got the stored provider
1477  }
1478  else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
1479  {
1480  mProviderKey = QStringLiteral( "postgres" );
1481  }
1482  else
1483  {
1484  mProviderKey = QStringLiteral( "ogr" );
1485  }
1486 
1487  QgsDataProvider::ProviderOptions options { context.transformContext() };
1488  if ( ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) || !setDataProvider( mProviderKey, options ) )
1489  {
1490  if ( !( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) )
1491  {
1492  QgsDebugMsg( QStringLiteral( "Could not set data provider for layer %1" ).arg( publicSource() ) );
1493  }
1494  const QDomElement elem = layer_node.toElement();
1495 
1496  // for invalid layer sources, we fallback to stored wkbType if available
1497  if ( elem.hasAttribute( QStringLiteral( "wkbType" ) ) )
1498  mWkbType = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "wkbType" ) ), mWkbType );
1499  }
1500 
1501  QDomElement pkeyElem = pkeyNode.toElement();
1502  if ( !pkeyElem.isNull() )
1503  {
1504  QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1505  if ( mDataProvider && !encodingString.isEmpty() )
1506  {
1507  mDataProvider->setEncoding( encodingString );
1508  }
1509  }
1510 
1511  // load vector joins - does not resolve references to layers yet
1512  mJoinBuffer->readXml( layer_node );
1513 
1514  updateFields();
1515 
1516  QString errorMsg;
1517  if ( !readSymbology( layer_node, errorMsg, context ) )
1518  {
1519  return false;
1520  }
1521 
1522  readStyleManager( layer_node );
1523 
1524  QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1525  QDomNodeList depsNodes = depsNode.childNodes();
1526  QSet<QgsMapLayerDependency> sources;
1527  for ( int i = 0; i < depsNodes.count(); i++ )
1528  {
1529  QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1530  sources << QgsMapLayerDependency( source );
1531  }
1532  setDependencies( sources );
1533 
1535  QDomElement legendElem = layer_node.firstChildElement( QStringLiteral( "legend" ) );
1536  if ( !legendElem.isNull() )
1537  legend->readXml( legendElem, context );
1538  setLegend( legend );
1539 
1540  // read extent
1541  if ( mReadExtentFromXml )
1542  {
1543  QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1544  if ( !extentNode.isNull() )
1545  {
1546  mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1547  }
1548  }
1549 
1550  // auxiliary layer
1551  const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
1552  const QDomElement asElem = asNode.toElement();
1553  if ( !asElem.isNull() )
1554  {
1555  mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
1556  }
1557 
1558  // QGIS Server WMS Dimensions
1559  mServerProperties->readXml( layer_node );
1560 
1561  return mValid; // should be true if read successfully
1562 
1563 } // void QgsVectorLayer::readXml
1564 
1565 
1566 void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag )
1567 {
1569  setDataSource( dataSource, baseName, provider, options, loadDefaultStyleFlag );
1570 }
1571 
1572 void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag )
1573 {
1575 
1576  mDataSource = dataSource;
1577  setName( baseName );
1578  setDataProvider( provider, options );
1579 
1580  if ( !mValid )
1581  {
1582  emit dataSourceChanged();
1583  return;
1584  }
1585 
1586  // Always set crs
1588 
1589  // reset style if loading default style, style is missing, or geometry type is has changed (and layer is valid)
1590  if ( !renderer() || !legend() || ( mValid && geomType != geometryType() ) || loadDefaultStyleFlag )
1591  {
1592  bool defaultLoadedFlag = false;
1593 
1594  if ( loadDefaultStyleFlag && isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1595  {
1596  // first try to create a renderer directly from the data provider
1597  std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1598  if ( defaultRenderer )
1599  {
1600  defaultLoadedFlag = true;
1601  setRenderer( defaultRenderer.release() );
1602  }
1603  }
1604 
1605  // else check if there is a default style / propertysheet defined
1606  // for this layer and if so apply it
1607  if ( !defaultLoadedFlag && loadDefaultStyleFlag )
1608  {
1609  loadDefaultStyle( defaultLoadedFlag );
1610  }
1611 
1612  // if the default style failed to load or was disabled use some very basic defaults
1613  if ( !defaultLoadedFlag && isSpatial() )
1614  {
1615  // add single symbol renderer
1617  }
1618 
1620 
1621  if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
1622  {
1623  std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
1624  if ( defaultLabeling )
1625  {
1626  setLabeling( defaultLabeling.release() );
1627  setLabelsEnabled( true );
1628  }
1629  }
1630  }
1631 
1632  emit dataSourceChanged();
1633  triggerRepaint();
1634 }
1635 
1636 QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
1637 {
1638  if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1639  {
1640  // first try to create a renderer directly from the data provider
1641  std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1642  if ( defaultRenderer )
1643  {
1644  resultFlag = true;
1645  setRenderer( defaultRenderer.release() );
1646  return QString();
1647  }
1648  }
1649 
1650  return QgsMapLayer::loadDefaultStyle( resultFlag );
1651 }
1652 
1653 
1654 bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options )
1655 {
1656  mProviderKey = provider;
1657  delete mDataProvider;
1658 
1659  // For Postgres provider primary key unicity is tested at construction time,
1660  // so it has to be set before initializing the provider,
1661  // this manipulation is necessary to preserve default behavior when
1662  // "trust layer metadata" project level option is set and checkPrimaryKeyUnicity
1663  // was not explicitly passed in the uri
1664  if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
1665  {
1666  const QString checkUnicityKey { QStringLiteral( "checkPrimaryKeyUnicity" ) };
1668  if ( ! uri.hasParam( checkUnicityKey ) )
1669  {
1670  uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
1671  mDataSource = uri.uri( false );
1672  }
1673  }
1674 
1675  mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, mDataSource, options ) );
1676  if ( !mDataProvider )
1677  {
1678  mValid = false;
1679  QgsDebugMsgLevel( QStringLiteral( "Unable to get data provider" ), 2 );
1680  return false;
1681  }
1682 
1683  mDataProvider->setParent( this );
1684  connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1685 
1686  QgsDebugMsgLevel( QStringLiteral( "Instantiated the data provider plugin" ), 2 );
1687 
1688  mValid = mDataProvider->isValid();
1689  if ( !mValid )
1690  {
1691  QgsDebugMsgLevel( QStringLiteral( "Invalid provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1692  return false;
1693  }
1694 
1695  if ( mDataProvider->capabilities() & QgsVectorDataProvider::ReadLayerMetadata )
1696  {
1697  setMetadata( mDataProvider->layerMetadata() );
1698  QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
1699  }
1700 
1701  // TODO: Check if the provider has the capability to send fullExtentCalculated
1702  connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
1703 
1704  // get and store the feature type
1705  mWkbType = mDataProvider->wkbType();
1706 
1707  updateFields();
1708 
1709  if ( mProviderKey == QLatin1String( "postgres" ) )
1710  {
1711  // update datasource from data provider computed one
1712  mDataSource = mDataProvider->dataSourceUri( false );
1713 
1714  QgsDebugMsgLevel( QStringLiteral( "Beautifying layer name %1" ).arg( name() ), 3 );
1715 
1716  // adjust the display name for postgres layers
1717  QRegExp reg( R"lit("[^"]+"\."([^"] + )"( \([^)]+\))?)lit" );
1718  if ( reg.indexIn( name() ) >= 0 )
1719  {
1720  QStringList stuff = reg.capturedTexts();
1721  QString lName = stuff[1];
1722 
1723  const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
1724 
1725  QMap<QString, QgsMapLayer *>::const_iterator it;
1726  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1727  ;
1728 
1729  if ( it != layers.constEnd() && stuff.size() > 2 )
1730  {
1731  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1732  }
1733 
1734  if ( !lName.isEmpty() )
1735  setName( lName );
1736  }
1737  QgsDebugMsgLevel( QStringLiteral( "Beautified layer name %1" ).arg( name() ), 3 );
1738  }
1739  else if ( mProviderKey == QLatin1String( "osm" ) )
1740  {
1741  // make sure that the "observer" has been removed from URI to avoid crashes
1742  mDataSource = mDataProvider->dataSourceUri();
1743  }
1744  else if ( provider == QLatin1String( "ogr" ) )
1745  {
1746  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1747  mDataSource = mDataProvider->dataSourceUri();
1748  if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1749  mDataSource.chop( 10 );
1750  }
1751  else if ( provider == QStringLiteral( "memory" ) )
1752  {
1753  // required so that source differs between memory layers
1754  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1755  }
1756 
1757  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::emitDataChanged );
1758  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
1759 
1760  return true;
1761 } // QgsVectorLayer:: setDataProvider
1762 
1763 
1764 
1765 
1766 /* virtual */
1767 bool QgsVectorLayer::writeXml( QDomNode &layer_node,
1768  QDomDocument &document,
1769  const QgsReadWriteContext &context ) const
1770 {
1771  // first get the layer element so that we can append the type attribute
1772 
1773  QDomElement mapLayerNode = layer_node.toElement();
1774 
1775  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1776  {
1777  QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1778  return false;
1779  }
1780 
1781  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "vector" ) );
1782 
1783  // set the geometry type
1784  mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1785  mapLayerNode.setAttribute( QStringLiteral( "wkbType" ), qgsEnumValueToKey( wkbType() ) );
1786 
1787  // add provider node
1788  if ( mDataProvider )
1789  {
1790  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1791  provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1792  QDomText providerText = document.createTextNode( providerType() );
1793  provider.appendChild( providerText );
1794  layer_node.appendChild( provider );
1795  }
1796 
1797  //save joins
1798  mJoinBuffer->writeXml( layer_node, document );
1799 
1800  // dependencies
1801  QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1802  const auto constDependencies = dependencies();
1803  for ( const QgsMapLayerDependency &dep : constDependencies )
1804  {
1805  if ( dep.type() != QgsMapLayerDependency::PresenceDependency )
1806  continue;
1807  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1808  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1809  dependenciesElement.appendChild( depElem );
1810  }
1811  layer_node.appendChild( dependenciesElement );
1812 
1813  // change dependencies
1814  QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1815  for ( const QgsMapLayerDependency &dep : constDependencies )
1816  {
1817  if ( dep.type() != QgsMapLayerDependency::DataDependency )
1818  continue;
1819  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1820  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1821  dataDependenciesElement.appendChild( depElem );
1822  }
1823  layer_node.appendChild( dataDependenciesElement );
1824 
1825  // legend
1826  if ( legend() )
1827  {
1828  QDomElement legendElement = legend()->writeXml( document, context );
1829  if ( !legendElement.isNull() )
1830  layer_node.appendChild( legendElement );
1831  }
1832 
1833  // save expression fields
1834  mExpressionFieldBuffer->writeXml( layer_node, document );
1835 
1836  writeStyleManager( layer_node, document );
1837 
1838  // auxiliary layer
1839  QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
1840  if ( mAuxiliaryLayer )
1841  {
1842  const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
1843  asElem.setAttribute( QStringLiteral( "key" ), pkField );
1844  }
1845  layer_node.appendChild( asElem );
1846 
1847  // save QGIS Server WMS Dimension definitions
1848  mServerProperties->writeXml( layer_node, document );
1849 
1850  // renderer specific settings
1851  QString errorMsg;
1852  return writeSymbology( layer_node, document, errorMsg, context );
1853 }
1854 
1855 QString QgsVectorLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1856 {
1857  QString src( source );
1858 
1859  // TODO: what about postgres, mysql and others, they should not go through writePath()
1860  if ( providerType() == QLatin1String( "spatialite" ) )
1861  {
1862  QgsDataSourceUri uri( src );
1863  QString database = context.pathResolver().writePath( uri.database() );
1864  uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
1865  src = uri.uri();
1866  }
1867  else if ( providerType() == QLatin1String( "ogr" ) )
1868  {
1869  QStringList theURIParts = src.split( '|' );
1870  theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
1871  src = theURIParts.join( QStringLiteral( "|" ) );
1872  }
1873  else if ( providerType() == QLatin1String( "gpx" ) )
1874  {
1875  QStringList theURIParts = src.split( '?' );
1876  theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
1877  src = theURIParts.join( QStringLiteral( "?" ) );
1878  }
1879  else if ( providerType() == QLatin1String( "delimitedtext" ) )
1880  {
1881  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1882  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
1883  urlDest.setQueryItems( urlSource.queryItems() );
1884  src = QString::fromLatin1( urlDest.toEncoded() );
1885  }
1886  else if ( providerType() == QLatin1String( "memory" ) )
1887  {
1888  // Refetch the source from the provider, because adding fields actually changes the source for this provider.
1889  src = dataProvider()->dataSourceUri();
1890  }
1891  else if ( providerType() == QLatin1String( "virtual" ) )
1892  {
1893  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1894  QStringList theURIParts;
1895 
1896  QUrlQuery query = QUrlQuery( urlSource.query() );
1897  QList<QPair<QString, QString> > queryItems = query.queryItems();
1898 
1899  for ( int i = 0; i < queryItems.size(); i++ )
1900  {
1901  QString key = queryItems.at( i ).first;
1902  QString value = queryItems.at( i ).second;
1903  if ( key == QLatin1String( "layer" ) )
1904  {
1905  // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
1906  theURIParts = value.split( ':' );
1907  theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
1908  theURIParts[1] = context.pathResolver().writePath( theURIParts[1] );
1909  theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
1910  queryItems[i].second = theURIParts.join( QStringLiteral( ":" ) ) ;
1911  }
1912  }
1913 
1914  query.setQueryItems( queryItems );
1915 
1916  QUrl urlDest = QUrl( urlSource );
1917  urlDest.setQuery( query.query() );
1918  src = QString::fromLatin1( urlDest.toEncoded() );
1919  }
1920  else
1921  {
1922  src = context.pathResolver().writePath( src );
1923  }
1924 
1925  return src;
1926 }
1927 
1928 QString QgsVectorLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1929 {
1930  QString src( source );
1931 
1932  if ( provider == QLatin1String( "spatialite" ) )
1933  {
1934  QgsDataSourceUri uri( src );
1935  uri.setDatabase( context.pathResolver().readPath( uri.database() ) );
1936  src = uri.uri();
1937  }
1938  else if ( provider == QLatin1String( "ogr" ) )
1939  {
1940  QStringList theURIParts = src.split( '|' );
1941  theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
1942  src = theURIParts.join( QStringLiteral( "|" ) );
1943  }
1944  else if ( provider == QLatin1String( "gpx" ) )
1945  {
1946  QStringList theURIParts = src.split( '?' );
1947  theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
1948  src = theURIParts.join( QStringLiteral( "?" ) );
1949  }
1950  else if ( provider == QLatin1String( "delimitedtext" ) )
1951  {
1952  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1953 
1954  if ( !src.startsWith( QLatin1String( "file:" ) ) )
1955  {
1956  QUrl file = QUrl::fromLocalFile( src.left( src.indexOf( '?' ) ) );
1957  urlSource.setScheme( QStringLiteral( "file" ) );
1958  urlSource.setPath( file.path() );
1959  }
1960 
1961  QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
1962  urlDest.setQueryItems( urlSource.queryItems() );
1963  src = QString::fromLatin1( urlDest.toEncoded() );
1964  }
1965  else if ( provider == QLatin1String( "virtual" ) )
1966  {
1967  QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
1968  QStringList theURIParts;
1969 
1970  QUrlQuery query = QUrlQuery( urlSource.query() );
1971  QList<QPair<QString, QString> > queryItems = query.queryItems();
1972 
1973  for ( int i = 0; i < queryItems.size(); i++ )
1974  {
1975  QString key = queryItems.at( i ).first;
1976  QString value = queryItems.at( i ).second;
1977  if ( key == QLatin1String( "layer" ) )
1978  {
1979  // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
1980  theURIParts = value.split( ':' );
1981  theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
1982  theURIParts[1] = context.pathResolver().readPath( theURIParts[1] );
1983  theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
1984  queryItems[i].second = theURIParts.join( QStringLiteral( ":" ) ) ;
1985  }
1986  }
1987 
1988  query.setQueryItems( queryItems );
1989 
1990  QUrl urlDest = QUrl( urlSource );
1991  urlDest.setQuery( query.query() );
1992  src = QString::fromLatin1( urlDest.toEncoded() );
1993  }
1994  else
1995  {
1996  src = context.pathResolver().readPath( src );
1997  }
1998 
1999  return src;
2000 }
2001 
2002 
2003 
2005 {
2006  QgsMapLayer::resolveReferences( project );
2007  mJoinBuffer->resolveReferences( project );
2008 }
2009 
2010 
2011 bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage,
2012  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2013 {
2014  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Symbology" ) );
2015 
2016  if ( categories.testFlag( Fields ) )
2017  {
2018  if ( !mExpressionFieldBuffer )
2019  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
2020  mExpressionFieldBuffer->readXml( layerNode );
2021 
2022  updateFields();
2023  }
2024 
2025  QDomElement layerElement = layerNode.toElement();
2026 
2027  readCommonStyle( layerElement, context, categories );
2028 
2029  readStyle( layerNode, errorMessage, context, categories );
2030 
2031  if ( categories.testFlag( MapTips ) )
2032  mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
2033 
2034  if ( categories.testFlag( LayerConfiguration ) )
2035  mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
2036 
2037  // Try to migrate pre QGIS 3.0 display field property
2038  QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
2039  if ( mFields.lookupField( displayField ) < 0 )
2040  {
2041  // if it's not a field, it's a maptip
2042  if ( mMapTipTemplate.isEmpty() && categories.testFlag( MapTips ) )
2043  mMapTipTemplate = displayField;
2044  }
2045  else
2046  {
2047  if ( mDisplayExpression.isEmpty() && categories.testFlag( LayerConfiguration ) )
2048  mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
2049  }
2050 
2051  // process the attribute actions
2052  if ( categories.testFlag( Actions ) )
2053  mActions->readXml( layerNode );
2054 
2055  if ( categories.testFlag( Fields ) )
2056  {
2057  mAttributeAliasMap.clear();
2058  QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
2059  if ( !aliasesNode.isNull() )
2060  {
2061  QDomElement aliasElem;
2062 
2063  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
2064  for ( int i = 0; i < aliasNodeList.size(); ++i )
2065  {
2066  aliasElem = aliasNodeList.at( i ).toElement();
2067 
2068  QString field;
2069  if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
2070  {
2071  field = aliasElem.attribute( QStringLiteral( "field" ) );
2072  }
2073  else
2074  {
2075  int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
2076 
2077  if ( index >= 0 && index < fields().count() )
2078  field = fields().at( index ).name();
2079  }
2080 
2081  QString alias;
2082 
2083  if ( !aliasElem.attribute( QStringLiteral( "name" ) ).isEmpty() )
2084  {
2085  //if it has alias
2086  alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral( "name" ) ) );
2087  QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + aliasElem.attribute( QStringLiteral( "name" ) ), 3 );
2088  }
2089  else
2090  {
2091  //if it has no alias, it should be the fields translation
2092  alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), field );
2093  QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + field, 3 );
2094  //if it gets the exact field value, there has been no translation (or not even translation loaded) - so no alias should be generated;
2095  if ( alias == aliasElem.attribute( QStringLiteral( "field" ) ) )
2096  alias.clear();
2097  }
2098 
2099  QgsDebugMsgLevel( "field " + field + " origalias " + aliasElem.attribute( QStringLiteral( "name" ) ) + " trans " + alias, 3 );
2100  mAttributeAliasMap.insert( field, alias );
2101  }
2102  }
2103 
2104  // default expressions
2105  mDefaultExpressionMap.clear();
2106  QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
2107  if ( !defaultsNode.isNull() )
2108  {
2109  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
2110  for ( int i = 0; i < defaultNodeList.size(); ++i )
2111  {
2112  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
2113 
2114  QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
2115  QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
2116  bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
2117  if ( field.isEmpty() || expression.isEmpty() )
2118  continue;
2119 
2120  mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
2121  }
2122  }
2123 
2124  // constraints
2125  mFieldConstraints.clear();
2126  mFieldConstraintStrength.clear();
2127  QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
2128  if ( !constraintsNode.isNull() )
2129  {
2130  QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2131  for ( int i = 0; i < constraintNodeList.size(); ++i )
2132  {
2133  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2134 
2135  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2136  int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
2137  if ( field.isEmpty() || constraints == 0 )
2138  continue;
2139 
2140  mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
2141 
2142  int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
2143  int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
2144  int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
2145 
2146  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
2147  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
2148  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
2149  }
2150  }
2151  mFieldConstraintExpressions.clear();
2152  QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
2153  if ( !constraintExpressionsNode.isNull() )
2154  {
2155  QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2156  for ( int i = 0; i < constraintNodeList.size(); ++i )
2157  {
2158  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2159 
2160  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2161  QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
2162  QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
2163  if ( field.isEmpty() || exp.isEmpty() )
2164  continue;
2165 
2166  mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
2167  }
2168  }
2169 
2170  updateFields();
2171 
2172  //Attributes excluded from WMS and WFS
2173  mExcludeAttributesWMS.clear();
2174  QDomNode excludeWMSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWMS" ) );
2175  if ( !excludeWMSNode.isNull() )
2176  {
2177  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2178  for ( int i = 0; i < attributeNodeList.size(); ++i )
2179  {
2180  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
2181  }
2182  }
2183 
2184  mExcludeAttributesWFS.clear();
2185  QDomNode excludeWFSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWFS" ) );
2186  if ( !excludeWFSNode.isNull() )
2187  {
2188  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2189  for ( int i = 0; i < attributeNodeList.size(); ++i )
2190  {
2191  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
2192  }
2193  }
2194 
2195  // Load editor widget configuration
2196  QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
2197  QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
2198  for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
2199  {
2200  const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
2201  const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
2202 
2203  QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
2204 
2205  const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
2206  const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
2207  const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
2208  QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
2209  if ( widgetType == QStringLiteral( "ValueRelation" ) )
2210  {
2211  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() );
2212  }
2213  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
2214  mFieldWidgetSetups[fieldName] = setup;
2215  }
2216  }
2217 
2218  if ( categories.testFlag( GeometryOptions ) )
2219  mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral( "geometryOptions" ) ) );
2220 
2221  if ( categories.testFlag( Forms ) )
2222  mEditFormConfig.readXml( layerNode, context );
2223 
2224  if ( categories.testFlag( AttributeTable ) )
2225  {
2226  mAttributeTableConfig.readXml( layerNode );
2227  mConditionalStyles->readXml( layerNode, context );
2228  mStoredExpressionManager->readXml( layerNode );
2229  }
2230 
2231  if ( categories.testFlag( CustomProperties ) )
2232  readCustomProperties( layerNode, QStringLiteral( "variable" ) );
2233 
2234  QDomElement mapLayerNode = layerNode.toElement();
2235  if ( categories.testFlag( LayerConfiguration )
2236  && mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
2237  mReadOnly = true;
2238 
2239  updateFields();
2240 
2241  return true;
2242 }
2243 
2244 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage,
2245  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2246 {
2247  bool result = true;
2248  emit readCustomSymbology( node.toElement(), errorMessage );
2249 
2250  // we must try to restore a renderer if our geometry type is unknown
2251  // as this allows the renderer to be correctly restored even for layers
2252  // with broken sources
2253  if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2254  {
2255  // try renderer v2 first
2256  if ( categories.testFlag( Symbology ) )
2257  {
2258  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
2259  if ( !rendererElement.isNull() )
2260  {
2261  QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
2262  if ( r )
2263  {
2264  setRenderer( r );
2265  }
2266  else
2267  {
2268  result = false;
2269  }
2270  }
2271  // make sure layer has a renderer - if none exists, fallback to a default renderer
2272  if ( isSpatial() && !renderer() )
2273  {
2275  }
2276  }
2277 
2278  // read labeling definition
2279  if ( categories.testFlag( Labeling ) )
2280  {
2281  QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
2283  if ( labelingElement.isNull() ||
2284  ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
2285  {
2286  // make sure we have custom properties for labeling for 2.x projects
2287  // (custom properties should be already loaded when reading the whole layer from XML,
2288  // but when reading style, custom properties are not read)
2289  readCustomProperties( node, QStringLiteral( "labeling" ) );
2290 
2291  // support for pre-QGIS 3 labeling configurations written in custom properties
2292  labeling = readLabelingFromCustomProperties();
2293  }
2294  else
2295  {
2296  labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
2297  }
2298  setLabeling( labeling );
2299 
2300  if ( node.toElement().hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
2301  mLabelsEnabled = node.toElement().attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
2302  else
2303  mLabelsEnabled = true;
2304  }
2305 
2306  if ( categories.testFlag( Symbology ) )
2307  {
2308  // get and set the blend mode if it exists
2309  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
2310  if ( !blendModeNode.isNull() )
2311  {
2312  QDomElement e = blendModeNode.toElement();
2313  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2314  }
2315 
2316  // get and set the feature blend mode if it exists
2317  QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
2318  if ( !featureBlendModeNode.isNull() )
2319  {
2320  QDomElement e = featureBlendModeNode.toElement();
2321  setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2322  }
2323  }
2324 
2325  // get and set the layer transparency if it exists
2326  if ( categories.testFlag( Rendering ) )
2327  {
2328  QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
2329  if ( !layerTransparencyNode.isNull() )
2330  {
2331  QDomElement e = layerTransparencyNode.toElement();
2332  setOpacity( 1.0 - e.text().toInt() / 100.0 );
2333  }
2334  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
2335  if ( !layerOpacityNode.isNull() )
2336  {
2337  QDomElement e = layerOpacityNode.toElement();
2338  setOpacity( e.text().toDouble() );
2339  }
2340  }
2341 
2342  if ( categories.testFlag( Rendering ) )
2343  {
2344  QDomElement e = node.toElement();
2345 
2346  // get the simplification drawing settings
2347  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
2348  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
2349  mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
2350  mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
2351  mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
2352  }
2353 
2354  //diagram renderer and diagram layer settings
2355  if ( categories.testFlag( Diagrams ) )
2356  {
2357  delete mDiagramRenderer;
2358  mDiagramRenderer = nullptr;
2359  QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
2360  if ( !singleCatDiagramElem.isNull() )
2361  {
2362  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2363  mDiagramRenderer->readXml( singleCatDiagramElem, context );
2364  }
2365  QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
2366  if ( !linearDiagramElem.isNull() )
2367  {
2368  if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
2369  {
2370  // fix project from before QGIS 3.0
2371  int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
2372  if ( idx >= 0 && idx < mFields.count() )
2373  linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
2374  }
2375 
2376  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2377  mDiagramRenderer->readXml( linearDiagramElem, context );
2378  }
2379 
2380  if ( mDiagramRenderer )
2381  {
2382  QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
2383  if ( !diagramSettingsElem.isNull() )
2384  {
2385  bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
2386  bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
2387  bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
2388  if ( oldXPos || oldYPos || oldShow )
2389  {
2390  // fix project from before QGIS 3.0
2392  if ( oldXPos )
2393  {
2394  int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
2395  if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
2396  ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
2397  }
2398  if ( oldYPos )
2399  {
2400  int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
2401  if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
2402  ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
2403  }
2404  if ( oldShow )
2405  {
2406  int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
2407  if ( showColumn >= 0 && showColumn < mFields.count() )
2408  ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
2409  }
2410  QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
2412  {
2413  { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
2414  { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
2415  { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
2416  };
2417  ddp.writeXml( propertiesElem, defs );
2418  diagramSettingsElem.appendChild( propertiesElem );
2419  }
2420 
2421  delete mDiagramLayerSettings;
2422  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2423  mDiagramLayerSettings->readXml( diagramSettingsElem );
2424  }
2425  }
2426  }
2427  // end diagram
2428  }
2429  return result;
2430 }
2431 
2432 
2433 bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2434  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2435 {
2436  QDomElement layerElement = node.toElement();
2437  writeCommonStyle( layerElement, doc, context, categories );
2438 
2439  ( void )writeStyle( node, doc, errorMessage, context, categories );
2440 
2441  if ( categories.testFlag( GeometryOptions ) )
2442  mGeometryOptions->writeXml( node );
2443 
2444  if ( categories.testFlag( Fields ) )
2445  {
2446  QDomElement fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2447  node.appendChild( fieldConfigurationElement );
2448 
2449  int index = 0;
2450  for ( const QgsField &field : mFields )
2451  {
2452  QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2453  fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2454 
2455  fieldConfigurationElement.appendChild( fieldElement );
2456 
2457  QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
2458 
2459  // TODO : wrap this part in an if to only save if it was user-modified
2460  QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2461  fieldElement.appendChild( editWidgetElement );
2462  editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2463  QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2464 
2465  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2466  editWidgetElement.appendChild( editWidgetConfigElement );
2467  // END TODO : wrap this part in an if to only save if it was user-modified
2468 
2469  ++index;
2470  }
2471 
2472  //attribute aliases
2473  QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2474  for ( const QgsField &field : mFields )
2475  {
2476  QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2477  aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2478  aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2479  aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2480  aliasElem.appendChild( aliasEntryElem );
2481  }
2482  node.appendChild( aliasElem );
2483 
2484  //exclude attributes WMS
2485  QDomElement excludeWMSElem = doc.createElement( QStringLiteral( "excludeAttributesWMS" ) );
2486  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2487  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2488  {
2489  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2490  QDomText attrText = doc.createTextNode( *attWMSIt );
2491  attrElem.appendChild( attrText );
2492  excludeWMSElem.appendChild( attrElem );
2493  }
2494  node.appendChild( excludeWMSElem );
2495 
2496  //exclude attributes WFS
2497  QDomElement excludeWFSElem = doc.createElement( QStringLiteral( "excludeAttributesWFS" ) );
2498  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2499  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2500  {
2501  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2502  QDomText attrText = doc.createTextNode( *attWFSIt );
2503  attrElem.appendChild( attrText );
2504  excludeWFSElem.appendChild( attrElem );
2505  }
2506  node.appendChild( excludeWFSElem );
2507 
2508  //default expressions
2509  QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2510  for ( const QgsField &field : mFields )
2511  {
2512  QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2513  defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2514  defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
2515  defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2516  defaultsElem.appendChild( defaultElem );
2517  }
2518  node.appendChild( defaultsElem );
2519 
2520  // constraints
2521  QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2522  for ( const QgsField &field : mFields )
2523  {
2524  QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2525  constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2526  constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2527  constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2528  constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2529  constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2530  constraintsElem.appendChild( constraintElem );
2531  }
2532  node.appendChild( constraintsElem );
2533 
2534  // constraint expressions
2535  QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2536  for ( const QgsField &field : mFields )
2537  {
2538  QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2539  constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2540  constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2541  constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2542  constraintExpressionsElem.appendChild( constraintExpressionElem );
2543  }
2544  node.appendChild( constraintExpressionsElem );
2545 
2546  // save expression fields
2547  if ( !mExpressionFieldBuffer )
2548  {
2549  // can happen when saving style on a invalid layer
2551  dummy.writeXml( node, doc );
2552  }
2553  else
2554  {
2555  mExpressionFieldBuffer->writeXml( node, doc );
2556  }
2557  }
2558 
2559  // add attribute actions
2560  if ( categories.testFlag( Actions ) )
2561  mActions->writeXml( node );
2562 
2563  if ( categories.testFlag( AttributeTable ) )
2564  {
2565  mAttributeTableConfig.writeXml( node );
2566  mConditionalStyles->writeXml( node, doc, context );
2567  mStoredExpressionManager->writeXml( node );
2568  }
2569 
2570  if ( categories.testFlag( Forms ) )
2571  mEditFormConfig.writeXml( node, context );
2572 
2573  // save readonly state
2574  if ( categories.testFlag( LayerConfiguration ) )
2575  node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2576 
2577  // save preview expression
2578  if ( categories.testFlag( LayerConfiguration ) )
2579  {
2580  QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2581  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2582  prevExpElem.appendChild( prevExpText );
2583  node.appendChild( prevExpElem );
2584  }
2585 
2586  // save map tip
2587  if ( categories.testFlag( MapTips ) )
2588  {
2589  QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2590  QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2591  mapTipElem.appendChild( mapTipText );
2592  node.toElement().appendChild( mapTipElem );
2593  }
2594 
2595  return true;
2596 }
2597 
2598 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2599  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2600 {
2601  QDomElement mapLayerNode = node.toElement();
2602 
2603  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2604 
2605  if ( isSpatial() )
2606  {
2607  if ( categories.testFlag( Symbology ) )
2608  {
2609  if ( mRenderer )
2610  {
2611  QDomElement rendererElement = mRenderer->save( doc, context );
2612  node.appendChild( rendererElement );
2613  }
2614  }
2615 
2616  if ( categories.testFlag( Labeling ) )
2617  {
2618  if ( mLabeling )
2619  {
2620  QDomElement labelingElement = mLabeling->save( doc, context );
2621  node.appendChild( labelingElement );
2622  }
2623  mapLayerNode.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2624  }
2625 
2626  // save the simplification drawing settings
2627  if ( categories.testFlag( Rendering ) )
2628  {
2629  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2630  mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2631  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2632  mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2633  mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2634  }
2635 
2636  //save customproperties
2637  if ( categories.testFlag( CustomProperties ) )
2638  {
2639  writeCustomProperties( node, doc );
2640  }
2641 
2642  if ( categories.testFlag( Symbology ) )
2643  {
2644  // add the blend mode field
2645  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2646  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2647  blendModeElem.appendChild( blendModeText );
2648  node.appendChild( blendModeElem );
2649 
2650  // add the feature blend mode field
2651  QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2652  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2653  featureBlendModeElem.appendChild( featureBlendModeText );
2654  node.appendChild( featureBlendModeElem );
2655  }
2656 
2657  // add the layer opacity
2658  if ( categories.testFlag( Rendering ) )
2659  {
2660  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
2661  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
2662  layerOpacityElem.appendChild( layerOpacityText );
2663  node.appendChild( layerOpacityElem );
2664  }
2665 
2666  if ( categories.testFlag( Diagrams ) && mDiagramRenderer )
2667  {
2668  mDiagramRenderer->writeXml( mapLayerNode, doc, context );
2669  if ( mDiagramLayerSettings )
2670  mDiagramLayerSettings->writeXml( mapLayerNode, doc );
2671  }
2672  }
2673  return true;
2674 }
2675 
2676 bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
2677 {
2678  // get the Name element
2679  QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2680  if ( nameElem.isNull() )
2681  {
2682  errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2683  }
2684 
2685  if ( isSpatial() )
2686  {
2687  QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
2688  if ( !r )
2689  return false;
2690 
2691  setRenderer( r );
2692 
2693  // labeling
2694  readSldLabeling( node );
2695  }
2696  return true;
2697 }
2698 
2699 bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsStringMap &props ) const
2700 {
2701  Q_UNUSED( errorMessage )
2702 
2703  QgsStringMap localProps = QgsStringMap( props );
2704  if ( hasScaleBasedVisibility() )
2705  {
2707  }
2708 
2709  if ( isSpatial() )
2710  {
2711  // store the Name element
2712  QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
2713  nameNode.appendChild( doc.createTextNode( name() ) );
2714  node.appendChild( nameNode );
2715 
2716  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
2717  node.appendChild( userStyleElem );
2718 
2719  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
2720  nameElem.appendChild( doc.createTextNode( name() ) );
2721 
2722  userStyleElem.appendChild( nameElem );
2723 
2724  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
2725  userStyleElem.appendChild( featureTypeStyleElem );
2726 
2727  mRenderer->toSld( doc, featureTypeStyleElem, localProps );
2728  if ( labelsEnabled() )
2729  {
2730  mLabeling->toSld( featureTypeStyleElem, localProps );
2731  }
2732  }
2733  return true;
2734 }
2735 
2736 
2737 bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
2738 {
2739  if ( !mEditBuffer || !mDataProvider )
2740  {
2741  return false;
2742  }
2743 
2744  if ( mGeometryOptions->isActive() )
2745  mGeometryOptions->apply( geom );
2746 
2747  updateExtents();
2748 
2749  bool result = mEditBuffer->changeGeometry( fid, geom );
2750 
2751  if ( result )
2752  {
2753  updateExtents();
2754  if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
2755  updateDefaultValues( fid );
2756  }
2757  return result;
2758 }
2759 
2760 
2761 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
2762 {
2763  bool result = false;
2764 
2765  switch ( fields().fieldOrigin( field ) )
2766  {
2767  case QgsFields::OriginJoin:
2768  result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2769  if ( result )
2770  emit attributeValueChanged( fid, field, newValue );
2771  break;
2772 
2774  case QgsFields::OriginEdit:
2776  {
2777  if ( mEditBuffer && mDataProvider )
2778  result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2779  break;
2780  }
2781 
2783  break;
2784  }
2785 
2786  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
2787  updateDefaultValues( fid );
2788 
2789  return result;
2790 }
2791 
2792 bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
2793 {
2794  bool result = true;
2795 
2796  QgsAttributeMap newValuesJoin;
2797  QgsAttributeMap oldValuesJoin;
2798 
2799  QgsAttributeMap newValuesNotJoin;
2800  QgsAttributeMap oldValuesNotJoin;
2801 
2802  for ( auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
2803  {
2804  const int field = it.key();
2805  const QVariant newValue = it.value();
2806  QVariant oldValue;
2807 
2808  if ( oldValues.contains( field ) )
2809  oldValue = oldValues[field];
2810 
2811  switch ( fields().fieldOrigin( field ) )
2812  {
2813  case QgsFields::OriginJoin:
2814  newValuesJoin[field] = newValue;
2815  oldValuesJoin[field] = oldValue;
2816  break;
2817 
2819  case QgsFields::OriginEdit:
2821  {
2822  newValuesNotJoin[field] = newValue;
2823  oldValuesNotJoin[field] = oldValue;
2824  break;
2825  }
2826 
2828  break;
2829  }
2830  }
2831 
2832  if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
2833  {
2834  result = mJoinBuffer->changeAttributeValues( fid, newValuesJoin, oldValuesJoin );
2835  }
2836 
2837  if ( ! newValuesNotJoin.isEmpty() && mEditBuffer && mDataProvider )
2838  {
2839  result &= mEditBuffer->changeAttributeValues( fid, newValues, oldValues );
2840  }
2841 
2842  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
2843  {
2844  updateDefaultValues( fid );
2845  }
2846 
2847  return result;
2848 }
2849 
2851 {
2852  if ( !mEditBuffer || !mDataProvider )
2853  return false;
2854 
2855  return mEditBuffer->addAttribute( field );
2856 }
2857 
2859 {
2860  if ( attIndex < 0 || attIndex >= fields().count() )
2861  return;
2862 
2863  QString name = fields().at( attIndex ).name();
2864  mFields[ attIndex ].setAlias( QString() );
2865  if ( mAttributeAliasMap.contains( name ) )
2866  {
2867  mAttributeAliasMap.remove( name );
2868  updateFields();
2869  mEditFormConfig.setFields( mFields );
2870  emit layerModified();
2871  }
2872 }
2873 
2874 bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
2875 {
2876  if ( index < 0 || index >= fields().count() )
2877  return false;
2878 
2879  switch ( mFields.fieldOrigin( index ) )
2880  {
2882  {
2883  if ( mExpressionFieldBuffer )
2884  {
2885  int oi = mFields.fieldOriginIndex( index );
2886  mExpressionFieldBuffer->renameExpression( oi, newName );
2887  updateFields();
2888  return true;
2889  }
2890  else
2891  {
2892  return false;
2893  }
2894  }
2895 
2897  case QgsFields::OriginEdit:
2898 
2899  if ( !mEditBuffer || !mDataProvider )
2900  return false;
2901 
2902  return mEditBuffer->renameAttribute( index, newName );
2903 
2904  case QgsFields::OriginJoin:
2906  return false;
2907 
2908  }
2909 
2910  return false; // avoid warning
2911 }
2912 
2913 void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
2914 {
2915  if ( attIndex < 0 || attIndex >= fields().count() )
2916  return;
2917 
2918  QString name = fields().at( attIndex ).name();
2919 
2920  mAttributeAliasMap.insert( name, aliasString );
2921  mFields[ attIndex ].setAlias( aliasString );
2922  mEditFormConfig.setFields( mFields );
2923  emit layerModified(); // TODO[MD]: should have a different signal?
2924 }
2925 
2926 QString QgsVectorLayer::attributeAlias( int index ) const
2927 {
2928  if ( index < 0 || index >= fields().count() )
2929  return QString();
2930 
2931  return fields().at( index ).alias();
2932 }
2933 
2934 QString QgsVectorLayer::attributeDisplayName( int index ) const
2935 {
2936  if ( index >= 0 && index < mFields.count() )
2937  return mFields.at( index ).displayName();
2938  else
2939  return QString();
2940 }
2941 
2943 {
2944  return mAttributeAliasMap;
2945 }
2946 
2948 {
2949  if ( index < 0 || index >= fields().count() )
2950  return false;
2951 
2952  if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2953  {
2954  removeExpressionField( index );
2955  return true;
2956  }
2957 
2958  if ( !mEditBuffer || !mDataProvider )
2959  return false;
2960 
2961  return mEditBuffer->deleteAttribute( index );
2962 }
2963 
2964 bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
2965 {
2966  bool deleted = false;
2967 
2968  // Remove multiple occurrences of same attribute
2969  QList<int> attrList = attrs.toSet().toList();
2970 
2971  std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
2972 
2973  for ( int attr : qgis::as_const( attrList ) )
2974  {
2975  if ( deleteAttribute( attr ) )
2976  {
2977  deleted = true;
2978  }
2979  }
2980 
2981  return deleted;
2982 }
2983 
2985 {
2986  if ( !mEditBuffer )
2987  return false;
2988 
2989  if ( mJoinBuffer->containsJoins() )
2990  mJoinBuffer->deleteFeature( fid );
2991 
2992  bool res = mEditBuffer->deleteFeature( fid );
2993  if ( res )
2994  {
2995  mSelectedFeatureIds.remove( fid ); // remove it from selection
2996  updateExtents();
2997  }
2998 
2999  return res;
3000 }
3001 
3003 {
3004  if ( !mEditBuffer )
3005  {
3006  QgsDebugMsgLevel( QStringLiteral( "Cannot delete features (mEditBuffer==NULL)" ), 1 );
3007  return false;
3008  }
3009 
3010  if ( mJoinBuffer->containsJoins() )
3011  mJoinBuffer->deleteFeatures( fids );
3012 
3013  bool res = mEditBuffer->deleteFeatures( fids );
3014 
3015  if ( res )
3016  {
3017  mSelectedFeatureIds.subtract( fids ); // remove it from selection
3018  updateExtents();
3019  }
3020 
3021  return res;
3022 }
3023 
3025 {
3026  return mFields;
3027 }
3028 
3030 {
3031  QgsAttributeList pkAttributesList;
3032 
3033  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
3034  for ( int i = 0; i < mFields.count(); ++i )
3035  {
3036  if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
3037  providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
3038  pkAttributesList << i;
3039  }
3040 
3041  return pkAttributesList;
3042 }
3043 
3045 {
3046  if ( ! mDataProvider )
3047  return -1;
3048  return mDataProvider->featureCount() +
3049  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
3050 }
3051 
3053 {
3054  const QgsFeatureIds deletedFeatures( mEditBuffer ? mEditBuffer->deletedFeatureIds() : QgsFeatureIds() );
3055  const QgsFeatureMap addedFeatures( mEditBuffer ? mEditBuffer->addedFeatures() : QgsFeatureMap() );
3056 
3057  if ( mEditBuffer && !deletedFeatures.empty() )
3058  {
3059  if ( addedFeatures.size() > deletedFeatures.size() )
3060  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3061  else
3062  return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
3063  }
3064 
3065  if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider->empty() )
3066  return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
3067  else
3068  return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3069 }
3070 
3072 {
3073  mCommitErrors.clear();
3074 
3075  if ( !mDataProvider )
3076  {
3077  mCommitErrors << tr( "ERROR: no provider" );
3078  return false;
3079  }
3080 
3081  if ( !mEditBuffer )
3082  {
3083  mCommitErrors << tr( "ERROR: layer not editable" );
3084  return false;
3085  }
3086 
3087  emit beforeCommitChanges();
3088 
3089  if ( !mAllowCommit )
3090  return false;
3091 
3092  bool success = mEditBuffer->commitChanges( mCommitErrors );
3093 
3094  if ( success )
3095  {
3096  delete mEditBuffer;
3097  mEditBuffer = nullptr;
3098  undoStack()->clear();
3099  emit editingStopped();
3100  }
3101  else
3102  {
3103  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QStringLiteral( "\n " ) ) ) );
3104  }
3105 
3106  updateFields();
3107  mDataProvider->updateExtents();
3108 
3109  mDataProvider->leaveUpdateMode();
3110 
3111  triggerRepaint();
3112 
3113  return success;
3114 }
3115 
3116 QStringList QgsVectorLayer::commitErrors() const
3117 {
3118  return mCommitErrors;
3119 }
3120 
3121 bool QgsVectorLayer::rollBack( bool deleteBuffer )
3122 {
3123  if ( !mEditBuffer )
3124  {
3125  return false;
3126  }
3127 
3128  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
3129  !mEditBuffer->mAddedFeatures.isEmpty() ||
3130  !mEditBuffer->mChangedGeometries.isEmpty();
3131 
3132  emit beforeRollBack();
3133 
3134  mEditBuffer->rollBack();
3135 
3136  emit afterRollBack();
3137 
3138  if ( isModified() )
3139  {
3140  // new undo stack roll back method
3141  // old method of calling every undo could cause many canvas refreshes
3142  undoStack()->setIndex( 0 );
3143  }
3144 
3145  updateFields();
3146 
3147  if ( deleteBuffer )
3148  {
3149  delete mEditBuffer;
3150  mEditBuffer = nullptr;
3151  undoStack()->clear();
3152  }
3153  emit editingStopped();
3154 
3155  if ( rollbackExtent )
3156  updateExtents();
3157 
3158  mDataProvider->leaveUpdateMode();
3159 
3160  triggerRepaint();
3161  return true;
3162 }
3163 
3165 {
3166  return mSelectedFeatureIds.size();
3167 }
3168 
3170 {
3171  return mSelectedFeatureIds;
3172 }
3173 
3175 {
3176  QgsFeatureList features;
3177  features.reserve( mSelectedFeatureIds.count() );
3178  QgsFeature f;
3179 
3180  if ( mSelectedFeatureIds.count() <= 8 )
3181  {
3182  // for small amount of selected features, fetch them directly
3183  // because request with FilterFids would go iterate over the whole layer
3184  const auto constMSelectedFeatureIds = mSelectedFeatureIds;
3185  for ( QgsFeatureId fid : constMSelectedFeatureIds )
3186  {
3187  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
3188  features << f;
3189  }
3190  }
3191  else
3192  {
3194 
3195  while ( it.nextFeature( f ) )
3196  {
3197  features.push_back( f );
3198  }
3199  }
3200 
3201  return features;
3202 }
3203 
3205 {
3206  if ( mSelectedFeatureIds.isEmpty() )
3207  return QgsFeatureIterator();
3208 
3211 
3212  if ( mSelectedFeatureIds.count() == 1 )
3213  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
3214  else
3215  request.setFilterFids( mSelectedFeatureIds );
3216 
3217  return getFeatures( request );
3218 }
3219 
3221 {
3222  if ( !mEditBuffer || !mDataProvider )
3223  return false;
3224 
3225  if ( mGeometryOptions->isActive() )
3226  {
3227  for ( auto feature = features.begin(); feature != features.end(); ++feature )
3228  {
3229  QgsGeometry geom = feature->geometry();
3230  mGeometryOptions->apply( geom );
3231  feature->setGeometry( geom );
3232  }
3233  }
3234 
3235  bool res = mEditBuffer->addFeatures( features );
3236  updateExtents();
3237 
3238  if ( res && mJoinBuffer->containsJoins() )
3239  res = mJoinBuffer->addFeatures( features );
3240 
3241  return res;
3242 }
3243 
3245 {
3246  // if layer is not spatial, it has not CRS!
3247  setCrs( isSpatial() ? mDataProvider->crs() : QgsCoordinateReferenceSystem() );
3248 }
3249 
3251 {
3253  if ( exp.isField() )
3254  {
3255  return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
3256  }
3257 
3258  return QString();
3259 }
3260 
3262 {
3263  if ( mDisplayExpression == displayExpression )
3264  return;
3265 
3266  mDisplayExpression = displayExpression;
3267  emit displayExpressionChanged();
3268 }
3269 
3270 QString QgsVectorLayer::displayExpression() const
3271 {
3272  if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
3273  {
3274  return mDisplayExpression;
3275  }
3276  else
3277  {
3278  QString idxName;
3279 
3280  // Check the fields and keep the first one that matches.
3281  // We assume that the user has organized the data with the
3282  // more "interesting" field names first. As such, name should
3283  // be selected before oldname, othername, etc.
3284  // This candidates list is a prioritized list of candidates ranked by "interestingness"!
3285  // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
3286  // but adding hardcoded localized variants of the strings is encouraged.
3287  static QStringList sCandidates{ QStringLiteral( "name" ),
3288  QStringLiteral( "title" ),
3289  QStringLiteral( "heibt" ),
3290  QStringLiteral( "desc" ),
3291  QStringLiteral( "nom" ),
3292  QStringLiteral( "street" ),
3293  QStringLiteral( "road" ),
3294  QStringLiteral( "id" )};
3295  for ( const QString &candidate : sCandidates )
3296  {
3297  for ( const QgsField &field : mFields )
3298  {
3299  QString fldName = field.name();
3300  if ( fldName.indexOf( candidate, 0, Qt::CaseInsensitive ) > -1 )
3301  {
3302  idxName = fldName;
3303  break;
3304  }
3305  }
3306 
3307  if ( !idxName.isEmpty() )
3308  break;
3309  }
3310 
3311  if ( !idxName.isNull() )
3312  {
3313  return QgsExpression::quotedColumnRef( idxName );
3314  }
3315  else
3316  {
3317  return QgsExpression::quotedColumnRef( mFields.at( 0 ).name() );
3318  }
3319  }
3320 }
3321 
3323 {
3324  return ( mEditBuffer && mDataProvider );
3325 }
3326 
3328 {
3331 }
3332 
3333 bool QgsVectorLayer::isReadOnly() const
3334 {
3335  return mReadOnly;
3336 }
3337 
3338 bool QgsVectorLayer::setReadOnly( bool readonly )
3339 {
3340  // exit if the layer is in editing mode
3341  if ( readonly && mEditBuffer )
3342  return false;
3343 
3344  mReadOnly = readonly;
3345  emit readOnlyChanged();
3346  return true;
3347 }
3348 
3350 {
3351  emit beforeModifiedCheck();
3352  return mEditBuffer && mEditBuffer->isModified();
3353 }
3354 
3355 bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
3356 {
3357  bool auxiliaryField = false;
3358  srcIndex = -1;
3359 
3360  if ( !auxiliaryLayer() )
3361  return auxiliaryField;
3362 
3363  if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
3364  {
3365  const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
3366 
3367  if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
3368  auxiliaryField = true;
3369  }
3370 
3371  return auxiliaryField;
3372 }
3373 
3375 {
3376  // we must allow setting a renderer if our geometry type is unknown
3377  // as this allows the renderer to be correctly set even for layers
3378  // with broken sources
3379  if ( !isSpatial() && mWkbType != QgsWkbTypes::Unknown )
3380  return;
3381 
3382  if ( r != mRenderer )
3383  {
3384  delete mRenderer;
3385  mRenderer = r;
3386  mSymbolFeatureCounted = false;
3387  mSymbolFeatureCountMap.clear();
3388  mSymbolFeatureIdMap.clear();
3389 
3390  emit rendererChanged();
3391  emit styleChanged();
3392  }
3393 }
3394 
3395 void QgsVectorLayer::beginEditCommand( const QString &text )
3396 {
3397  if ( !mDataProvider )
3398  {
3399  return;
3400  }
3401  if ( mDataProvider->transaction() )
3402  {
3403  QString ignoredError;
3404  mDataProvider->transaction()->createSavepoint( ignoredError );
3405  }
3406  undoStack()->beginMacro( text );
3407  mEditCommandActive = true;
3408  emit editCommandStarted( text );
3409 }
3410 
3412 {
3413  if ( !mDataProvider )
3414  {
3415  return;
3416  }
3417  undoStack()->endMacro();
3418  mEditCommandActive = false;
3419  if ( !mDeletedFids.isEmpty() )
3420  {
3421  emit featuresDeleted( mDeletedFids );
3422  mDeletedFids.clear();
3423  }
3424  emit editCommandEnded();
3425 }
3426 
3428 {
3429  if ( !mDataProvider )
3430  {
3431  return;
3432  }
3433  undoStack()->endMacro();
3434  undoStack()->undo();
3435 
3436  // it's not directly possible to pop the last command off the stack (the destroyed one)
3437  // and delete, so we add a dummy obsolete command to force this to occur.
3438  // Pushing the new command deletes the destroyed one, and since the new
3439  // command is obsolete it's automatically deleted by the undo stack.
3440  std::unique_ptr< QUndoCommand > command = qgis::make_unique< QUndoCommand >();
3441  command->setObsolete( true );
3442  undoStack()->push( command.release() );
3443 
3444  mEditCommandActive = false;
3445  mDeletedFids.clear();
3446  emit editCommandDestroyed();
3447 }
3448 
3450 {
3451  return mJoinBuffer->addJoin( joinInfo );
3452 }
3453 
3454 
3455 bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
3456 {
3457  return mJoinBuffer->removeJoin( joinLayerId );
3458 }
3459 
3460 const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
3461 {
3462  return mJoinBuffer->vectorJoins();
3463 }
3464 
3465 int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
3466 {
3467  emit beforeAddingExpressionField( fld.name() );
3468  mExpressionFieldBuffer->addExpression( exp, fld );
3469  updateFields();
3470  int idx = mFields.indexFromName( fld.name() );
3471  emit attributeAdded( idx );
3472  return idx;
3473 }
3474 
3476 {
3477  emit beforeRemovingExpressionField( index );
3478  int oi = mFields.fieldOriginIndex( index );
3479  mExpressionFieldBuffer->removeExpression( oi );
3480  updateFields();
3481  emit attributeDeleted( index );
3482 }
3483 
3484 QString QgsVectorLayer::expressionField( int index ) const
3485 {
3486  int oi = mFields.fieldOriginIndex( index );
3487  if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
3488  return QString();
3489 
3490  return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
3491 }
3492 
3493 void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
3494 {
3495  int oi = mFields.fieldOriginIndex( index );
3496  mExpressionFieldBuffer->updateExpression( oi, exp );
3497 }
3498 
3500 {
3501  if ( !mDataProvider )
3502  return;
3503 
3504  QgsFields oldFields = mFields;
3505 
3506  mFields = mDataProvider->fields();
3507 
3508  // added / removed fields
3509  if ( mEditBuffer )
3510  mEditBuffer->updateFields( mFields );
3511 
3512  // joined fields
3513  if ( mJoinBuffer->containsJoins() )
3514  mJoinBuffer->updateFields( mFields );
3515 
3516  if ( mExpressionFieldBuffer )
3517  mExpressionFieldBuffer->updateFields( mFields );
3518 
3519  // set aliases and default values
3520  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
3521  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
3522  {
3523  int index = mFields.lookupField( aliasIt.key() );
3524  if ( index < 0 )
3525  continue;
3526 
3527  mFields[ index ].setAlias( aliasIt.value() );
3528  }
3529 
3530  // Update default values
3531  mDefaultValueOnUpdateFields.clear();
3532  QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
3533  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
3534  {
3535  int index = mFields.lookupField( defaultIt.key() );
3536  if ( index < 0 )
3537  continue;
3538 
3539  mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
3540  if ( defaultIt.value().applyOnUpdate() )
3541  mDefaultValueOnUpdateFields.insert( index );
3542  }
3543 
3544  QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
3545  for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
3546  {
3547  int index = mFields.lookupField( constraintIt.key() );
3548  if ( index < 0 )
3549  continue;
3550 
3551  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3552 
3553  // always keep provider constraints intact
3554  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
3556  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
3558  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
3560  mFields[ index ].setConstraints( constraints );
3561  }
3562 
3563  QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
3564  for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
3565  {
3566  int index = mFields.lookupField( constraintExpIt.key() );
3567  if ( index < 0 )
3568  continue;
3569 
3570  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3571 
3572  // always keep provider constraints intact
3574  continue;
3575 
3576  constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
3577  mFields[ index ].setConstraints( constraints );
3578  }
3579 
3580  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
3581  for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
3582  {
3583  int index = mFields.lookupField( constraintStrengthIt.key().first );
3584  if ( index < 0 )
3585  continue;
3586 
3587  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3588 
3589  // always keep provider constraints intact
3591  continue;
3592 
3593  constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
3594  mFields[ index ].setConstraints( constraints );
3595  }
3596 
3597  auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
3598  for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
3599  {
3600  int index = mFields.indexOf( fieldWidgetIterator.key() );
3601  if ( index < 0 )
3602  continue;
3603 
3604  mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
3605  }
3606 
3607  if ( oldFields != mFields )
3608  {
3609  emit updatedFields();
3610  mEditFormConfig.setFields( mFields );
3611  }
3612 }
3613 
3614 
3615 QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
3616 {
3617  if ( index < 0 || index >= mFields.count() )
3618  return QVariant();
3619 
3620  QString expression = mFields.at( index ).defaultValueDefinition().expression();
3621  if ( expression.isEmpty() )
3622  return mDataProvider->defaultValue( index );
3623 
3624  QgsExpressionContext *evalContext = context;
3625  std::unique_ptr< QgsExpressionContext > tempContext;
3626  if ( !evalContext )
3627  {
3628  // no context passed, so we create a default one
3630  evalContext = tempContext.get();
3631  }
3632 
3633  if ( feature.isValid() )
3634  {
3636  featScope->setFeature( feature );
3637  featScope->setFields( feature.fields() );
3638  evalContext->appendScope( featScope );
3639  }
3640 
3641  QVariant val;
3642  QgsExpression exp( expression );
3643  exp.prepare( evalContext );
3644  if ( exp.hasEvalError() )
3645  {
3646  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
3647  }
3648  else
3649  {
3650  val = exp.evaluate( evalContext );
3651  }
3652 
3653  if ( feature.isValid() )
3654  {
3655  delete evalContext->popScope();
3656  }
3657 
3658  return val;
3659 }
3660 
3662 {
3663  if ( index < 0 || index >= mFields.count() )
3664  return;
3665 
3666  if ( definition.isValid() )
3667  {
3668  mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
3669  }
3670  else
3671  {
3672  mDefaultExpressionMap.remove( mFields.at( index ).name() );
3673  }
3674  updateFields();
3675 }
3676 
3678 {
3679  if ( index < 0 || index >= mFields.count() )
3680  return QgsDefaultValue();
3681  else
3682  return mFields.at( index ).defaultValueDefinition();
3683 }
3684 
3685 QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
3686 {
3687  QSet<QVariant> uniqueValues;
3688  if ( !mDataProvider )
3689  {
3690  return uniqueValues;
3691  }
3692 
3693  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3694  switch ( origin )
3695  {
3697  return uniqueValues;
3698 
3699  case QgsFields::OriginProvider: //a provider field
3700  {
3701  uniqueValues = mDataProvider->uniqueValues( index, limit );
3702 
3703  if ( mEditBuffer )
3704  {
3705  QSet<QString> vals;
3706  const auto constUniqueValues = uniqueValues;
3707  for ( const QVariant &v : constUniqueValues )
3708  {
3709  vals << v.toString();
3710  }
3711 
3712  QgsFeatureMap added = mEditBuffer->addedFeatures();
3713  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3714  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3715  {
3716  addedIt.next();
3717  QVariant v = addedIt.value().attribute( index );
3718  if ( v.isValid() )
3719  {
3720  QString vs = v.toString();
3721  if ( !vals.contains( vs ) )
3722  {
3723  vals << vs;
3724  uniqueValues << v;
3725  }
3726  }
3727  }
3728 
3729  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3730  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3731  {
3732  it.next();
3733  QVariant v = it.value().value( index );
3734  if ( v.isValid() )
3735  {
3736  QString vs = v.toString();
3737  if ( !vals.contains( vs ) )
3738  {
3739  vals << vs;
3740  uniqueValues << v;
3741  }
3742  }
3743  }
3744  }
3745 
3746  return uniqueValues;
3747  }
3748 
3749  case QgsFields::OriginEdit:
3750  // the layer is editable, but in certain cases it can still be avoided going through all features
3751  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3752  mEditBuffer->mAddedFeatures.isEmpty() &&
3753  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3754  mEditBuffer->mChangedAttributeValues.isEmpty() )
3755  {
3756  uniqueValues = mDataProvider->uniqueValues( index, limit );
3757  return uniqueValues;
3758  }
3759  FALLTHROUGH
3760  //we need to go through each feature
3761  case QgsFields::OriginJoin:
3763  {
3764  QgsAttributeList attList;
3765  attList << index;
3766 
3769  .setSubsetOfAttributes( attList ) );
3770 
3771  QgsFeature f;
3772  QVariant currentValue;
3773  QHash<QString, QVariant> val;
3774  while ( fit.nextFeature( f ) )
3775  {
3776  currentValue = f.attribute( index );
3777  val.insert( currentValue.toString(), currentValue );
3778  if ( limit >= 0 && val.size() >= limit )
3779  {
3780  break;
3781  }
3782  }
3783 
3784  return val.values().toSet();
3785  }
3786  }
3787 
3788  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3789  return uniqueValues;
3790 }
3791 
3792 QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
3793 {
3794  QStringList results;
3795  if ( !mDataProvider )
3796  {
3797  return results;
3798  }
3799 
3800  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3801  switch ( origin )
3802  {
3804  return results;
3805 
3806  case QgsFields::OriginProvider: //a provider field
3807  {
3808  results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3809 
3810  if ( mEditBuffer )
3811  {
3812  QgsFeatureMap added = mEditBuffer->addedFeatures();
3813  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3814  while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3815  {
3816  addedIt.next();
3817  QVariant v = addedIt.value().attribute( index );
3818  if ( v.isValid() )
3819  {
3820  QString vs = v.toString();
3821  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3822  {
3823  results << vs;
3824  }
3825  }
3826  }
3827 
3828  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3829  while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3830  {
3831  it.next();
3832  QVariant v = it.value().value( index );
3833  if ( v.isValid() )
3834  {
3835  QString vs = v.toString();
3836  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3837  {
3838  results << vs;
3839  }
3840  }
3841  }
3842  }
3843 
3844  return results;
3845  }
3846 
3847  case QgsFields::OriginEdit:
3848  // the layer is editable, but in certain cases it can still be avoided going through all features
3849  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3850  mEditBuffer->mAddedFeatures.isEmpty() &&
3851  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3852  mEditBuffer->mChangedAttributeValues.isEmpty() )
3853  {
3854  return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3855  }
3856  FALLTHROUGH
3857  //we need to go through each feature
3858  case QgsFields::OriginJoin:
3860  {
3861  QgsAttributeList attList;
3862  attList << index;
3863 
3864  QgsFeatureRequest request;
3865  request.setSubsetOfAttributes( attList );
3867  QString fieldName = mFields.at( index ).name();
3868  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
3869  QgsFeatureIterator fit = getFeatures( request );
3870 
3871  QgsFeature f;
3872  QString currentValue;
3873  while ( fit.nextFeature( f ) )
3874  {
3875  currentValue = f.attribute( index ).toString();
3876  if ( !results.contains( currentValue ) )
3877  results << currentValue;
3878 
3879  if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
3880  {
3881  break;
3882  }
3883  }
3884 
3885  return results;
3886  }
3887  }
3888 
3889  Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
3890  return results;
3891 }
3892 
3893 QVariant QgsVectorLayer::minimumValue( int index ) const
3894 {
3895  return minimumOrMaximumValue( index, true );
3896 }
3897 
3898 QVariant QgsVectorLayer::maximumValue( int index ) const
3899 {
3900  return minimumOrMaximumValue( index, false );
3901 }
3902 
3903 QVariant QgsVectorLayer::minimumOrMaximumValue( int index, bool minimum ) const
3904 {
3905  if ( !mDataProvider )
3906  {
3907  return QVariant();
3908  }
3909 
3910  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3911 
3912  switch ( origin )
3913  {
3915  return QVariant();
3916 
3917  case QgsFields::OriginProvider: //a provider field
3918  {
3919  QVariant val = minimum ? mDataProvider->minimumValue( index ) : mDataProvider->maximumValue( index );
3920  if ( mEditBuffer )
3921  {
3922  QgsFeatureMap added = mEditBuffer->addedFeatures();
3923  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3924  while ( addedIt.hasNext() )
3925  {
3926  addedIt.next();
3927  QVariant v = addedIt.value().attribute( index );
3928  if ( ( v.isValid() && minimum && qgsVariantLessThan( v, val ) )
3929  || ( v.isValid() && !minimum && qgsVariantGreaterThan( v, val ) ) )
3930  {
3931  val = v;
3932  }
3933  }
3934 
3935  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3936  while ( it.hasNext() )
3937  {
3938  it.next();
3939  QVariant v = it.value().value( index );
3940  if ( ( v.isValid() && minimum && qgsVariantLessThan( v, val ) )
3941  || ( v.isValid() && !minimum && qgsVariantGreaterThan( v, val ) ) )
3942  {
3943  val = v;
3944  }
3945  }
3946  }
3947  return val;
3948  }
3949 
3950  case QgsFields::OriginEdit:
3951  {
3952  // the layer is editable, but in certain cases it can still be avoided going through all features
3953  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3954  mEditBuffer->mAddedFeatures.isEmpty() &&
3955  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3956  mEditBuffer->mChangedAttributeValues.isEmpty() )
3957  {
3958  return minimum ? mDataProvider->minimumValue( index ) : mDataProvider->maximumValue( index );
3959  }
3960  }
3961  FALLTHROUGH
3962  // no choice but to go through all features
3964  case QgsFields::OriginJoin:
3965  {
3966  // we need to go through each feature
3967  QgsAttributeList attList;
3968  attList << index;
3969 
3972  .setSubsetOfAttributes( attList ) );
3973 
3974  QgsFeature f;
3975  double value = minimum ? std::numeric_limits<double>::max() : -std::numeric_limits<double>::max();
3976  double currentValue = 0;
3977  while ( fit.nextFeature( f ) )
3978  {
3979  currentValue = f.attribute( index ).toDouble();
3980  if ( ( minimum && currentValue < value ) || ( !minimum && currentValue > value ) )
3981  {
3982  value = currentValue;
3983  }
3984  }
3985  return QVariant( value );
3986  }
3987  }
3988 
3989  Q_ASSERT_X( false, "QgsVectorLayer::minOrMax()", "Unknown source of the field!" );
3990  return QVariant();
3991 }
3992 
3993 QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
3995  bool *ok, QgsFeatureIds *fids ) const
3996 {
3997  if ( ok )
3998  *ok = false;
3999 
4000  if ( !mDataProvider )
4001  {
4002  return QVariant();
4003  }
4004 
4005  // test if we are calculating based on a field
4006  int attrIndex = mFields.lookupField( fieldOrExpression );
4007  if ( attrIndex >= 0 )
4008  {
4009  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
4010  // to the provider itself
4011  QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
4012  if ( origin == QgsFields::OriginProvider )
4013  {
4014  bool providerOk = false;
4015  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk, fids );
4016  if ( providerOk )
4017  {
4018  // provider handled calculation
4019  if ( ok )
4020  *ok = true;
4021  return val;
4022  }
4023  }
4024  }
4025 
4026  // fallback to using aggregate calculator to determine aggregate
4027  QgsAggregateCalculator c( this );
4028  if ( fids )
4029  c.setFidsFilter( *fids );
4030  c.setParameters( parameters );
4031  return c.calculate( aggregate, fieldOrExpression, context, ok );
4032 }
4033 
4035 {
4036  if ( mFeatureBlendMode == featureBlendMode )
4037  return;
4038 
4039  mFeatureBlendMode = featureBlendMode;
4040  emit featureBlendModeChanged( featureBlendMode );
4041  emit styleChanged();
4042 }
4043 
4044 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
4045 {
4046  return mFeatureBlendMode;
4047 }
4048 
4050 {
4051  if ( qgsDoubleNear( mLayerOpacity, opacity ) )
4052  return;
4053  mLayerOpacity = opacity;
4054  emit opacityChanged( opacity );
4055  emit styleChanged();
4056 }
4057 
4058 double QgsVectorLayer::opacity() const
4059 {
4060  return mLayerOpacity;
4061 }
4062 
4063 
4064 
4065 void QgsVectorLayer::readSldLabeling( const QDomNode &node )
4066 {
4067  setLabeling( nullptr ); // start with no labeling
4068  setLabelsEnabled( false );
4069 
4070  QDomElement element = node.toElement();
4071  if ( element.isNull() )
4072  return;
4073 
4074  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
4075  if ( userStyleElem.isNull() )
4076  {
4077  QgsDebugMsgLevel( QStringLiteral( "Info: UserStyle element not found." ), 4 );
4078  return;
4079  }
4080 
4081  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
4082  if ( featureTypeStyleElem.isNull() )
4083  {
4084  QgsDebugMsgLevel( QStringLiteral( "Info: FeatureTypeStyle element not found." ), 4 );
4085  return;
4086  }
4087 
4088  // use last rule
4089  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( QStringLiteral( "Rule" ) );
4090  if ( ruleElem.isNull() )
4091  {
4092  QgsDebugMsgLevel( QStringLiteral( "Info: Rule element not found." ), 4 );
4093  return;
4094  }
4095 
4096  // use last text symbolizer
4097  QDomElement textSymbolizerElem = ruleElem.lastChildElement( QStringLiteral( "TextSymbolizer" ) );
4098  if ( textSymbolizerElem.isNull() )
4099  {
4100  QgsDebugMsgLevel( QStringLiteral( "Info: TextSymbolizer element not found." ), 4 );
4101  return;
4102  }
4103 
4104  QgsPalLayerSettings settings;
4105 
4106  // Label
4107  QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
4108  if ( !labelElem.isNull() )
4109  {
4110  QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
4111  if ( !propertyNameElem.isNull() )
4112  {
4113  // set labeling defaults
4114 
4115  // label attribute
4116  QString labelAttribute = propertyNameElem.text();
4117  settings.fieldName = labelAttribute;
4118  settings.isExpression = false;
4119 
4120  int fieldIndex = mFields.lookupField( labelAttribute );
4121  if ( fieldIndex == -1 )
4122  {
4123  // label attribute is not in columns, check if it is an expression
4124  QgsExpression exp( labelAttribute );
4125  if ( !exp.hasEvalError() )
4126  {
4127  settings.isExpression = true;
4128  }
4129  else
4130  {
4131  QgsDebugMsgLevel( QStringLiteral( "SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
4132  }
4133  }
4134  }
4135  else
4136  {
4137  QgsDebugMsgLevel( QStringLiteral( "Info: PropertyName element not found." ), 4 );
4138  return;
4139  }
4140  }
4141  else
4142  {
4143  QgsDebugMsgLevel( QStringLiteral( "Info: Label element not found." ), 4 );
4144  return;
4145  }
4146 
4147  QString fontFamily = QStringLiteral( "Sans-Serif" );
4148  int fontPointSize = 10;
4149  int fontWeight = -1;
4150  bool fontItalic = false;
4151  bool fontUnderline = false;
4152 
4153  // Font
4154  QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
4155  if ( !fontElem.isNull() )
4156  {
4157  QString cssName;
4158  QString elemText;
4159  QDomElement cssElem = fontElem.firstChildElement( QStringLiteral( "CssParameter" ) );
4160  while ( !cssElem.isNull() )
4161  {
4162  cssName = cssElem.attribute( QStringLiteral( "name" ), QStringLiteral( "not_found" ) );
4163  if ( cssName != QLatin1String( "not_found" ) )
4164  {
4165  elemText = cssElem.text();
4166  if ( cssName == QLatin1String( "font-family" ) )
4167  {
4168  fontFamily = elemText;
4169  }
4170  else if ( cssName == QLatin1String( "font-style" ) )
4171  {
4172  fontItalic = ( elemText == QLatin1String( "italic" ) ) || ( elemText == QLatin1String( "Italic" ) );
4173  }
4174  else if ( cssName == QLatin1String( "font-size" ) )
4175  {
4176  bool ok;
4177  int fontSize = elemText.toInt( &ok );
4178  if ( ok )
4179  {
4180  fontPointSize = fontSize;
4181  }
4182  }
4183  else if ( cssName == QLatin1String( "font-weight" ) )
4184  {
4185  if ( ( elemText == QLatin1String( "bold" ) ) || ( elemText == QLatin1String( "Bold" ) ) )
4186  fontWeight = QFont::Bold;
4187  }
4188  else if ( cssName == QLatin1String( "font-underline" ) )
4189  {
4190  fontUnderline = ( elemText == QLatin1String( "underline" ) ) || ( elemText == QLatin1String( "Underline" ) );
4191  }
4192  }
4193 
4194  cssElem = cssElem.nextSiblingElement( QStringLiteral( "CssParameter" ) );
4195  }
4196  }
4197 
4198  QgsTextFormat format;
4199  QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
4200  font.setUnderline( fontUnderline );
4201  format.setFont( font );
4202  format.setSize( fontPointSize );
4203 
4204  // Fill
4205  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) ) );
4206  if ( textColor.isValid() )
4207  {
4208  format.setColor( textColor );
4209  }
4210 
4211  QgsTextBufferSettings bufferSettings;
4212 
4213  // Halo
4214  QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
4215  if ( !haloElem.isNull() )
4216  {
4217  bufferSettings.setEnabled( true );
4218  bufferSettings.setSize( 1 );
4219 
4220  QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
4221  if ( !radiusElem.isNull() )
4222  {
4223  bool ok;
4224  double bufferSize = radiusElem.text().toDouble( &ok );
4225  if ( ok )
4226  {
4227  bufferSettings.setSize( bufferSize );
4228  }
4229  }
4230 
4231  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( QStringLiteral( "Fill" ) ) );
4232  if ( bufferColor.isValid() )
4233  {
4234  bufferSettings.setColor( bufferColor );
4235  }
4236  }
4237 
4238  // LabelPlacement
4239  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
4240  if ( !labelPlacementElem.isNull() )
4241  {
4242  // PointPlacement
4243  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
4244  if ( !pointPlacementElem.isNull() )
4245  {
4247 
4248  QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
4249  if ( !displacementElem.isNull() )
4250  {
4251  QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
4252  if ( !displacementXElem.isNull() )
4253  {
4254  bool ok;
4255  double xOffset = displacementXElem.text().toDouble( &ok );
4256  if ( ok )
4257  {
4258  settings.xOffset = xOffset;
4259  }
4260  }
4261  QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
4262  if ( !displacementYElem.isNull() )
4263  {
4264  bool ok;
4265  double yOffset = displacementYElem.text().toDouble( &ok );
4266  if ( ok )
4267  {
4268  settings.yOffset = yOffset;
4269  }
4270  }
4271  }
4272 
4273  QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
4274  if ( !rotationElem.isNull() )
4275  {
4276  bool ok;
4277  double rotation = rotationElem.text().toDouble( &ok );
4278  if ( ok )
4279  {
4280  settings.angleOffset = 360 - rotation;
4281  }
4282  }
4283  }
4284  }
4285 
4286  format.setBuffer( bufferSettings );
4287  settings.setFormat( format );
4288  setLabeling( new QgsVectorLayerSimpleLabeling( settings ) );
4289  setLabelsEnabled( true );
4290 }
4291 
4293 {
4294  return mEditFormConfig;
4295 }
4296 
4298 {
4299  if ( mEditFormConfig == editFormConfig )
4300  return;
4301 
4302  mEditFormConfig = editFormConfig;
4303  mEditFormConfig.onRelationsLoaded();
4304  emit editFormConfigChanged();
4305 }
4306 
4307 QString QgsVectorLayer::mapTipTemplate() const
4308 {
4309  return mMapTipTemplate;
4310 }
4311 
4312 void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
4313 {
4314  if ( mMapTipTemplate == mapTip )
4315  return;
4316 
4317  mMapTipTemplate = mapTip;
4318  emit mapTipTemplateChanged();
4319 }
4320 
4322 {
4323  QgsAttributeTableConfig config = mAttributeTableConfig;
4324 
4325  if ( config.isEmpty() )
4326  config.update( fields() );
4327 
4328  return config;
4329 }
4330 
4332 {
4333  if ( mAttributeTableConfig != attributeTableConfig )
4334  {
4335  mAttributeTableConfig = attributeTableConfig;
4336  emit configChanged();
4337  }
4338 }
4339 
4341 {
4343 }
4344 
4346 {
4348 }
4349 
4351 {
4352  if ( !mDiagramLayerSettings )
4353  mDiagramLayerSettings = new QgsDiagramLayerSettings();
4354  *mDiagramLayerSettings = s;
4355 }
4356 
4358 {
4359  QgsLayerMetadataFormatter htmlFormatter( metadata() );
4360  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
4361 
4362  // Begin Provider section
4363  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
4364  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
4365 
4366  // name
4367  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
4368 
4369  // local path
4370  QVariantMap uriComponents = QgsProviderRegistry::instance()->decodeUri( mProviderKey, publicSource() );
4371  QString path;
4372  if ( uriComponents.contains( QStringLiteral( "path" ) ) )
4373  {
4374  path = uriComponents[QStringLiteral( "path" )].toString();
4375  if ( QFile::exists( path ) )
4376  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" );
4377  }
4378  if ( uriComponents.contains( QStringLiteral( "url" ) ) )
4379  {
4380  const QString url = uriComponents[QStringLiteral( "url" )].toString();
4381  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" );
4382  }
4383 
4384  // data source
4385  if ( publicSource() != path )
4386  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>%1" ).arg( publicSource() ) + QStringLiteral( "</td></tr>\n" );
4387 
4388  // storage type
4389  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
4390 
4391  // comment
4392  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
4393 
4394  // encoding
4395  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + dataProvider()->encoding() + QStringLiteral( "</td></tr>\n" );
4396 
4397  if ( isSpatial() )
4398  {
4399  // geom type
4401  if ( type < 0 || type > QgsWkbTypes::NullGeometry )
4402  {
4403  QgsDebugMsgLevel( QStringLiteral( "Invalid vector type" ), 2 );
4404  }
4405  else
4406  {
4407  QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
4409  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
4410  }
4411 
4412  // EPSG
4413  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" );
4414  if ( crs().isValid() )
4415  {
4416  myMetadata += crs().authid() + QStringLiteral( " - " );
4417  myMetadata += crs().description() + QStringLiteral( " - " );
4418  if ( crs().isGeographic() )
4419  myMetadata += tr( "Geographic" );
4420  else
4421  myMetadata += tr( "Projected" );
4422  }
4423  myMetadata += QLatin1String( "</td></tr>\n" );
4424 
4425  // Extent
4426  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
4427 
4428  // unit
4429  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
4430 
4431  }
4432 
4433  // feature count
4434  QLocale locale = QLocale();
4435  locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
4436  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
4437  + tr( "Feature count" ) + QStringLiteral( "</td><td>" )
4438  + ( featureCount() == -1 ? tr( "unknown" ) : locale.toString( static_cast<qlonglong>( featureCount() ) ) )
4439  + QStringLiteral( "</td></tr>\n" );
4440 
4441  // End Provider section
4442  myMetadata += QLatin1String( "</table>\n<br><br>" );
4443 
4444  // identification section
4445  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
4446  myMetadata += htmlFormatter.identificationSectionHtml( );
4447  myMetadata += QLatin1String( "<br><br>\n" );
4448 
4449  // extent section
4450  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
4451  myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
4452  myMetadata += QLatin1String( "<br><br>\n" );
4453 
4454  // Start the Access section
4455  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
4456  myMetadata += htmlFormatter.accessSectionHtml( );
4457  myMetadata += QLatin1String( "<br><br>\n" );
4458 
4459  // Fields section
4460  myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
4461 
4462  // primary key
4463  QgsAttributeList pkAttrList = primaryKeyAttributes();
4464  if ( !pkAttrList.isEmpty() )
4465  {
4466  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
4467  const auto constPkAttrList = pkAttrList;
4468  for ( int idx : constPkAttrList )
4469  {
4470  myMetadata += fields().at( idx ).name() + ' ';
4471  }
4472  myMetadata += QLatin1String( "</td></tr>\n" );
4473  }
4474 
4475  const QgsFields myFields = fields();
4476 
4477  // count fields
4478  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
4479 
4480  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
4481  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" );
4482 
4483  for ( int i = 0; i < myFields.size(); ++i )
4484  {
4485  QgsField myField = myFields.at( i );
4486  QString rowClass;
4487  if ( i % 2 )
4488  rowClass = QStringLiteral( "class=\"odd-row\"" );
4489  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" );
4490  }
4491 
4492  //close field list
4493  myMetadata += QLatin1String( "</table>\n<br><br>" );
4494 
4495  // Start the contacts section
4496  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
4497  myMetadata += htmlFormatter.contactsSectionHtml( );
4498  myMetadata += QLatin1String( "<br><br>\n" );
4499 
4500  // Start the links section
4501  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
4502  myMetadata += htmlFormatter.linksSectionHtml( );
4503  myMetadata += QLatin1String( "<br><br>\n" );
4504 
4505  // Start the history section
4506  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
4507  myMetadata += htmlFormatter.historySectionHtml( );
4508  myMetadata += QLatin1String( "<br><br>\n" );
4509 
4510  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
4511  return myMetadata;
4512 }
4513 
4514 void QgsVectorLayer::invalidateSymbolCountedFlag()
4515 {
4516  mSymbolFeatureCounted = false;
4517 }
4518 
4519 void QgsVectorLayer::onFeatureCounterCompleted()
4520 {
4521  onSymbolsCounted();
4522  mFeatureCounter = nullptr;
4523 }
4524 
4525 void QgsVectorLayer::onFeatureCounterTerminated()
4526 {
4527  mFeatureCounter = nullptr;
4528 }
4529 
4530 void QgsVectorLayer::onJoinedFieldsChanged()
4531 {
4532  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4533  updateFields();
4534 }
4535 
4536 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4537 {
4538  if ( mEditCommandActive )
4539  mDeletedFids << fid;
4540  else
4541  emit featuresDeleted( QgsFeatureIds() << fid );
4542 
4543  emit featureDeleted( fid );
4544 }
4545 
4546 void QgsVectorLayer::onRelationsLoaded()
4547 {
4548  mEditFormConfig.onRelationsLoaded();
4549 }
4550 
4551 void QgsVectorLayer::onSymbolsCounted()
4552 {
4553  if ( mFeatureCounter )
4554  {
4555  mSymbolFeatureCounted = true;
4556  mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
4557  mSymbolFeatureIdMap = mFeatureCounter->symbolFeatureIdMap();
4559  }
4560 }
4561 
4562 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
4563 {
4564  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4565 }
4566 
4567 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
4568 {
4569  return QgsProviderRegistry::instance()->listStyles( mProviderKey, mDataSource, ids, names, descriptions, msgError );
4570 }
4571 
4572 QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
4573 {
4574  return QgsProviderRegistry::instance()->getStyleById( mProviderKey, mDataSource, styleId, msgError );
4575 }
4576 
4577 bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
4578 {
4579  return QgsProviderRegistry::instance()->deleteStyleById( mProviderKey, mDataSource, styleId, msgError );
4580 }
4581 
4582 
4583 void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
4584  bool useAsDefault, const QString &uiFileContent, QString &msgError )
4585 {
4586 
4587  QString sldStyle, qmlStyle;
4588  QDomDocument qmlDocument, sldDocument;
4589  QgsReadWriteContext context;
4590  exportNamedStyle( qmlDocument, msgError, context );
4591  if ( !msgError.isNull() )
4592  {
4593  return;
4594  }
4595  qmlStyle = qmlDocument.toString();
4596 
4597  this->exportSldStyle( sldDocument, msgError );
4598  if ( !msgError.isNull() )
4599  {
4600  return;
4601  }
4602  sldStyle = sldDocument.toString();
4603 
4605  mDataSource, qmlStyle, sldStyle, name,
4606  description, uiFileContent, useAsDefault, msgError );
4607 }
4608 
4609 
4610 
4611 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, QgsMapLayer::StyleCategories categories )
4612 {
4613  return loadNamedStyle( theURI, resultFlag, false, categories );
4614 }
4615 
4616 bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
4617 {
4618  bool rc = false;
4619 
4620  QString joinKey = mAuxiliaryLayerKey;
4621  if ( !key.isEmpty() )
4622  joinKey = key;
4623 
4624  if ( storage.isValid() && !joinKey.isEmpty() )
4625  {
4626  QgsAuxiliaryLayer *alayer = nullptr;
4627 
4628  int idx = fields().lookupField( joinKey );
4629 
4630  if ( idx >= 0 )
4631  {
4632  alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
4633 
4634  if ( alayer )
4635  {
4636  setAuxiliaryLayer( alayer );
4637  rc = true;
4638  }
4639  }
4640  }
4641 
4642  return rc;
4643 }
4644 
4646 {
4647  mAuxiliaryLayerKey.clear();
4648 
4649  if ( mAuxiliaryLayer )
4650  removeJoin( mAuxiliaryLayer->id() );
4651 
4652  if ( alayer )
4653  {
4654  addJoin( alayer->joinInfo() );
4655 
4656  if ( !alayer->isEditable() )
4657  alayer->startEditing();
4658 
4659  mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
4660  }
4661 
4662  mAuxiliaryLayer.reset( alayer );
4663  if ( mAuxiliaryLayer )
4664  mAuxiliaryLayer->setParent( this );
4665  updateFields();
4666 }
4667 
4669 {
4670  return mAuxiliaryLayer.get();
4671 }
4672 
4674 {
4675  return mAuxiliaryLayer.get();
4676 }
4677 
4678 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories )
4679 {
4680  QgsDataSourceUri dsUri( theURI );
4681  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
4682  {
4683  QString qml, errorMsg;
4685  if ( !qml.isEmpty() )
4686  {
4687  QDomDocument myDocument( QStringLiteral( "qgis" ) );
4688  myDocument.setContent( qml );
4689  resultFlag = importNamedStyle( myDocument, errorMsg );
4690  return QObject::tr( "Loaded from Provider" );
4691  }
4692  }
4693  return QgsMapLayer::loadNamedStyle( theURI, resultFlag, categories );
4694 }
4695 
4696 QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
4697 {
4698  if ( mDataProvider )
4699  return mDataProvider->dependencies() + mDependencies;
4700  return mDependencies;
4701 }
4702 
4703 void QgsVectorLayer::emitDataChanged()
4704 {
4705  if ( mDataChangedFired )
4706  return;
4707 
4708  mDataChangedFired = true;
4709  emit dataChanged();
4710  mDataChangedFired = false;
4711 }
4712 
4713 bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
4714 {
4715  QSet<QgsMapLayerDependency> deps;
4716  const auto constODeps = oDeps;
4717  for ( const QgsMapLayerDependency &dep : constODeps )
4718  {
4719  if ( dep.origin() == QgsMapLayerDependency::FromUser )
4720  deps << dep;
4721  }
4722 
4723  QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
4724 
4725  // disconnect layers that are not present in the list of dependencies anymore
4726  for ( const QgsMapLayerDependency &dep : qgis::as_const( mDependencies ) )
4727  {
4728  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4729  if ( !lyr )
4730  continue;
4731  disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
4732  disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
4733  disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
4734  disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
4736  }
4737 
4738  // assign new dependencies
4739  if ( mDataProvider )
4740  mDependencies = mDataProvider->dependencies() + deps;
4741  else
4742  mDependencies = deps;
4743  emit dependenciesChanged();
4744 
4745  // connect to new layers
4746  for ( const QgsMapLayerDependency &dep : qgis::as_const( mDependencies ) )
4747  {
4748  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4749  if ( !lyr )
4750  continue;
4751  connect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
4752  connect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
4753  connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
4754  connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
4756  }
4757 
4758  // if new layers are present, emit a data change
4759  if ( ! toAdd.isEmpty() )
4760  emitDataChanged();
4761 
4762  return true;
4763 }
4764 
4765 QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
4766 {
4767  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4768  return nullptr;
4769 
4770  QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
4771 
4772  // make sure provider constraints are always present!
4773  if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
4774  {
4775  constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
4776  }
4777 
4778  return constraints;
4779 }
4780 
4781 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
4782 {
4783  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
4784 
4785  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4786  return m;
4787 
4788  QString name = mFields.at( fieldIndex ).name();
4789 
4790  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
4791  for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
4792  {
4793  if ( conIt.key().first == name )
4794  {
4795  m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
4796  }
4797  }
4798 
4799  return m;
4800 }
4801 
4803 {
4804  if ( index < 0 || index >= mFields.count() )
4805  return;
4806 
4807  QString name = mFields.at( index ).name();
4808 
4809  // add constraint to existing constraints
4810  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
4811  constraints |= constraint;
4812  mFieldConstraints.insert( name, constraints );
4813 
4814  mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
4815 
4816  updateFields();
4817 }
4818 
4820 {
4821  if ( index < 0 || index >= mFields.count() )
4822  return;
4823 
4824  QString name = mFields.at( index ).name();
4825 
4826  // remove constraint from existing constraints
4827  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
4828  constraints &= ~constraint;
4829  mFieldConstraints.insert( name, constraints );
4830 
4831  mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
4832 
4833  updateFields();
4834 }
4835 
4836 QString QgsVectorLayer::constraintExpression( int index ) const
4837 {
4838  if ( index < 0 || index >= mFields.count() )
4839  return QString();
4840 
4841  return mFields.at( index ).constraints().constraintExpression();
4842 }
4843 
4844 QString QgsVectorLayer::constraintDescription( int index ) const
4845 {
4846  if ( index < 0 || index >= mFields.count() )
4847  return QString();
4848 
4849  return mFields.at( index ).constraints().constraintDescription();
4850 }
4851 
4852 void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
4853 {
4854  if ( index < 0 || index >= mFields.count() )
4855  return;
4856 
4857  if ( expression.isEmpty() )
4858  {
4859  mFieldConstraintExpressions.remove( mFields.at( index ).name() );
4860  }
4861  else
4862  {
4863  mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
4864  }
4865  updateFields();
4866 }
4867 
4869 {
4870  if ( index < 0 || index >= mFields.count() )
4871  return;
4872 
4873  if ( setup.isNull() )
4874  mFieldWidgetSetups.remove( mFields.at( index ).name() );
4875  else
4876  mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
4877  updateFields();
4878 }
4879 
4881 {
4882 
4883  if ( index < 0 || index >= mFields.count() )
4884  return QgsEditorWidgetSetup();
4885 
4886  return mFields.at( index ).editorWidgetSetup();
4887 }
4888 
4889 QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
4890 {
4892  if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
4893  {
4894  if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() )
4895  {
4896  // try to load from custom properties
4897  QgsPalLayerSettings settings;
4898  settings.readFromLayerCustomProperties( this );
4899  labeling = new QgsVectorLayerSimpleLabeling( settings );
4900  }
4901 
4902  // also clear old-style labeling config
4903  removeCustomProperty( QStringLiteral( "labeling" ) );
4904  const auto constCustomPropertyKeys = customPropertyKeys();
4905  for ( const QString &key : constCustomPropertyKeys )
4906  {
4907  if ( key.startsWith( QLatin1String( "labeling/" ) ) )
4908  removeCustomProperty( key );
4909  }
4910  }
4911 
4912  return labeling;
4913 }
4914 
4916 {
4917  return mAllowCommit;
4918 }
4919 
4921 {
4922  if ( mAllowCommit == allowCommit )
4923  return;
4924 
4925  mAllowCommit = allowCommit;
4926  emit allowCommitChanged();
4927 }
4928 
4930 {
4931  return mGeometryOptions.get();
4932 }
4933 
4935 {
4936  mReadExtentFromXml = readExtentFromXml;
4937 }
4938 
4940 {
4941  return mReadExtentFromXml;
4942 }
4943 
4944 void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
4945 {
4947  if ( tr && mEditBuffer )
4948  {
4949  qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
4950  }
4951 }
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QgsStringMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const FINAL
Writes vector layer specific state to project file Dom node.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features in joined layers.
QList< QgsExpressionFieldBuffer::ExpressionField > expressions() const
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
QgsFeatureIds symbolFeatureIds(const QString &legendKey) const
Ids of features rendered with specified legend key.
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves mVectorJoins to xml under the layer node.
Class for parsing and evaluation of expressions (formerly called "search strings").
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider...
void opacityChanged(double opacity)
Emitted when the layer&#39;s opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
Q_DECL_DEPRECATED QgsGeometry::OperationResult addPart(const QList< QgsPointXY > &ring)
Adds a new part polygon to a multipart feature.
QgsRectangle sourceExtent() const FINAL
Returns the extent of all geometries from the source.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
QgsFeatureId id
Definition: qgsfeature.h:64
double xOffset
Horizontal offset of label.
QString encoding() const
Gets encoding which is used for accessing data.
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const FINAL
Writes just the style information for the layer into the document.
The class is used as a container of context for various read/write operations on other objects...
Wrapper for iterator of features from vector data provider or vector layer.
void featuresDeleted(const QgsFeatureIds &fids)
Emitted when features have been deleted.
void selectAll()
Select all the features.
void setConstraintStrength(Constraint constraint, ConstraintStrength strength)
Sets the strength of a constraint.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e...
bool saveStyle(const QString &providerKey, const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Saves a layer style to provider.
virtual bool setSubsetString(const QString &subset, bool updateFeatureCount=true)
Set the subset string used to create a subset of features in the layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
bool readSld(const QDomNode &node, QString &errorMessage) FINAL
Base class for all map layer types.
Definition: qgsmaplayer.h:79
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
double rendererScale() const
Returns the renderer map scale.
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geom)
Emitted when a feature&#39;s geometry is changed.
void renameExpression(int index, const QString &name)
Renames an expression field at a given index.
virtual void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const =0
Writes diagram state to a DOM element.
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
QVariant maximumValue(int index) const override
Returns the maximum value of an attribute.
QgsVectorLayerFeatureCounter * countSymbolFeatures()
Count features for symbols.
bool containsJoins() const
Quick way to test if there is any join at all.
void update(const QgsFields &fields)
Update the configuration with the given fields.
virtual QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml()
void setRenderer(QgsFeatureRenderer *r)
Sets renderer which will be invoked to represent this layer.
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:50
bool readSymbology(const QDomNode &layerNode, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) FINAL
Reads the symbology for the current layer from the Dom node supplied.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
void setExcludeAttributesWms(const QSet< QString > &att)
A set of attributes that are not advertised in WMS requests with QGIS server.
QVariantMap config() const
virtual bool renameAttribute(int attr, const QString &newName)
Renames an attribute field (but does not commit it)
virtual bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
int size() const
Returns number of items.
Definition: qgsfields.cpp:138
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as SLD style in a QDomDocument.
FieldOrigin fieldOrigin(int fieldIdx) const
Gets field&#39;s origin (value from an enumeration)
Definition: qgsfields.cpp:189
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:151
virtual QString subsetString() const
Returns the subset definition string (typically sql) currently in use by the layer and used by the pr...
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
void taskCompleted()
Will be emitted by task to indicate its successful completion.
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
void dependenciesChanged()
Emitted when dependencies are changed.
QgsWkbTypes::Type wkbType() const override=0
Returns the geometry type which is returned by this layer.
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
void readXml(const QDomNode &node, QgsReadWriteContext &context)
Read XML information Deserialize on project load.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
bool isValid() const
Returns the status of the auxiliary storage currently defined.
virtual QString subsetString() const
Returns the string (typically sql) used to define a subset of the layer.
QgsMapLayerType type() const
Returns the type of the layer.
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
void editFormConfigChanged()
Will be emitted whenever the edit form configuration of this layer changes.
void modifySelection(const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds)
Modifies the current selection on this layer.
bool writeXml(QDomNode &layer_node) const
Writes the actions out in XML format.
virtual void updateExtents()
Update the extents of the layer.
QString name
Definition: qgsfield.h:58
The QgsGeometryOptions class contains options to automatically adjust geometries to constraints on a ...
void addExpression(const QString &exp, const QgsField &fld)
Add an expression to the buffer.
QVariant minimumValue(int index) const override
Returns the minimum value of an attribute.
int precision
Definition: qgsfield.h:55
void setFidsFilter(const QgsFeatureIds &fids)
Sets a filter to limit the features used during the aggregate calculation.
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field index.
bool isValid() const
Returns if this default value should be applied.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
bool writeXml(QDomNode &node, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes the condition styles state to a DOM node.
void beforeRollBack()
Emitted before changes are rolled back.
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
bool hasParam(const QString &key) const
Returns true if a parameter with the specified key exists.
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
Use exact geometry intersection (slower) instead of bounding boxes.
QSet< QString > excludeAttributesWms() const
A set of attributes that are not advertised in WMS requests with QGIS server.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const FINAL
Called by writeLayerXML(), used by derived classes to encode provider&#39;s specific data source to proje...
QStringList customPropertyKeys() const
Returns list of all keys within custom properties.
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString())
Push a category to the stack.
double angleOffset
Label rotation, in degrees clockwise.
QString mapTipTemplate() const
The mapTip is a pretty, html representation for feature information.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
QString alias
Definition: qgsfield.h:59
QgsMapLayerLegend * legend() const
Can be nullptr.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
Renders the diagrams for all features with the same settings.
FeatureAvailability
Possible return value for hasFeatures() to determine if a source is empty.
void setExtent(const QgsRectangle &rect) FINAL
Sets the extent.
The QgsDefaultValue class provides a container for managing client side default values for fields...
Q_DECL_DEPRECATED QgsGeometry::OperationResult addRing(const QVector< QgsPointXY > &ring, QgsFeatureId *featureId=nullptr)
Adds a ring to polygon/multipolygon features.
virtual void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgsrenderer.h:301
Constraint
Constraints which may be present on a field.
QSet< QString > excludeAttributesWfs() const
A set of attributes that are not advertised in WFS requests with QGIS server.
virtual bool addFeature(QgsFeature &f)
Adds a feature.
Field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfields.h:51
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Setting options for loading vector layers.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
bool deleteFeature(QgsFeatureId fid)
Deletes a feature from the layer (but does not commit it).
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QSet< QgsMapLayerDependency > dependencies() const FINAL
Gets the list of dependencies.
QList< QgsRelation > referencingRelations(const QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Gets all relations where the specified layer (and field) is the referencing part (i.e.
void mapTipTemplateChanged()
Emitted when the map tip changes.
Class allowing to manage the auxiliary storage for a vector layer.
QString qgsEnumValueToKey(const T &value)
Returns the value for the given key of an enum.
Definition: qgis.h:451
bool mShouldValidateCrs
true if the layer&#39;s CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1541
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present at the provider for a specified field index.
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point...
void attributeDeleted(int idx)
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads diagram state from a DOM element.
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:1529
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
bool deleteStyleById_t(const QString &uri, QString styleID, QString &errCause)
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:121
Counts the features in a QgsVectorLayer in task.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
void setSize(double size)
Sets the size of the buffer.
A class to represent a 2D point.
Definition: qgspointxy.h:43
friend class QgsVectorLayerFeatureSource
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported...
void readOnlyChanged()
Emitted when the read only state of this layer is changed.
bool renameAttribute(int index, const QString &newName)
Renames an attribute field (but does not commit it).
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:280
void invertSelectionInRectangle(QgsRectangle &rect)
Inverts selection of features found within the search rectangle (in layer&#39;s coordinates) ...
void subsetStringChanged()
Emitted when the layer&#39;s subset string has changed.
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
bool commitChanges()
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
virtual QSet< QgsMapLayerDependency > dependencies() const
Gets the list of layer ids on which this layer depends.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context)
store renderer info to XML element
EditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
bool startEditing()
Makes the layer editable.
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
void setFont(const QFont &font)
Sets the font used for rendering text.
QgsVectorLayer(const QString &path=QString(), const QString &baseName=QString(), const QString &providerLib="ogr", const QgsVectorLayer::LayerOptions &options=QgsVectorLayer::LayerOptions())
Constructor - creates a vector layer.
bool deleteAttributes(const QList< int > &attrs)
Deletes a list of attribute fields (but does not commit it)
VertexMarkerType
Editing vertex markers.
void removeExpressionField(int index)
Removes an expression field.
void setFeatureBlendMode(QPainter::CompositionMode blendMode)
Sets the blending mode used for rendering each feature.
QVariant evaluate()
Evaluate the feature and return the result.
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
Remove from current selection.
void writeXml(QDomElement &layerElem, QDomDocument &doc) const
Writes the diagram settings to a DOM element.
QString comment
Definition: qgsfield.h:57
virtual void resolveReferences(QgsProject *project)
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects...
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
~QgsVectorLayer() override
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const FINAL
Writes the symbology for the layer into the document provided.
Class providing some utility methods to manage auxiliary storage.
SimplifyHint
Simplification flags for fast rendering of features.
Utility class for calculating aggregates for a field (or expression) over the features from a vector ...
double yOffset
Vertical offset of label.
void setLabeling(QgsAbstractVectorLayerLabeling *labeling)
Sets labeling configuration.
Provider can create feature renderers using backend-specific formatting information. Since QGIS 3.2. See QgsVectorDataProvider::createRenderer().
void readCustomSymbology(const QDomElement &element, QString &errorMessage)
Signal emitted whenever the symbology (QML-file) for this layer is being read.
QString evalErrorString() const
Returns evaluation error.
Aliases, widgets, WMS/WFS, expressions, constraints, virtual fields.
Definition: qgsmaplayer.h:155
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it)
virtual const QgsLayerMetadata & metadata() const
Returns a reference to the layer&#39;s metadata store.
void readXml(const QDomNode &layer_node)
Reads joins from project file.
void raiseError(const QString &msg) const
Signals an error in this provider.
void configChanged()
Emitted whenever the configuration is changed.
void setDiagramRenderer(QgsDiagramRenderer *r)
Sets diagram rendering object (takes ownership)
Container of fields for a vector layer.
Definition: qgsfields.h:42
virtual void rollBack()
Stop editing and discard the edits.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
void selectByIds(const QgsFeatureIds &ids, SelectBehavior behavior=SetSelection)
Selects matching features using a list of feature IDs.
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:211
virtual QgsFeatureRenderer * createRenderer(const QVariantMap &configuration=QVariantMap()) const
Creates a new vector layer feature renderer, using provider backend specific information.
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer...
long featureCount() const FINAL
Returns feature count including changes which have not yet been committed If you need only the count ...
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const FINAL
Called by readLayerXML(), used by derived classes to decode provider&#39;s specific data source from proj...
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not committed.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
Allows entering a context category and takes care of leaving this category on deletion of the class...
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:438
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > fieldConstraintsAndStrength(int fieldIndex) const
Returns a map of constraint with their strength for a specific field of the layer.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
QString getStyleById(const QString &providerKey, const QString &uri, QString styleId, QString &errCause)
Gets a layer style defined by styleId.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
Stores information about constraints which may be present on a field.
Field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfields.h:49
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
bool isAuxiliaryField(int index, int &srcIndex) const
Returns true if the field comes from the auxiliary layer, false otherwise.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
static const int EditingCapabilities
Bitmask of all provider&#39;s editing capabilities.
void resolveReferences(QgsProject *project) FINAL
Resolves references to other layers (kept as layer IDs after reading XML) into layer objects...
bool isValid() const
Returns the status of the layer.
An interface for classes which can visit style entity (e.g.
QgsFields fields
Definition: qgsfeature.h:66
QgsChangedAttributesMap changedAttributeValues() const
Returns a map of features with changed attributes values which are not committed. ...
void beforeCommitChanges()
Emitted before changes are committed to the data provider.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
Definition: qgis.cpp:222
QgsFeatureList selectedFeatures() const
Returns a copy of the user-selected features.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
Emitted when features are deleted from the provider.
QUuid addAction(QgsAction::ActionType type, const QString &name, const QString &command, bool capture=false)
Add an action with the given name and action details.
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Emitted when attributes are deleted from the provider.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SslMode sslmode=SslPrefer, const QString &authConfigId=QString())
Sets all connection related members at once.
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...
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:612
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
OperationResult
Success or failure of a geometry operation.
Definition: qgsgeometry.h:134
QString username() const
Returns the username stored in the URI.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present for a specified field index.
QgsFeatureIds deletedFeatureIds() const
Returns a list of deleted feature IDs which are not committed.
void invertSelection()
Selects not selected features and deselects selected ones.
void setParameters(const AggregateParameters &parameters)
Sets all aggregate parameters from a parameter bundle.
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:154
Attribute table settings: choice and order of columns, conditional styling.
Definition: qgsmaplayer.h:160
It has not been specified where the field comes from.
Definition: qgsfields.h:48
void deselect(QgsFeatureId featureId)
Deselects feature by its ID.
Constraint was set at data provider.
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
Field has an expression constraint set. See constraintExpression().
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
bool writeXml(QDomNode &layerNode) const
Writes the stored expressions out in XML format.
virtual QgsRectangle extent() const
Returns the extent of the layer.
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
void removeSelection()
Clear selection.
QString attributeAlias(int index) const
Returns the alias of an attribute name or a null string if there is no alias.
Manages joined fields for a vector layer.
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
virtual QgsLayerMetadata layerMetadata() const
Returns layer metadata collected from the provider&#39;s source.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
void setAuxiliaryLayer(QgsAuxiliaryLayer *layer=nullptr)
Sets the current auxiliary layer.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions())
Creates a new instance of a provider.
int length
Definition: qgsfield.h:54
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
int fieldOriginIndex(int fieldIdx) const
Gets field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfields.cpp:197
bool updateFeature(QgsFeature &feature, bool skipDefaultValues=false)
Updates an existing feature in the layer, replacing the attributes and geometry for the feature with ...
static QgsTaskManager * taskManager()
Returns the application&#39;s task manager, used for managing application wide background task handling...
void dataChanged()
Emitted whenever a change is made to the data provider which may have caused changes in the provider&#39;...
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Definition: qgsfeedback.h:44
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
void setFieldConstraint(int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthHard)
Sets a constraint for a specified field index.
void featureAdded(QgsFeatureId fid)
virtual int listStylesInDatabase(QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError)
Lists all the style in db split into related to the layer and not related to.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsRectangle mExtent
Extent of the layer.
Definition: qgsmaplayer.h:1477
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
void setExcludeAttributesWfs(const QSet< QString > &att)
A set of attributes that are not advertised in WFS requests with QGIS server.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets feature ID that should be fetched.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changes attribute value in joined layers.
Q_DECL_DEPRECATED void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Update the data source of the layer.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
QString host() const
Returns the host name stored in the URI.
void setEditorWidgetSetup(int index, const QgsEditorWidgetSetup &setup)
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
QgsRectangle boundingBoxOfSelected() const
Returns the bounding box of the selected features. If there is no selection, QgsRectangle(0,0,0,0) is returned.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
virtual void updateExtents(bool force=false)
Update the extents for the layer.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
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.
bool readXml(const QDomNode &layer_node)
Reads the actions in in XML format.
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
void setSize(double size)
Sets the size for rendered text.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue)
Returns the value corresponding to the given key of an enum.
Definition: qgis.h:463
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
void reselect()
Reselects the previous set of selected features.
QgsGeometry getGeometry(QgsFeatureId fid) const
Queries the layer for the geometry at the given id.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
#define FALLTHROUGH
Definition: qgis.h:681
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature&#39;s geometry within the layer&#39;s edit buffer (but does not immediately commit the chan...
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any). To be called by subclasses.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted...
bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) FINAL
Reads the style for the current layer from the Dom node supplied.
void attributeAdded(int idx)
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
bool deleteFeature(QgsFeatureId fid) const
Deletes a feature from joined layers.
void select(QgsFeatureId featureId)
Selects feature by its ID.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
bool allowCommit() const
Controls, if the layer is allowed to commit changes.
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:105
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:161
void featureBlendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when setFeatureBlendMode() is called.
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:87
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer&#39;s metadata store.
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap())
Changes attributes&#39; values in joined layers.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
QSet< QgsMapLayerDependency > mDependencies
List of layers that may modify this layer on modification.
Definition: qgsmaplayer.h:1516
void beforeModifiedCheck() const
Emitted when the layer is checked for modifications. Use for last-minute additions.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
void reload() FINAL
Synchronises with changes in the datasource.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
QString dataComment() const
Returns a description for this layer as defined in the data provider.
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer&#39;s relations, where the foreign key is on this layer.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
static QString geometryDisplayString(GeometryType type)
Returns a display string for a geometry type.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
bool deleteFeatures(const QgsFeatureIds &fids) const
Deletes a list of features from joined layers.
void afterRollBack()
Emitted after changes are rolled back.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
Utility class that encapsulates an action based on vector attributes.
Definition: qgsaction.h:35
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
double opacity() const
Returns the opacity for the vector layer, where opacity is a value between 0 (totally transparent) an...
Geometry validation configuration.
Definition: qgsmaplayer.h:163
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
Emitted when features are added to the provider.
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) FINAL
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context...
void readXml(const QDomElement &elem)
Reads the diagram settings from a DOM element.
int listStyles(const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Lists stored layer styles in the provider defined by providerKey and uri.
bool setDependencies(const QSet< QgsMapLayerDependency > &layers) FINAL
Sets the list of dependencies.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsStringMap &props=QgsStringMap()) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Q_DECL_DEPRECATED QgsGeometry::OperationResult addPart(const QVector< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
Defines left outer join from our vector layer to some other vector layer.
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it).
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void beforeEditingStarted()
Emitted before editing on this layer is started.
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:812
QgsGeometryMap mChangedGeometries
Changed geometries which are not committed.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
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)...
Don&#39;t resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:531
void setColor(const QColor &color)
Sets the color that text will be rendered in.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsAttributeList primaryKeyAttributes() const
Returns the list of attributes which make up the layer&#39;s primary keys.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves expressions to xml under the layer node.
QgsVectorLayerJoinInfo joinInfo() const
Returns information to use for joining with primary key and so on.
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature&#39;s geometry.
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const =0
Returns labeling configuration as XML element.
void setFieldAlias(int index, const QString &aliasString)
Sets an alias (a display name) for attributes to display in dialogs.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
float threshold() const
Gets the simplification threshold of the vector layer managed.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a list of features to the sink.
An expression node which takes it value from a feature&#39;s field.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
virtual QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, int index, const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool &ok, QgsFeatureIds *fids=nullptr) const
Calculates an aggregated value from the layer&#39;s features.
void dataSourceChanged()
Emitted whenever the layer&#39;s data source has been changed.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
Storage and management of actions associated with a layer.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
virtual bool deleteFeatures(const QgsFeatureIds &fid)
Deletes a set of features from the layer (but does not commit it)
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
bool setReadOnly(bool readonly=true)
Makes layer read-only (editing disabled) or not.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
void setParam(const QString &key, const QString &value)
Sets a generic parameter value on the URI.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr)
Adds a single feature to the sink.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
QString loadStyle(const QString &providerKey, const QString &uri, QString &errCause)
Loads a layer style defined by uri.
T flagValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on a flag.
Definition: qgssettings.h:322
Manages QGIS Server properties for a vector layer.
QgsFeatureRenderer * renderer()
Returns renderer.
Y-coordinate data defined diagram position.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not committed.
const QgsVectorJoinList & vectorJoins() const
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
QgsEditFormConfig editFormConfig() const
Returns the configuration of the form used to represent this vector layer.
void setSimplifyAlgorithm(SimplifyAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error...
void rendererChanged()
Signal emitted when renderer is changed.
void updateFields(QgsFields &flds)
Adds fields with the expressions buffered in this object to a QgsFields object.
virtual bool isSaveAndLoadStyleToDatabaseSupported() const
It returns false by default.
Single scope for storing variables and functions for use within a QgsExpressionContext.
double minimumScale() const
Returns the minimum map scale (i.e.
Contains information about the context in which a coordinate transform is executed.
virtual bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues)
Changes values of attributes (but does not commit it).
Fast access to features using their ID.
QgsRelationManager relationManager
Definition: qgsproject.h:100
Whether to show the diagram.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
double maximumScale() const
Returns the maximum map scale (i.e.
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1480
QString port() const
Returns the port stored in the URI.
void raiseError(const QString &msg)
Signals an error related to this vector layer.
Add selection to current selection.
void editingStarted()
Emitted when editing on this layer has started.
void setName(const QString &name)
Set the display name of the layer.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QString capabilitiesString() const
Capabilities for this layer, comma separated and translated.
static Q_DECL_DEPRECATED void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
QVariant calculate(Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr) const
Calculates the value of an aggregate.
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
Double value (including negative values)
Definition: qgsproperty.h:57
virtual QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const
Returns the set of unique values contained within the specified fieldIndex from this source...
QString constraintDescription(int index) const
Returns the descriptive name for the constraint expression for a specified field index.
void symbolFeatureCountMapChanged()
Emitted when the feature count for symbols on this layer has been recalculated.
QHash< QString, QgsFeatureIds > symbolFeatureIdMap() const
Returns the QgsFeatureIds for each symbol.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
virtual bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
void setConstraint(Constraint constraint, ConstraintOrigin origin=ConstraintOriginLayer)
Sets a constraint on the field.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
Emitted when attribute value changes are saved to the provider.
void dirtied(const QString &sql, const QString &name)
Emitted if a sql query is executed and the underlying data is modified.
const QgsVectorSimplifyMethod & simplifyMethod() const
Returns the simplification settings for fast rendering of features.
QString displayField() const
This is a shorthand for accessing the displayExpression if it is a simple field.
virtual bool deleteAttribute(int attr)
Delete an attribute field (but does not commit it)
bool readXml(const QDomNode &node, const QgsReadWriteContext &context)
Reads the condition styles state from a DOM node.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
Definition for a property.
Definition: qgsproperty.h:46
void fullExtentCalculated()
Emitted whenever a deferred extent calculation is completed by the provider.
const QgsDiagramRenderer * diagramRenderer() const
virtual QgsAbstractVectorLayerLabeling * createLabeling(const QVariantMap &configuration=QVariantMap()) const
Creates labeling settings, using provider backend specific information.
bool loadAuxiliaryLayer(const QgsAuxiliaryStorage &storage, const QString &key=QString())
Loads the auxiliary layer for this vector layer.
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
void writeXml(QDomNode &node) const
Serialize to XML on layer save.
bool readExtentFromXml() const
Returns true if the extent is read from the XML document when data source has no metadata, false if it&#39;s the data provider which determines it.
void editCommandDestroyed()
Signal emitted, when an edit command is destroyed.
void recalculateExtents() const
This is used to send a request that any mapcanvas using this layer update its extents.
Set selection, removing any existing selection.
int addExpressionField(const QString &exp, const QgsField &fld)
Add a new field which is calculated by the expression specified.
void setMaximumScale(float maximumScale)
Sets the maximum scale at which the layer should be simplified.
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurve.cpp:40
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
The derived translate() translates with QTranslator and qm file the sourceText.
void selectByRect(QgsRectangle &rect, SelectBehavior behavior=SetSelection)
Selects features found within the search rectangle (in layer&#39;s coordinates)
static QgsMapLayerLegend * defaultVectorLegend(QgsVectorLayer *vl)
Create new legend implementation for vector layer.
void setProviderEncoding(const QString &encoding)
Sets the textencoding of the data provider.
void relationsLoaded()
Emitted when the relations were loaded after reading a project.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
virtual void cancel()
Notifies the task that it should terminate.
General configuration: identifiable, removable, searchable, display expression, read-only.
Definition: qgsmaplayer.h:151
Implementation of threaded rendering for vector layers.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists). To be called by subclasses.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
Stores the settings for rendering of all diagrams for a layer.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
void writeXml(QDomNode &node, const QgsReadWriteContext &context) const
Write XML information Serialize on project save.
QVector< QgsPoint > QgsPointSequence
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:359
bool readXml(const QDomNode &layerNode)
Reads the stored expressions in in XML format.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
QString capabilitiesString() const
Returns the above in friendly format.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:139
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
Modify current selection to include only select features which match.
QgsDefaultValue defaultValueDefinition(int index) const
Returns the definition of the expression used when calculating the default value for a field...
QMap< QgsFeatureId, QgsFeature > QgsFeatureMap
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
SelectBehavior
Selection behavior.
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Insert a new vertex before the given vertex number, in the given ring, item (first number is index 0)...
QgsFeatureMap addedFeatures() const
Returns a map of new features which are not committed.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
void selectByExpression(const QString &expression, SelectBehavior behavior=SetSelection)
Selects matching features using an expression.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
void allowCommitChanged()
Emitted whenever the allowCommitChanged() property of this layer changes.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void beforeAddingExpressionField(const QString &fieldName)
Will be emitted, when an expression field is going to be added to this vector layer.
Custom properties (by plugins for instance)
Definition: qgsmaplayer.h:162
Contains information about the context of a rendering operation.
QgsExpressionContextScope * createExpressionContextScope() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Setting options for creating vector data providers.
QgsFieldConstraints constraints
Definition: qgsfield.h:61
X-coordinate data defined diagram position.
QString name() const
Returns the display name of the layer.
Buffers information about expression fields for a vector layer.
QString getStyleById_t(const QString &uri, QString styleID, QString &errCause)
bool isEmpty() const
Returns true if the configuration is empty, ie it contains no columns.
bool deleteStyleById(const QString &providerKey, const QString &uri, QString styleId, QString &errCause)
Deletes a layer style defined by styleId.
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
QString loadStyle_t(const QString &uri, QString &errCause)
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
void displayExpressionChanged()
Emitted when the display expression changes.
Q_DECL_DEPRECATED QgsGeometry::OperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1483
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
virtual void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets data coordinate transform context to transformContext.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
QString source() const
Returns the source for the layer.
long featureCount() const override=0
Number of features in the layer.
const QgsDiagramLayerSettings * diagramLayerSettings() const
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
void setConstraintExpression(const QString &expression, const QString &description=QString())
Set the constraint expression for the field.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
QgsCoordinateTransformContext transformContext
Coordinate transform context.
ConstraintStrength
Strength of constraints.
Holder for the widget type and its configuration for a field.
void updateExpression(int index, const QString &exp)
Changes the expression at a given index.
virtual void toSld(QDomNode &parent, const QgsStringMap &props) const
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
static QgsFeatureRenderer * loadSld(const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
Container for settings relating to a text buffer.
virtual void reloadData()
Reloads the data from the source.
void setAllowCommit(bool allowCommit)
Controls, if the layer is allowed to commit changes.
bool deleteSelectedFeatures(int *deletedCount=nullptr)
Deletes the selected features.
Edit operation was successful.
QString expressionField(int index) const
Returns the expression used for a given expression field.
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported...
Feature form.
Definition: qgsmaplayer.h:156
QString constraintExpression(int index) const
Returns the constraint expression for for a specified field index, if set.
The QgsConditionalLayerStyles class holds conditional style information for a layer.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0)...
void updateFields(QgsFields &fields)
Updates field map with joined attributes.
QgsWkbTypes::Type fallbackWkbType
Fallback geometry type.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
Emitted when attributes are added to the provider.
void readXml(const QDomNode &layer_node)
Reads expressions from project file.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:442
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
void removeExpression(int index)
Remove an expression from the buffer.
virtual QString dataComment() const
Returns a short comment for the data that this provider is providing access to (e.g.
This class represents a coordinate reference system (CRS).
bool isField() const
Checks whether an expression consists only of a single field reference.
virtual QStringList uniqueStringsMatching(int index, const QString &substring, int limit=-1, QgsFeedback *feedback=nullptr) const
Returns unique string values of an attribute which contain a specified subset string.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
friend class QgsVectorLayerEditBuffer
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QHash< QString, long > symbolFeatureCountMap() const
Returns the count for each symbol.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:436
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
Provider can set labeling settings using backend-specific formatting information. Since QGIS 3...
void removeFieldAlias(int index)
Removes an alias (a display name) for attributes to display in dialogs.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a single feature to the sink.
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written. ...
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QgsVectorLayer::EditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
void setDefaultValueDefinition(int index, const QgsDefaultValue &definition)
Sets the definition of the expression to use when calculating the default value for a field...
virtual QString getStyleFromDatabase(const QString &styleId, QString &msgError)
Returns the named style corresponding to style id provided.
virtual bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
virtual bool enterUpdateMode()
Enter update mode.
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Sets the simplification settings for fast rendering of features.
friend class QgsVectorLayerEditPassthrough
Class for metadata formatter.
Basic implementation of the labeling interface.
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
Definition: qgssettings.h:244
void dataChanged()
Data of layer changed.
void joinedFieldsChanged()
Emitted whenever the list of joined fields changes (e.g.
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
virtual bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changed an attribute value (but does not commit it)
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
Base class for utility classes that encapsulate information necessary for rendering of map layers...
void setConstraintExpression(int index, const QString &expression, const QString &description=QString())
Sets the constraint expression for the specified field index.
QString sourceName() const FINAL
Returns a friendly display name for the source.
virtual void handlePostCloneOperations(QgsVectorDataProvider *source)
Handles any post-clone operations required after this vector data provider was cloned from the source...
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text&#39;s buffer settings.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
bool isExpression
true if this label is made from a expression string, e.g., FieldName || &#39;mm&#39;
QgsCoordinateReferenceSystem sourceCrs() const FINAL
Returns the coordinate reference system for features in the source.
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
QString password() const
Returns the password stored in the URI.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:66
virtual QgsRectangle extent() const =0
Returns the extent of the layer.
FeatureAvailability hasFeatures() const FINAL
Determines if this vector layer has features.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:126
QgsGeometry geometry
Definition: qgsfeature.h:67
Edit failed due to invalid layer.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QUndoStack * undoStack()
Returns pointer to layer&#39;s undo stack.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer&#39;s data provider, it may be nullptr.
QList< int > QgsAttributeList
Definition: qgsfield.h:27
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
void normalize()
Normalize the rectangle so it has non-negative width/height.
Definition: qgsrectangle.h:182
virtual bool deleteStyleFromDatabase(const QString &styleId, QString &msgError)
Deletes a style from the database.
bool nextFeature(QgsFeature &f)
This is a container for configuration of the attribute table.
void setCoordinateSystem()
Setup the coordinate system transformation for the layer.
This is the base class for vector data providers.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
virtual void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
Container for all settings relating to text rendering.
QString constraintExpression() const
Returns the constraint expression for the field, if set.
static QgsFeatureRenderer * defaultRenderer(QgsWkbTypes::GeometryType geomType)
Returns a new renderer - used by default in vector layers.
Definition: qgsrenderer.cpp:76
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap(), bool skipDefaultValues=false)
Changes attributes&#39; values for a feature (but does not immediately commit the changes).
Geometry is not required. It may still be returned if e.g. required for a filter condition.
void setEditFormConfig(const QgsEditFormConfig &editFormConfig)
Sets the editFormConfig (configuration) of the form used to represent this vector layer...
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
Class for storing the component parts of a RDBMS data source URI (e.g.
QgsFeatureMap mAddedFeatures
New features which are not committed.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
Emitted when geometry changes are saved to the provider.
A vector of attributes.
Definition: qgsattributes.h:57
virtual bool empty() const
Returns true if the layer does not contain any feature.
QgsCoordinateReferenceSystem fallbackCrs
Fallback layer coordinate reference system.
This class models dependencies with or between map layers.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QString createSavepoint(QString &error)
creates a save point returns empty string on error returns the last created savepoint if it&#39;s not dir...
QString displayExpression() const
Returns the preview expression, used to create a human readable preview string.
void updateFields(QgsFields &fields)
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error...
void layerModified()
Emitted when modifications has been done on layer.
Represents a vector layer which manages a vector based data sets.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QString htmlMetadata() const FINAL
Obtain a formatted HTML string containing assorted metadata for this layer.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml()
Field is calculated from an expression.
Definition: qgsfields.h:52
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
void updateExpressionField(int index, const QString &exp)
Changes the expression used to define an expression based (virtual) field.
EditResult
Result of an edit operation.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
void layerModified()
Emitted when modifications has been done on layer.
QgsAttributeList mDeletedAttributeIds
Deleted attributes fields which are not committed. The list is kept sorted.
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:37
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else...
void setColor(const QColor &color)
Sets the color for the buffer.
QString database() const
Returns the database name stored in the URI.
Manages stored expressions regarding creation, modification and storing in the project.
void featureDeleted(QgsFeatureId fid)
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
QgsAuxiliaryLayer * createAuxiliaryLayer(const QgsField &field, QgsVectorLayer *layer) const
Creates an auxiliary layer for a vector layer.
QgsDefaultValue defaultValueDefinition
Definition: qgsfield.h:60
void set(const QgsPointXY &p1, const QgsPointXY &p2)
Sets the rectangle from two QgsPoints.
Definition: qgsrectangle.h:105
QString authid() const
Returns the authority identifier for the CRS.
void setDatabase(const QString &database)
Sets the URI database name.
QgsAttributes attributes
Definition: qgsfeature.h:65
void resolveReferences(QgsProject *project)
Resolves layer IDs of joined layers using given project&#39;s available layers.
static QgsAbstractVectorLayerLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Try to create instance of an implementation based on the XML data.
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
virtual bool hasMetadata() const
Returns true if the data source has metadata, false otherwise.
void readXml(const QDomNode &node)
Deserialize to XML on layer load.
Aggregate
Available aggregates to calculate.
virtual bool leaveUpdateMode()
Leave update mode.
void setFlags(QgsMapLayer::LayerFlags flags)
Returns the flags for this layer.
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) FINAL
Reads vector layer specific state from project file Dom node.
QString joinLayerId() const
ID of the joined layer - may be used to resolve reference to the joined layer.
void setReadExtentFromXml(bool readExtentFromXml)
Flag allowing to indicate if the extent has to be read from the XML document when data source has no ...
QgsMapLayer::ReadFlags mReadFlags
Read flags. It&#39;s up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1534
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.
A bundle of parameters controlling aggregate calculation.
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
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.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
bool saveStyle_t(const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
QString fieldName
Name of field (or an expression) to use for label text.
Field must have a unique value.
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&#39;s features.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index...
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
void setOpacity(double opacity)
Sets the opacity for the vector layer, where opacity is a value between 0 (totally transparent) and 1...