QGIS API Documentation  2.99.0-Master (b058df7)
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 <QImage>
27 #include <QPainter>
28 #include <QPainterPath>
29 #include <QPolygonF>
30 #include <QProgressDialog>
31 #include <QString>
32 #include <QDomNode>
33 #include <QVector>
34 #include <QStringBuilder>
35 
36 #include "qgssettings.h"
37 #include "qgsvectorlayer.h"
38 #include "qgsactionmanager.h"
39 #include "qgis.h" //for globals
40 #include "qgsapplication.h"
41 #include "qgsclipper.h"
42 #include "qgsconditionalstyle.h"
44 #include "qgscoordinatetransform.h"
45 #include "qgsexception.h"
46 #include "qgscurve.h"
47 #include "qgsdatasourceuri.h"
49 #include "qgsexpressionnodeimpl.h"
50 #include "qgsfeature.h"
51 #include "qgsfeaturerequest.h"
52 #include "qgsfields.h"
53 #include "qgsgeometry.h"
55 #include "qgslogger.h"
56 #include "qgsmaplayerlegend.h"
57 #include "qgsmaptopixel.h"
58 #include "qgsmessagelog.h"
59 #include "qgsogcutils.h"
60 #include "qgspainting.h"
61 #include "qgspointxy.h"
62 #include "qgsproject.h"
63 #include "qgsproviderregistry.h"
64 #include "qgsrectangle.h"
65 #include "qgsrelationmanager.h"
66 #include "qgsrendercontext.h"
67 #include "qgsvectordataprovider.h"
73 #include "qgsvectorlayerlabeling.h"
74 #include "qgsvectorlayerrenderer.h"
77 #include "qgspoint.h"
78 #include "qgsrenderer.h"
79 #include "qgssymbollayer.h"
81 #include "qgsdiagramrenderer.h"
82 #include "qgsstyle.h"
83 #include "qgspallabeling.h"
84 #include "qgssimplifymethod.h"
85 #include "qgsexpressioncontext.h"
86 #include "qgsfeedback.h"
87 #include "qgsxmlutils.h"
88 #include "qgsunittypes.h"
89 #include "qgstaskmanager.h"
90 #include "qgstransaction.h"
91 #include "qgsauxiliarystorage.h"
92 
93 #include "diagram/qgsdiagram.h"
94 
95 #ifdef TESTPROVIDERLIB
96 #include <dlfcn.h>
97 #endif
98 
99 typedef bool saveStyle_t(
100  const QString &uri,
101  const QString &qmlStyle,
102  const QString &sldStyle,
103  const QString &styleName,
104  const QString &styleDescription,
105  const QString &uiFileContent,
106  bool useAsDefault,
107  QString &errCause
108 );
109 
110 typedef QString loadStyle_t(
111  const QString &uri,
112  QString &errCause
113 );
114 
115 typedef int listStyles_t(
116  const QString &uri,
117  QStringList &ids,
118  QStringList &names,
119  QStringList &descriptions,
120  QString &errCause
121 );
122 
123 typedef QString getStyleById_t(
124  const QString &uri,
125  QString styleID,
126  QString &errCause
127 );
128 
129 typedef bool deleteStyleById_t(
130  const QString &uri,
131  QString styleID,
132  QString &errCause
133 );
134 
135 
136 QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
137  const QString &baseName,
138  const QString &providerKey,
139  const LayerOptions &options )
140  : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
141  , mProviderKey( providerKey )
142  , mAuxiliaryLayer( nullptr )
143  , mAuxiliaryLayerKey( QString() )
144  , mReadExtentFromXml( options.readExtentFromXml )
145 {
146  mActions = new QgsActionManager( this );
147  mConditionalStyles = new QgsConditionalLayerStyles();
148 
149  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
150  connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
151 
152  // if we're given a provider type, try to create and bind one to this layer
153  if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
154  {
155  setDataSource( vectorLayerPath, baseName, providerKey, options.loadDefaultStyle );
156  }
157 
158  connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { emit repaintRequested(); } );
159  connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
160 
161  // Default simplify drawing settings
162  QgsSettings settings;
163  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( settings.value( QStringLiteral( "qgis/simplifyDrawingHints" ), static_cast< int>( mSimplifyMethod.simplifyHints() ) ).toInt() ) );
164  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( settings.value( QStringLiteral( "qgis/simplifyAlgorithm" ), static_cast< int>( mSimplifyMethod.simplifyAlgorithm() ) ).toInt() ) );
165  mSimplifyMethod.setThreshold( settings.value( QStringLiteral( "qgis/simplifyDrawingTol" ), mSimplifyMethod.threshold() ).toFloat() );
166  mSimplifyMethod.setForceLocalOptimization( settings.value( QStringLiteral( "qgis/simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ).toBool() );
167  mSimplifyMethod.setMaximumScale( settings.value( QStringLiteral( "qgis/simplifyMaxScale" ), mSimplifyMethod.maximumScale() ).toFloat() );
168 } // QgsVectorLayer ctor
169 
170 
171 
173 {
174  emit willBeDeleted();
175 
176  mValid = false;
177 
178  delete mDataProvider;
179  delete mEditBuffer;
180  delete mJoinBuffer;
181  delete mExpressionFieldBuffer;
182  delete mLabeling;
183  delete mDiagramLayerSettings;
184  delete mDiagramRenderer;
185 
186  delete mActions;
187 
188  delete mRenderer;
189  delete mConditionalStyles;
190 
191  if ( mFeatureCounter )
192  mFeatureCounter->cancel();
193 }
194 
196 {
197  QgsVectorLayer *layer = new QgsVectorLayer( source(), name(), mProviderKey );
198  QgsMapLayer::clone( layer );
199 
200  QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
201  Q_FOREACH ( const QgsVectorLayerJoinInfo &join, joins )
202  {
203  // do not copy join information for auxiliary layer
204  if ( !auxiliaryLayer()
205  || ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() ) )
206  layer->addJoin( join );
207  }
208 
209  layer->setProviderEncoding( dataProvider()->encoding() );
211  layer->setMapTipTemplate( mapTipTemplate() );
212  layer->setReadOnly( isReadOnly() );
213  layer->selectByIds( selectedFeatureIds() );
218  layer->setOpacity( opacity() );
220 
221  Q_FOREACH ( const QgsAction &action, actions()->actions() )
222  {
223  layer->actions()->addAction( action );
224  }
225 
226  if ( renderer() )
227  {
228  layer->setRenderer( renderer()->clone() );
229  }
230 
231  if ( labeling() )
232  {
233  layer->setLabeling( labeling()->clone() );
234  }
235  layer->setSimplifyMethod( simplifyMethod() );
236 
237  if ( diagramRenderer() )
238  {
240  }
241 
242  if ( diagramLayerSettings() )
243  {
245  }
246 
247  for ( int i = 0; i < fields().count(); i++ )
248  {
249  layer->setFieldAlias( i, attributeAlias( i ) );
250  layer->setEditorWidgetSetup( i, editorWidgetSetup( i ) );
253 
254  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> constraints = fieldConstraintsAndStrength( i );
255  auto constraintIt = constraints.constBegin();
256  for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
257  {
258  layer->setFieldConstraint( i, constraintIt.key(), constraintIt.value() );
259  }
260 
262  {
263  layer->addExpressionField( expressionField( i ), fields().at( i ) );
264  }
265  }
266 
267  layer->setEditFormConfig( editFormConfig() );
268 
269  if ( auxiliaryLayer() )
270  layer->setAuxiliaryLayer( auxiliaryLayer()->clone( layer ) );
271 
272  return layer;
273 }
274 
276 {
277  if ( mDataProvider )
278  {
279  return mDataProvider->storageType();
280  }
281  return QString();
282 }
283 
284 
286 {
287  if ( mDataProvider )
288  {
289  return mDataProvider->capabilitiesString();
290  }
291  return QString();
292 }
293 
295 {
296  if ( mDataProvider )
297  {
298  return mDataProvider->dataComment();
299  }
300  return QString();
301 }
302 
303 
305 {
306  return mProviderKey;
307 }
308 
310 {
311  return crs();
312 }
313 
315 {
316  return name();
317 }
318 
320 {
321  if ( mDataProvider )
322  {
323  mDataProvider->reloadData();
324  updateFields();
325  }
326 }
327 
329 {
330  return new QgsVectorLayerRenderer( this, rendererContext );
331 }
332 
333 
334 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int m )
335 {
337  {
338  p.setPen( QColor( 50, 100, 120, 200 ) );
339  p.setBrush( QColor( 200, 200, 210, 120 ) );
340  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
341  }
342  else if ( type == QgsVectorLayer::Cross )
343  {
344  p.setPen( QColor( 255, 0, 0 ) );
345  p.drawLine( x - m, y + m, x + m, y - m );
346  p.drawLine( x - m, y - m, x + m, y + m );
347  }
348 }
349 
351 {
352  mSelectedFeatureIds.insert( fid );
353 
354  emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
355 }
356 
357 void QgsVectorLayer::select( const QgsFeatureIds &featureIds )
358 {
359  mSelectedFeatureIds.unite( featureIds );
360 
361  emit selectionChanged( featureIds, QgsFeatureIds(), false );
362 }
363 
365 {
366  mSelectedFeatureIds.remove( fid );
367 
368  emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
369 }
370 
371 void QgsVectorLayer::deselect( const QgsFeatureIds &featureIds )
372 {
373  mSelectedFeatureIds.subtract( featureIds );
374 
375  emit selectionChanged( QgsFeatureIds(), featureIds, false );
376 }
377 
379 {
380  // normalize the rectangle
381  rect.normalize();
382 
383  QgsFeatureIds newSelection;
384 
386  .setFilterRect( rect )
388  .setSubsetOfAttributes( QgsAttributeList() ) );
389 
390  QgsFeature feat;
391  while ( features.nextFeature( feat ) )
392  {
393  newSelection << feat.id();
394  }
395  features.close();
396 
397  selectByIds( newSelection, behavior );
398 }
399 
400 void QgsVectorLayer::selectByExpression( const QString &expression, QgsVectorLayer::SelectBehavior behavior )
401 {
402  QgsFeatureIds newSelection;
403 
405 
406  if ( behavior == SetSelection || behavior == AddToSelection )
407  {
409  .setExpressionContext( context )
412 
413  QgsFeatureIterator features = getFeatures( request );
414 
415  if ( behavior == AddToSelection )
416  {
417  newSelection = selectedFeatureIds();
418  }
419  QgsFeature feat;
420  while ( features.nextFeature( feat ) )
421  {
422  newSelection << feat.id();
423  }
424  features.close();
425  }
426  else if ( behavior == IntersectSelection || behavior == RemoveFromSelection )
427  {
428  QgsExpression exp( expression );
429  exp.prepare( &context );
430 
431  QgsFeatureIds oldSelection = selectedFeatureIds();
432  QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
433 
434  //refine request
435  if ( !exp.needsGeometry() )
437  request.setSubsetOfAttributes( exp.referencedColumns(), fields() );
438 
439  QgsFeatureIterator features = getFeatures( request );
440  QgsFeature feat;
441  while ( features.nextFeature( feat ) )
442  {
443  context.setFeature( feat );
444  bool matches = exp.evaluate( &context ).toBool();
445 
446  if ( matches && behavior == IntersectSelection )
447  {
448  newSelection << feat.id();
449  }
450  else if ( !matches && behavior == RemoveFromSelection )
451  {
452  newSelection << feat.id();
453  }
454  }
455  }
456 
457  selectByIds( newSelection );
458 }
459 
461 {
462  QgsFeatureIds newSelection;
463 
464  switch ( behavior )
465  {
466  case SetSelection:
467  newSelection = ids;
468  break;
469 
470  case AddToSelection:
471  newSelection = mSelectedFeatureIds + ids;
472  break;
473 
474  case RemoveFromSelection:
475  newSelection = mSelectedFeatureIds - ids;
476  break;
477 
478  case IntersectSelection:
479  newSelection = mSelectedFeatureIds.intersect( ids );
480  break;
481  }
482 
483  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
484  mSelectedFeatureIds = newSelection;
485 
486  emit selectionChanged( newSelection, deselectedFeatures, true );
487 }
488 
489 void QgsVectorLayer::modifySelection( const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds )
490 {
491  QgsFeatureIds intersectingIds = selectIds & deselectIds;
492  if ( !intersectingIds.isEmpty() )
493  {
494  QgsDebugMsg( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." );
495  }
496 
497  mSelectedFeatureIds -= deselectIds;
498  mSelectedFeatureIds += selectIds;
499 
500  emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
501 }
502 
504 {
506  ids.subtract( mSelectedFeatureIds );
507  selectByIds( ids );
508 }
509 
511 {
513 }
514 
516 {
517  // normalize the rectangle
518  rect.normalize();
519 
521  .setFilterRect( rect )
523  .setSubsetOfAttributes( QgsAttributeList() ) );
524 
525  QgsFeatureIds selectIds;
526  QgsFeatureIds deselectIds;
527 
528  QgsFeature fet;
529  while ( fit.nextFeature( fet ) )
530  {
531  if ( mSelectedFeatureIds.contains( fet.id() ) )
532  {
533  deselectIds << fet.id();
534  }
535  else
536  {
537  selectIds << fet.id();
538  }
539  }
540 
541  modifySelection( selectIds, deselectIds );
542 }
543 
545 {
546  if ( mSelectedFeatureIds.isEmpty() )
547  return;
548 
550 }
551 
553 {
554  return mDataProvider;
555 }
556 
558 {
559  return mDataProvider;
560 }
561 
562 void QgsVectorLayer::setProviderEncoding( const QString &encoding )
563 {
564  if ( mValid && mDataProvider && mDataProvider->encoding() != encoding )
565  {
566  mDataProvider->setEncoding( encoding );
567  updateFields();
568  }
569 }
570 
572 {
573  delete mDiagramRenderer;
574  mDiagramRenderer = r;
575  emit rendererChanged();
576  emit styleChanged();
577 }
578 
580 {
581  if ( mValid && mDataProvider )
582  {
583  return QgsWkbTypes::geometryType( mDataProvider->wkbType() );
584  }
585  else
586  {
587  QgsDebugMsg( "invalid layer or pointer to mDataProvider is null" );
588  }
589 
590  // We shouldn't get here, and if we have, other things are likely to
591  // go wrong. Code that uses the type() return value should be
592  // rewritten to cope with a value of Qgis::Unknown. To make this
593  // need known, the following message is printed every time we get
594  // here.
595  QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
596 
598 }
599 
601 {
602  return mWkbType;
603 }
604 
606 {
607  if ( !mValid || !isSpatial() || mSelectedFeatureIds.isEmpty() ) //no selected features
608  {
609  return QgsRectangle( 0, 0, 0, 0 );
610  }
611 
612  QgsRectangle r, retval;
613  retval.setMinimal();
614 
615  QgsFeature fet;
616  if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
617  {
619  .setFilterFids( mSelectedFeatureIds )
620  .setSubsetOfAttributes( QgsAttributeList() ) );
621 
622  while ( fit.nextFeature( fet ) )
623  {
624  if ( !fet.hasGeometry() )
625  continue;
626  r = fet.geometry().boundingBox();
627  retval.combineExtentWith( r );
628  }
629  }
630  else
631  {
633  .setSubsetOfAttributes( QgsAttributeList() ) );
634 
635  while ( fit.nextFeature( fet ) )
636  {
637  if ( mSelectedFeatureIds.contains( fet.id() ) )
638  {
639  if ( fet.hasGeometry() )
640  {
641  r = fet.geometry().boundingBox();
642  retval.combineExtentWith( r );
643  }
644  }
645  }
646  }
647 
648  if ( retval.width() == 0.0 || retval.height() == 0.0 )
649  {
650  // If all of the features are at the one point, buffer the
651  // rectangle a bit. If they are all at zero, do something a bit
652  // more crude.
653 
654  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
655  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
656  {
657  retval.set( -1.0, -1.0, 1.0, 1.0 );
658  }
659  }
660 
661  return retval;
662 }
663 
665 {
666  return static_cast< bool >( mLabeling );
667 }
668 
670 {
671  if ( !mDiagramRenderer || !mDiagramLayerSettings )
672  return false;
673 
674  QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
675  if ( !settingList.isEmpty() )
676  {
677  return settingList.at( 0 ).enabled;
678  }
679  return false;
680 }
681 
682 long QgsVectorLayer::featureCount( const QString &legendKey ) const
683 {
684  if ( !mSymbolFeatureCounted )
685  return -1;
686 
687  return mSymbolFeatureCountMap.value( legendKey );
688 }
689 
696 {
697  public:
698 
701  : mDialog( dialog )
702  {
703  }
704 
705  bool mustStop() const override
706  {
707  if ( mDialog->isVisible() )
708  {
709  // So that we get a chance of hitting the Abort button
710 #ifdef Q_OS_LINUX
711  // For some reason on Windows hasPendingEvents() always return true,
712  // but one iteration is actually enough on Windows to get good interactivity
713  // whereas on Linux we must allow for far more iterations.
714  // For safety limit the number of iterations
715  int nIters = 0;
716  while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
717 #endif
718  {
719  QCoreApplication::processEvents();
720  }
721  return mDialog->wasCanceled();
722  }
723  return false;
724  }
725 
726  private:
727  QProgressDialog *mDialog = nullptr;
728 };
729 
731 {
732  if ( mSymbolFeatureCounted || mFeatureCounter )
733  return mFeatureCounter;
734 
735  mSymbolFeatureCountMap.clear();
736 
737  if ( !mValid )
738  {
739  QgsDebugMsg( "invoked with invalid layer" );
740  return mFeatureCounter;
741  }
742  if ( !mDataProvider )
743  {
744  QgsDebugMsg( "invoked with null mDataProvider" );
745  return mFeatureCounter;
746  }
747  if ( !mRenderer )
748  {
749  QgsDebugMsg( "invoked with null mRenderer" );
750  return mFeatureCounter;
751  }
752 
753  if ( !mFeatureCounter )
754  {
755  mFeatureCounter = new QgsVectorLayerFeatureCounter( this );
756  connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted );
757  connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated );
758 
759  QgsApplication::taskManager()->addTask( mFeatureCounter );
760  }
761 
762  return mFeatureCounter;
763 }
764 
766 {
767  // do not update extent by default when trust project option is activated
768  if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.isNull() ) )
769  mValidExtent = false;
770 }
771 
773 {
775  mValidExtent = true;
776 }
777 
778 void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
779 {
780  if ( !mDefaultValueOnUpdateFields.isEmpty() )
781  {
782  if ( !feature.isValid() )
783  feature = getFeature( fid );
784 
785  int size = mFields.size();
786  for ( int idx : qgis::as_const( mDefaultValueOnUpdateFields ) )
787  {
788  if ( idx < 0 || idx >= size )
789  continue;
790 
791  feature.setAttribute( idx, defaultValue( idx, feature ) );
792  updateFeature( feature, true );
793  }
794  }
795 }
796 
798 {
799  QgsRectangle rect;
800  rect.setMinimal();
801 
802  if ( !isSpatial() )
803  return rect;
804 
805 
806  if ( !mValidExtent && mLazyExtent && mDataProvider && !mDataProvider->hasMetadata() && mReadExtentFromXml && !mXmlExtent.isNull() )
807  {
808  mExtent = mXmlExtent;
809  mValidExtent = true;
810  mLazyExtent = false;
811  }
812 
813  if ( !mValidExtent && mLazyExtent && mDataProvider )
814  {
815  // get the extent
816  QgsRectangle mbr = mDataProvider->extent();
817 
818  // show the extent
819  QgsDebugMsg( "Extent of layer: " + mbr.toString() );
820  // store the extent
821  mValidExtent = true;
822  mExtent = mbr;
823 
824  mLazyExtent = false;
825  }
826 
827  if ( mValidExtent )
828  return QgsMapLayer::extent();
829 
830  if ( !mValid || !mDataProvider )
831  {
832  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
833  return rect;
834  }
835 
836  if ( !mEditBuffer ||
837  ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() ) ||
838  QgsDataSourceUri( mDataProvider->dataSourceUri() ).useEstimatedMetadata() )
839  {
840  mDataProvider->updateExtents();
841 
842  // get the extent of the layer from the provider
843  // but only when there are some features already
844  if ( mDataProvider->featureCount() != 0 )
845  {
846  QgsRectangle r = mDataProvider->extent();
847  rect.combineExtentWith( r );
848  }
849 
850  if ( mEditBuffer )
851  {
852  for ( QgsFeatureMap::const_iterator it = mEditBuffer->mAddedFeatures.constBegin(); it != mEditBuffer->mAddedFeatures.constEnd(); ++it )
853  {
854  if ( it->hasGeometry() )
855  {
856  QgsRectangle r = it->geometry().boundingBox();
857  rect.combineExtentWith( r );
858  }
859  }
860  }
861  }
862  else
863  {
865  .setSubsetOfAttributes( QgsAttributeList() ) );
866 
867  QgsFeature fet;
868  while ( fit.nextFeature( fet ) )
869  {
870  if ( fet.hasGeometry() && fet.geometry().type() != QgsWkbTypes::UnknownGeometry )
871  {
872  QgsRectangle bb = fet.geometry().boundingBox();
873  rect.combineExtentWith( bb );
874  }
875  }
876  }
877 
878  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
879  {
880  // special case when there are no features in provider nor any added
881  rect = QgsRectangle(); // use rectangle with zero coordinates
882  }
883 
884  mValidExtent = true;
885  mExtent = rect;
886 
887  // Send this (hopefully) up the chain to the map canvas
888  emit recalculateExtents();
889 
890  return rect;
891 }
892 
894 {
895  return extent();
896 }
897 
899 {
900  if ( !mValid || !mDataProvider )
901  {
902  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
903  return QString();
904  }
905  return mDataProvider->subsetString();
906 }
907 
908 bool QgsVectorLayer::setSubsetString( const QString &subset )
909 {
910  if ( !mValid || !mDataProvider )
911  {
912  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
913  return false;
914  }
915 
916  bool res = mDataProvider->setSubsetString( subset );
917 
918  // get the updated data source string from the provider
919  mDataSource = mDataProvider->dataSourceUri();
920  updateExtents();
921  updateFields();
922 
923  if ( res )
924  emit repaintRequested();
925 
926  return res;
927 }
928 
930 {
931  if ( mValid && mDataProvider && !mEditBuffer && ( isSpatial() && geometryType() != QgsWkbTypes::PointGeometry ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
932  {
933  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
934 
935  // check maximum scale at which generalisation should be carried out
936  return !( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale );
937  }
938  return false;
939 }
940 
942 {
943  return mConditionalStyles;
944 }
945 
947 {
948  if ( !mValid || !mDataProvider )
949  return QgsFeatureIterator();
950 
951  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
952 }
953 
954 bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
955 {
956  if ( !mValid || !mEditBuffer || !mDataProvider )
957  return false;
958 
959  bool success = mEditBuffer->addFeature( feature );
960 
961  if ( success )
962  {
963  updateExtents();
964 
965  if ( mJoinBuffer->containsJoins() )
966  success = mJoinBuffer->addFeature( feature );
967  }
968 
969  return success;
970 }
971 
972 bool QgsVectorLayer::updateFeature( const QgsFeature &updatedFeature, bool skipDefaultValues )
973 {
974  bool hasChanged = false;
975  bool hasError = false;
976 
977  QgsFeature currentFeature = getFeature( updatedFeature.id() );
978  if ( currentFeature.isValid() )
979  {
980  QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( updatedFeature.id() ) );
981 
982  if ( updatedFeature.hasGeometry() && currentFeature.hasGeometry() && !updatedFeature.geometry().isGeosEqual( currentFeature.geometry() ) )
983  {
984  if ( changeGeometry( updatedFeature.id(), updatedFeature.geometry(), true ) )
985  {
986  hasChanged = true;
987  }
988  else
989  {
990  QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( updatedFeature.id() ) );
991  }
992  }
993 
994  QgsAttributes fa = updatedFeature.attributes();
995  QgsAttributes ca = currentFeature.attributes();
996 
997  for ( int attr = 0; attr < fa.count(); ++attr )
998  {
999  if ( fa.at( attr ) != ca.at( attr ) )
1000  {
1001  if ( changeAttributeValue( updatedFeature.id(), attr, fa.at( attr ), ca.at( attr ), true ) )
1002  {
1003  hasChanged = true;
1004  }
1005  else
1006  {
1007  QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.id() ) );
1008  hasError = true;
1009  }
1010  }
1011  }
1012  }
1013 
1014  if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() && !skipDefaultValues )
1015  updateDefaultValues( updatedFeature.id(), updatedFeature );
1016 
1017  return !hasError;
1018 }
1019 
1020 
1021 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1022 {
1023  if ( !mValid || !mEditBuffer || !mDataProvider )
1024  return false;
1025 
1026  QgsVectorLayerEditUtils utils( this );
1027  bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
1028  if ( result )
1029  updateExtents();
1030  return result;
1031 }
1032 
1033 
1034 bool QgsVectorLayer::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
1035 {
1036  if ( !mValid || !mEditBuffer || !mDataProvider )
1037  return false;
1038 
1039  QgsVectorLayerEditUtils utils( this );
1040  bool result = utils.insertVertex( point, atFeatureId, beforeVertex );
1041  if ( result )
1042  updateExtents();
1043  return result;
1044 }
1045 
1046 
1047 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1048 {
1049  if ( !mValid || !mEditBuffer || !mDataProvider )
1050  return false;
1051 
1052  QgsVectorLayerEditUtils utils( this );
1053  bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
1054 
1055  if ( result )
1056  updateExtents();
1057  return result;
1058 }
1059 
1060 bool QgsVectorLayer::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
1061 {
1062  if ( !mValid || !mEditBuffer || !mDataProvider )
1063  return false;
1064 
1065  QgsVectorLayerEditUtils utils( this );
1066  bool result = utils.moveVertex( p, atFeatureId, atVertex );
1067 
1068  if ( result )
1069  updateExtents();
1070  return result;
1071 }
1072 
1074 {
1075  if ( !mValid || !mEditBuffer || !mDataProvider )
1077 
1078  QgsVectorLayerEditUtils utils( this );
1079  EditResult result = utils.deleteVertex( featureId, vertex );
1080 
1081  if ( result == Success )
1082  updateExtents();
1083  return result;
1084 }
1085 
1086 
1088 {
1089  if ( !mValid || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1090  {
1091  return false;
1092  }
1093 
1094  if ( !isEditable() )
1095  {
1096  return false;
1097  }
1098 
1099  int deleted = 0;
1100  int count = mSelectedFeatureIds.size();
1101  // Make a copy since deleteFeature modifies mSelectedFeatureIds
1102  QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1103  Q_FOREACH ( QgsFeatureId fid, selectedFeatures )
1104  {
1105  deleted += deleteFeature( fid ); // removes from selection
1106  }
1107 
1108  triggerRepaint();
1109  updateExtents();
1110 
1111  if ( deletedCount )
1112  {
1113  *deletedCount = deleted;
1114  }
1115 
1116  return deleted == count;
1117 }
1118 
1119 int QgsVectorLayer::addRing( const QVector<QgsPointXY> &ring, QgsFeatureId *featureId )
1120 {
1121  if ( !mValid || !mEditBuffer || !mDataProvider )
1122  return 6;
1123 
1124  QgsVectorLayerEditUtils utils( this );
1125  int result = 5;
1126 
1127  //first try with selected features
1128  if ( !mSelectedFeatureIds.isEmpty() )
1129  {
1130  result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1131  }
1132 
1133  if ( result != 0 )
1134  {
1135  //try with all intersecting features
1136  result = utils.addRing( ring, QgsFeatureIds(), featureId );
1137  }
1138 
1139  return result;
1140 }
1141 
1143 {
1144  if ( !mValid || !mEditBuffer || !mDataProvider )
1145  {
1146  delete ring;
1147  return 6;
1148  }
1149 
1150  if ( !ring )
1151  {
1152  return 1;
1153  }
1154 
1155  if ( !ring->isClosed() )
1156  {
1157  delete ring;
1158  return 2;
1159  }
1160 
1161  QgsVectorLayerEditUtils utils( this );
1162  int result = 5;
1163 
1164  //first try with selected features
1165  if ( !mSelectedFeatureIds.isEmpty() )
1166  {
1167  result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), mSelectedFeatureIds, featureId );
1168  }
1169 
1170  if ( result != 0 )
1171  {
1172  //try with all intersecting features
1173  result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), QgsFeatureIds(), featureId );
1174  }
1175 
1176  delete ring;
1177  return result;
1178 }
1179 
1180 int QgsVectorLayer::addPart( const QList<QgsPointXY> &points )
1181 {
1182  if ( !mValid || !mEditBuffer || !mDataProvider )
1183  return 7;
1184 
1185  //number of selected features must be 1
1186 
1187  if ( mSelectedFeatureIds.empty() )
1188  {
1189  QgsDebugMsg( "Number of selected features <1" );
1190  return 4;
1191  }
1192  else if ( mSelectedFeatureIds.size() > 1 )
1193  {
1194  QgsDebugMsg( "Number of selected features >1" );
1195  return 5;
1196  }
1197 
1198  QgsVectorLayerEditUtils utils( this );
1199  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1200 
1201  if ( result == 0 )
1202  updateExtents();
1203  return result;
1204 }
1205 
1207 {
1208  if ( !mValid || !mEditBuffer || !mDataProvider )
1209  return 7;
1210 
1211  //number of selected features must be 1
1212 
1213  if ( mSelectedFeatureIds.empty() )
1214  {
1215  QgsDebugMsg( "Number of selected features <1" );
1216  return 4;
1217  }
1218  else if ( mSelectedFeatureIds.size() > 1 )
1219  {
1220  QgsDebugMsg( "Number of selected features >1" );
1221  return 5;
1222  }
1223 
1224  QgsVectorLayerEditUtils utils( this );
1225  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1226 
1227  if ( result == 0 )
1228  updateExtents();
1229  return result;
1230 }
1231 
1233 {
1234  if ( !mValid || !mEditBuffer || !mDataProvider )
1235  return 7;
1236 
1237  //number of selected features must be 1
1238 
1239  if ( mSelectedFeatureIds.empty() )
1240  {
1241  QgsDebugMsg( "Number of selected features <1" );
1242  return 4;
1243  }
1244  else if ( mSelectedFeatureIds.size() > 1 )
1245  {
1246  QgsDebugMsg( "Number of selected features >1" );
1247  return 5;
1248  }
1249 
1250  QgsVectorLayerEditUtils utils( this );
1251  int result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1252 
1253  if ( result == 0 )
1254  updateExtents();
1255  return result;
1256 }
1257 
1258 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1259 {
1260  if ( !mValid || !mEditBuffer || !mDataProvider )
1261  return -1;
1262 
1263  QgsVectorLayerEditUtils utils( this );
1264  int result = utils.translateFeature( featureId, dx, dy );
1265 
1266  if ( result == 0 )
1267  updateExtents();
1268  return result;
1269 }
1270 
1271 int QgsVectorLayer::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1272 {
1273  if ( !mValid || !mEditBuffer || !mDataProvider )
1274  return -1;
1275 
1276  QgsVectorLayerEditUtils utils( this );
1277  return utils.splitParts( splitLine, topologicalEditing );
1278 }
1279 
1280 int QgsVectorLayer::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1281 {
1282  if ( !mValid || !mEditBuffer || !mDataProvider )
1283  return -1;
1284 
1285  QgsVectorLayerEditUtils utils( this );
1286  return utils.splitFeatures( splitLine, topologicalEditing );
1287 }
1288 
1290 {
1291  if ( !mValid || !mEditBuffer || !mDataProvider )
1292  return -1;
1293 
1294  QgsVectorLayerEditUtils utils( this );
1295  return utils.addTopologicalPoints( geom );
1296 }
1297 
1299 {
1300  if ( !mValid || !mEditBuffer || !mDataProvider )
1301  return -1;
1302 
1303  QgsVectorLayerEditUtils utils( this );
1304  return utils.addTopologicalPoints( p );
1305 }
1306 
1308 {
1309  if ( mLabeling == labeling )
1310  return;
1311 
1312  delete mLabeling;
1313  mLabeling = labeling;
1314 }
1315 
1317 {
1318  if ( !mValid || !mDataProvider )
1319  {
1320  return false;
1321  }
1322 
1323  // allow editing if provider supports any of the capabilities
1324  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1325  {
1326  return false;
1327  }
1328 
1329  if ( mReadOnly )
1330  {
1331  return false;
1332  }
1333 
1334  if ( mEditBuffer )
1335  {
1336  // editing already underway
1337  return false;
1338  }
1339 
1340  emit beforeEditingStarted();
1341 
1342  mDataProvider->enterUpdateMode();
1343 
1344  if ( mDataProvider->transaction() )
1345  {
1346  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1347 
1348  connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
1349  }
1350  else
1351  {
1352  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1353  }
1354  // forward signals
1355  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
1356  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
1357  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1359  connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
1370 
1371  updateFields();
1372 
1373  emit editingStarted();
1374 
1375  return true;
1376 }
1377 
1378 bool QgsVectorLayer::readXml( const QDomNode &layer_node, const QgsReadWriteContext &context )
1379 {
1380  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
1381 
1382  //process provider key
1383  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1384 
1385  if ( pkeyNode.isNull() )
1386  {
1387  mProviderKey.clear();
1388  }
1389  else
1390  {
1391  QDomElement pkeyElt = pkeyNode.toElement();
1392  mProviderKey = pkeyElt.text();
1393  }
1394 
1395  // determine type of vector layer
1396  if ( !mProviderKey.isNull() )
1397  {
1398  // if the provider string isn't empty, then we successfully
1399  // got the stored provider
1400  }
1401  else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
1402  {
1403  mProviderKey = QStringLiteral( "postgres" );
1404  }
1405  else
1406  {
1407  mProviderKey = QStringLiteral( "ogr" );
1408  }
1409 
1410  if ( !setDataProvider( mProviderKey ) )
1411  {
1412  return false;
1413  }
1414 
1415  QDomElement pkeyElem = pkeyNode.toElement();
1416  if ( !pkeyElem.isNull() )
1417  {
1418  QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1419  if ( !encodingString.isEmpty() )
1420  {
1421  mDataProvider->setEncoding( encodingString );
1422  }
1423  }
1424 
1425  // load vector joins - does not resolve references to layers yet
1426  mJoinBuffer->readXml( layer_node );
1427 
1428  updateFields();
1429 
1430  QString errorMsg;
1431  if ( !readSymbology( layer_node, errorMsg, context ) )
1432  {
1433  return false;
1434  }
1435 
1436  readStyleManager( layer_node );
1437 
1438  QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1439  QDomNodeList depsNodes = depsNode.childNodes();
1440  QSet<QgsMapLayerDependency> sources;
1441  for ( int i = 0; i < depsNodes.count(); i++ )
1442  {
1443  QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1444  sources << QgsMapLayerDependency( source );
1445  }
1446  setDependencies( sources );
1447 
1449 
1450  // read extent
1451  if ( mReadExtentFromXml )
1452  {
1453  QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1454  if ( !extentNode.isNull() )
1455  {
1456  mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1457  }
1458  }
1459 
1460  // auxiliary layer
1461  const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
1462  const QDomElement asElem = asNode.toElement();
1463  if ( !asElem.isNull() )
1464  {
1465  mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
1466  }
1467 
1468  return mValid; // should be true if read successfully
1469 
1470 } // void QgsVectorLayer::readXml
1471 
1472 
1473 void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag )
1474 {
1476 
1477  mDataSource = dataSource;
1478  setName( baseName );
1479  setDataProvider( provider );
1480 
1481  if ( !mValid )
1482  return;
1483 
1484  // Always set crs
1486 
1487  // reset style if loading default style, style is missing, or geometry type has changed
1488  if ( !renderer() || !legend() || geomType != geometryType() || loadDefaultStyleFlag )
1489  {
1490  // check if there is a default style / propertysheet defined
1491  // for this layer and if so apply it
1492  bool defaultLoadedFlag = false;
1493  if ( loadDefaultStyleFlag )
1494  {
1495  loadDefaultStyle( defaultLoadedFlag );
1496  }
1497 
1498  // if the default style failed to load or was disabled use some very basic defaults
1499  if ( !defaultLoadedFlag && isSpatial() )
1500  {
1501  // add single symbol renderer
1503  }
1504 
1506  }
1507 
1508  emit repaintRequested();
1509 }
1510 
1511 
1512 bool QgsVectorLayer::setDataProvider( QString const &provider )
1513 {
1514  mProviderKey = provider; // XXX is this necessary? Usually already set
1515 
1516  // primary key unicity is tested at construction time, so it has to be set
1517  // before initializing postgres provider
1518  QString checkUnicityKey = QStringLiteral( "checkPrimaryKeyUnicity" );
1519  QString dataSource = mDataSource;
1520  if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
1521  {
1522  QgsDataSourceUri uri( dataSource );
1523 
1524  if ( uri.hasParam( checkUnicityKey ) )
1525  uri.removeParam( checkUnicityKey );
1526 
1527  uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
1528  dataSource = uri.uri( false );
1529  }
1530 
1531  delete mDataProvider;
1532  mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource ) );
1533  if ( !mDataProvider )
1534  {
1535  QgsDebugMsg( " unable to get data provider" );
1536  return false;
1537  }
1538 
1539  connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1540 
1541  QgsDebugMsgLevel( "Instantiated the data provider plugin", 4 );
1542 
1543  mValid = mDataProvider->isValid();
1544  if ( !mValid )
1545  {
1546  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1547  return false;
1548  }
1549 
1550  // TODO: Check if the provider has the capability to send fullExtentCalculated
1551  connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
1552 
1553  // get and store the feature type
1554  mWkbType = mDataProvider->wkbType();
1555 
1556  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1557  updateFields();
1558 
1559  if ( mProviderKey == QLatin1String( "postgres" ) )
1560  {
1561  QgsDebugMsg( "Beautifying layer name " + name() );
1562 
1563  // adjust the display name for postgres layers
1564  QRegExp reg( R"lit("[^"]+"\."([^"] + )"( \([^)]+\))?)lit" );
1565  if ( reg.indexIn( name() ) >= 0 )
1566  {
1567  QStringList stuff = reg.capturedTexts();
1568  QString lName = stuff[1];
1569 
1570  const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
1571 
1572  QMap<QString, QgsMapLayer *>::const_iterator it;
1573  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1574  ;
1575 
1576  if ( it != layers.constEnd() && stuff.size() > 2 )
1577  {
1578  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1579  }
1580 
1581  if ( !lName.isEmpty() )
1582  setName( lName );
1583  }
1584 
1585  QgsDebugMsg( "Beautified layer name " + name() );
1586 
1587  // deal with unnecessary schema qualification to make v.in.ogr happy
1588  // and remove unnecessary key
1589  QgsDataSourceUri dataProviderUri( mDataProvider->dataSourceUri() );
1590  if ( dataProviderUri.hasParam( checkUnicityKey ) )
1591  dataProviderUri.removeParam( checkUnicityKey );
1592  mDataSource = dataProviderUri.uri( false );
1593  }
1594  else if ( mProviderKey == QLatin1String( "osm" ) )
1595  {
1596  // make sure that the "observer" has been removed from URI to avoid crashes
1597  mDataSource = mDataProvider->dataSourceUri();
1598  }
1599  else if ( provider == QLatin1String( "ogr" ) )
1600  {
1601  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1602  mDataSource = mDataProvider->dataSourceUri();
1603  if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1604  mDataSource.chop( 10 );
1605  }
1606  else if ( provider == QStringLiteral( "memory" ) )
1607  {
1608  // required so that source differs between memory layers
1609  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1610  }
1611 
1612  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::dataChanged );
1613  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
1614 
1615  return true;
1616 } // QgsVectorLayer:: setDataProvider
1617 
1618 
1619 
1620 
1621 /* virtual */
1622 bool QgsVectorLayer::writeXml( QDomNode &layer_node,
1623  QDomDocument &document,
1624  const QgsReadWriteContext &context ) const
1625 {
1626  // first get the layer element so that we can append the type attribute
1627 
1628  QDomElement mapLayerNode = layer_node.toElement();
1629 
1630  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1631  {
1632  QgsDebugMsg( "can't find <maplayer>" );
1633  return false;
1634  }
1635 
1636  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "vector" ) );
1637 
1638  // set the geometry type
1639  mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1640 
1641  // add provider node
1642  if ( mDataProvider )
1643  {
1644  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1645  provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1646  QDomText providerText = document.createTextNode( providerType() );
1647  provider.appendChild( providerText );
1648  layer_node.appendChild( provider );
1649  }
1650 
1651  //save joins
1652  mJoinBuffer->writeXml( layer_node, document );
1653 
1654  // dependencies
1655  QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1656  Q_FOREACH ( const QgsMapLayerDependency &dep, dependencies() )
1657  {
1659  continue;
1660  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1661  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1662  dependenciesElement.appendChild( depElem );
1663  }
1664  layer_node.appendChild( dependenciesElement );
1665 
1666  // change dependencies
1667  QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1668  Q_FOREACH ( const QgsMapLayerDependency &dep, dependencies() )
1669  {
1671  continue;
1672  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1673  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1674  dataDependenciesElement.appendChild( depElem );
1675  }
1676  layer_node.appendChild( dataDependenciesElement );
1677 
1678  // save expression fields
1679  mExpressionFieldBuffer->writeXml( layer_node, document );
1680 
1681  writeStyleManager( layer_node, document );
1682 
1683  // auxiliary layer
1684  QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
1685  if ( mAuxiliaryLayer )
1686  {
1687  const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
1688  asElem.setAttribute( QStringLiteral( "key" ), pkField );
1689  }
1690  layer_node.appendChild( asElem );
1691 
1692  // renderer specific settings
1693  QString errorMsg;
1694  return writeSymbology( layer_node, document, errorMsg, context );
1695 } // bool QgsVectorLayer::writeXml
1696 
1697 
1699 {
1700  QgsMapLayer::resolveReferences( project );
1701  mJoinBuffer->resolveReferences( project );
1702 }
1703 
1704 
1705 bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage, const QgsReadWriteContext &context )
1706 {
1707  if ( !mExpressionFieldBuffer )
1708  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1709  mExpressionFieldBuffer->readXml( layerNode );
1710 
1711  updateFields();
1712 
1713  readStyle( layerNode, errorMessage, context );
1714 
1715  mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
1716  mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
1717 
1718  QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
1719 
1720  // Try to migrate pre QGIS 3.0 display field property
1721  if ( mFields.lookupField( displayField ) < 0 )
1722  {
1723  // if it's not a field, it's a maptip
1724  if ( mMapTipTemplate.isEmpty() )
1725  mMapTipTemplate = displayField;
1726  }
1727  else
1728  {
1729  if ( mDisplayExpression.isEmpty() )
1730  mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
1731  }
1732 
1733  // process the attribute actions
1734  mActions->readXml( layerNode );
1735 
1736  mAttributeAliasMap.clear();
1737  QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
1738  if ( !aliasesNode.isNull() )
1739  {
1740  QDomElement aliasElem;
1741 
1742  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
1743  for ( int i = 0; i < aliasNodeList.size(); ++i )
1744  {
1745  aliasElem = aliasNodeList.at( i ).toElement();
1746 
1747  QString field;
1748  if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
1749  {
1750  field = aliasElem.attribute( QStringLiteral( "field" ) );
1751  }
1752  else
1753  {
1754  int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
1755 
1756  if ( index >= 0 && index < fields().count() )
1757  field = fields().at( index ).name();
1758  }
1759 
1760  mAttributeAliasMap.insert( field, aliasElem.attribute( QStringLiteral( "name" ) ) );
1761  }
1762  }
1763 
1764  // default expressions
1765  mDefaultExpressionMap.clear();
1766  QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
1767  if ( !defaultsNode.isNull() )
1768  {
1769  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
1770  for ( int i = 0; i < defaultNodeList.size(); ++i )
1771  {
1772  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
1773 
1774  QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
1775  QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
1776  bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
1777  if ( field.isEmpty() || expression.isEmpty() )
1778  continue;
1779 
1780  mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
1781  }
1782  }
1783 
1784  // constraints
1785  mFieldConstraints.clear();
1786  mFieldConstraintStrength.clear();
1787  QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
1788  if ( !constraintsNode.isNull() )
1789  {
1790  QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
1791  for ( int i = 0; i < constraintNodeList.size(); ++i )
1792  {
1793  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
1794 
1795  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
1796  int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
1797  if ( field.isEmpty() || constraints == 0 )
1798  continue;
1799 
1800  mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
1801 
1802  int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
1803  int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
1804  int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
1805 
1806  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
1807  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
1808  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
1809  }
1810  }
1811  mFieldConstraintExpressions.clear();
1812  QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
1813  if ( !constraintExpressionsNode.isNull() )
1814  {
1815  QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
1816  for ( int i = 0; i < constraintNodeList.size(); ++i )
1817  {
1818  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
1819 
1820  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
1821  QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
1822  QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
1823  if ( field.isEmpty() || exp.isEmpty() )
1824  continue;
1825 
1826  mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
1827  }
1828  }
1829 
1830  updateFields();
1831 
1832  //Attributes excluded from WMS and WFS
1833  mExcludeAttributesWMS.clear();
1834  QDomNode excludeWMSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWMS" ) );
1835  if ( !excludeWMSNode.isNull() )
1836  {
1837  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
1838  for ( int i = 0; i < attributeNodeList.size(); ++i )
1839  {
1840  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1841  }
1842  }
1843 
1844  mExcludeAttributesWFS.clear();
1845  QDomNode excludeWFSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWFS" ) );
1846  if ( !excludeWFSNode.isNull() )
1847  {
1848  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
1849  for ( int i = 0; i < attributeNodeList.size(); ++i )
1850  {
1851  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1852  }
1853  }
1854 
1855  // Load editor widget configuration
1856  QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
1857 
1858  QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
1859 
1860  for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
1861  {
1862  const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
1863  const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
1864 
1865  QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
1866 
1867  const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
1868  const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
1869  const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
1870  QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
1871  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
1872  mFieldWidgetSetups[fieldName] = setup;
1873  }
1874 
1875  mEditFormConfig.readXml( layerNode, context );
1876 
1877  mAttributeTableConfig.readXml( layerNode );
1878 
1879  mConditionalStyles->readXml( layerNode, context );
1880 
1881  readCustomProperties( layerNode, QStringLiteral( "variable" ) );
1882 
1883  QDomElement mapLayerNode = layerNode.toElement();
1884  if ( mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
1885  mReadOnly = true;
1886 
1887  updateFields();
1888 
1889  return true;
1890 }
1891 
1892 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context )
1893 {
1894  bool result = true;
1895  emit readCustomSymbology( node.toElement(), errorMessage );
1896 
1897  if ( isSpatial() )
1898  {
1899  // try renderer v2 first
1900  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1901  if ( !rendererElement.isNull() )
1902  {
1903  QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
1904  if ( r )
1905  {
1906  setRenderer( r );
1907  }
1908  else
1909  {
1910  result = false;
1911  }
1912  }
1913 
1914  // make sure layer has a renderer - if none exists, fallback to a default renderer
1915  if ( !renderer() )
1916  {
1918  }
1919 
1920  // read labeling definition
1921  QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
1923  if ( labelingElement.isNull() ||
1924  ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
1925  {
1926  // make sure we have custom properties for labeling for 2.x projects
1927  // (custom properties should be already loaded when reading the whole layer from XML,
1928  // but when reading style, custom properties are not read)
1929  readCustomProperties( node, QStringLiteral( "labeling" ) );
1930 
1931  // support for pre-QGIS 3 labeling configurations written in custom properties
1932  labeling = readLabelingFromCustomProperties();
1933  }
1934  else
1935  {
1936  labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
1937  }
1938  setLabeling( labeling );
1939 
1940  // get and set the blend mode if it exists
1941  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1942  if ( !blendModeNode.isNull() )
1943  {
1944  QDomElement e = blendModeNode.toElement();
1945  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1946  }
1947 
1948  // get and set the feature blend mode if it exists
1949  QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
1950  if ( !featureBlendModeNode.isNull() )
1951  {
1952  QDomElement e = featureBlendModeNode.toElement();
1953  setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1954  }
1955 
1956  // get and set the layer transparency if it exists
1957  QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
1958  if ( !layerTransparencyNode.isNull() )
1959  {
1960  QDomElement e = layerTransparencyNode.toElement();
1961  setOpacity( 1.0 - e.text().toInt() / 100.0 );
1962  }
1963  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1964  if ( !layerOpacityNode.isNull() )
1965  {
1966  QDomElement e = layerOpacityNode.toElement();
1967  setOpacity( e.text().toDouble() );
1968  }
1969 
1970  QDomElement e = node.toElement();
1971 
1972  // get the simplification drawing settings
1973  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
1974  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
1975  mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
1976  mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
1977  mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
1978 
1979  //diagram renderer and diagram layer settings
1980  delete mDiagramRenderer;
1981  mDiagramRenderer = nullptr;
1982  QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
1983  if ( !singleCatDiagramElem.isNull() )
1984  {
1985  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1986  mDiagramRenderer->readXml( singleCatDiagramElem, context );
1987  }
1988  QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
1989  if ( !linearDiagramElem.isNull() )
1990  {
1991  if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
1992  {
1993  // fix project from before QGIS 3.0
1994  int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
1995  if ( idx >= 0 && idx < mFields.count() )
1996  linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
1997  }
1998 
1999  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2000  mDiagramRenderer->readXml( linearDiagramElem, context );
2001  }
2002 
2003  if ( mDiagramRenderer )
2004  {
2005  QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
2006  if ( !diagramSettingsElem.isNull() )
2007  {
2008  bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
2009  bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
2010  bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
2011  if ( oldXPos || oldYPos || oldShow )
2012  {
2013  // fix project from before QGIS 3.0
2015  if ( oldXPos )
2016  {
2017  int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
2018  if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
2019  ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
2020  }
2021  if ( oldYPos )
2022  {
2023  int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
2024  if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
2025  ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
2026  }
2027  if ( oldShow )
2028  {
2029  int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
2030  if ( showColumn >= 0 && showColumn < mFields.count() )
2031  ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
2032  }
2033  QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
2035  {
2036  { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
2037  { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
2038  { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
2039  };
2040  ddp.writeXml( propertiesElem, defs );
2041  diagramSettingsElem.appendChild( propertiesElem );
2042  }
2043 
2044  delete mDiagramLayerSettings;
2045  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2046  mDiagramLayerSettings->readXml( diagramSettingsElem );
2047  }
2048  }
2049  }
2050  return result;
2051 }
2052 
2053 bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
2054 {
2055  ( void )writeStyle( node, doc, errorMessage, context );
2056 
2057  QDomElement fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2058  node.appendChild( fieldConfigurationElement );
2059 
2060  int index = 0;
2061  Q_FOREACH ( const QgsField &field, mFields )
2062  {
2063 
2064  QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2065  fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2066 
2067  fieldConfigurationElement.appendChild( fieldElement );
2068 
2069  QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
2070 
2071  // TODO : wrap this part in an if to only save if it was user-modified
2072  QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2073  fieldElement.appendChild( editWidgetElement );
2074  editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2075  QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2076 
2077  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2078  editWidgetElement.appendChild( editWidgetConfigElement );
2079  // END TODO : wrap this part in an if to only save if it was user-modified
2080 
2081  ++index;
2082  }
2083 
2084  //attribute aliases
2085  QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2086  Q_FOREACH ( const QgsField &field, mFields )
2087  {
2088  QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2089  aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2090  aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2091  aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2092  aliasElem.appendChild( aliasEntryElem );
2093  }
2094  node.appendChild( aliasElem );
2095 
2096  //exclude attributes WMS
2097  QDomElement excludeWMSElem = doc.createElement( QStringLiteral( "excludeAttributesWMS" ) );
2098  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2099  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2100  {
2101  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2102  QDomText attrText = doc.createTextNode( *attWMSIt );
2103  attrElem.appendChild( attrText );
2104  excludeWMSElem.appendChild( attrElem );
2105  }
2106  node.appendChild( excludeWMSElem );
2107 
2108  //exclude attributes WFS
2109  QDomElement excludeWFSElem = doc.createElement( QStringLiteral( "excludeAttributesWFS" ) );
2110  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2111  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2112  {
2113  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2114  QDomText attrText = doc.createTextNode( *attWFSIt );
2115  attrElem.appendChild( attrText );
2116  excludeWFSElem.appendChild( attrElem );
2117  }
2118  node.appendChild( excludeWFSElem );
2119 
2120  //default expressions
2121  QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2122  Q_FOREACH ( const QgsField &field, mFields )
2123  {
2124  QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2125  defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2126  defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
2127  defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2128  defaultsElem.appendChild( defaultElem );
2129  }
2130  node.appendChild( defaultsElem );
2131 
2132  // constraints
2133  QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2134  Q_FOREACH ( const QgsField &field, mFields )
2135  {
2136  QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2137  constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2138  constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2139  constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2140  constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2141  constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2142  constraintsElem.appendChild( constraintElem );
2143  }
2144  node.appendChild( constraintsElem );
2145 
2146  // constraint expressions
2147  QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2148  Q_FOREACH ( const QgsField &field, mFields )
2149  {
2150  QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2151  constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2152  constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2153  constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2154  constraintExpressionsElem.appendChild( constraintExpressionElem );
2155  }
2156  node.appendChild( constraintExpressionsElem );
2157 
2158  // add attribute actions
2159  mActions->writeXml( node );
2160  mAttributeTableConfig.writeXml( node );
2161  mEditFormConfig.writeXml( node, context );
2162  mConditionalStyles->writeXml( node, doc, context );
2163 
2164  // save expression fields
2165  if ( !mExpressionFieldBuffer )
2166  {
2167  // can happen when saving style on a invalid layer
2169  dummy.writeXml( node, doc );
2170  }
2171  else
2172  mExpressionFieldBuffer->writeXml( node, doc );
2173 
2174  // save readonly state
2175  node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2176 
2177  // save preview expression
2178  QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2179  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2180  prevExpElem.appendChild( prevExpText );
2181  node.appendChild( prevExpElem );
2182 
2183  // save map tip
2184  QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2185  QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2186  mapTipElem.appendChild( mapTipText );
2187  node.toElement().appendChild( mapTipElem );
2188 
2189  return true;
2190 }
2191 
2192 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
2193 {
2194  QDomElement mapLayerNode = node.toElement();
2195 
2196  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2197 
2198  if ( isSpatial() )
2199  {
2200  if ( mRenderer )
2201  {
2202  QDomElement rendererElement = mRenderer->save( doc, context );
2203  node.appendChild( rendererElement );
2204  }
2205 
2206  if ( mLabeling )
2207  {
2208  QDomElement labelingElement = mLabeling->save( doc, context );
2209  node.appendChild( labelingElement );
2210  }
2211 
2212  // save the simplification drawing settings
2213  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2214  mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2215  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2216  mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2217  mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2218 
2219  //save customproperties
2220  writeCustomProperties( node, doc );
2221 
2222  // add the blend mode field
2223  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2224  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2225  blendModeElem.appendChild( blendModeText );
2226  node.appendChild( blendModeElem );
2227 
2228  // add the feature blend mode field
2229  QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2230  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2231  featureBlendModeElem.appendChild( featureBlendModeText );
2232  node.appendChild( featureBlendModeElem );
2233 
2234  // add the layer opacity
2235  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
2236  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
2237  layerOpacityElem.appendChild( layerOpacityText );
2238  node.appendChild( layerOpacityElem );
2239 
2240  if ( mDiagramRenderer )
2241  {
2242  mDiagramRenderer->writeXml( mapLayerNode, doc, context );
2243  if ( mDiagramLayerSettings )
2244  mDiagramLayerSettings->writeXml( mapLayerNode, doc );
2245  }
2246  }
2247  return true;
2248 }
2249 
2250 bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
2251 {
2252  // get the Name element
2253  QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2254  if ( nameElem.isNull() )
2255  {
2256  errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2257  }
2258 
2259  if ( isSpatial() )
2260  {
2261  QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
2262  if ( !r )
2263  return false;
2264 
2265  setRenderer( r );
2266 
2267  // labeling
2268  readSldLabeling( node );
2269  }
2270  return true;
2271 }
2272 
2273 bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsStringMap &props ) const
2274 {
2275  Q_UNUSED( errorMessage );
2276 
2277  QgsStringMap localProps = QgsStringMap( props );
2278  if ( hasScaleBasedVisibility() )
2279  {
2281  }
2282 
2283  if ( isSpatial() )
2284  {
2285  // store the Name element
2286  QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
2287  nameNode.appendChild( doc.createTextNode( name() ) );
2288  node.appendChild( nameNode );
2289 
2290  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
2291  node.appendChild( userStyleElem );
2292 
2293  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
2294  nameElem.appendChild( doc.createTextNode( name() ) );
2295 
2296  userStyleElem.appendChild( nameElem );
2297 
2298  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
2299  userStyleElem.appendChild( featureTypeStyleElem );
2300 
2301  mRenderer->toSld( doc, featureTypeStyleElem, localProps );
2302  if ( labelsEnabled() )
2303  {
2304  mLabeling->toSld( featureTypeStyleElem, localProps );
2305  }
2306  }
2307  return true;
2308 }
2309 
2310 
2311 bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, const QgsGeometry &geom, bool skipDefaultValue )
2312 {
2313  if ( !mEditBuffer || !mDataProvider )
2314  {
2315  return false;
2316  }
2317 
2318  updateExtents();
2319 
2320  bool result = mEditBuffer->changeGeometry( fid, geom );
2321 
2322  if ( result )
2323  {
2324  updateExtents();
2325  if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
2326  updateDefaultValues( fid );
2327  }
2328  return result;
2329 }
2330 
2331 
2332 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
2333 {
2334  bool result = false;
2335 
2336  switch ( fields().fieldOrigin( field ) )
2337  {
2338  case QgsFields::OriginJoin:
2339  result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2340  break;
2341 
2343  case QgsFields::OriginEdit:
2345  {
2346  if ( mEditBuffer && mDataProvider )
2347  result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2348  break;
2349  }
2350 
2352  break;
2353  }
2354 
2355  if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
2356  updateDefaultValues( fid );
2357 
2358  return result;
2359 }
2360 
2362 {
2363  if ( !mEditBuffer || !mDataProvider )
2364  return false;
2365 
2366  return mEditBuffer->addAttribute( field );
2367 }
2368 
2370 {
2371  if ( attIndex < 0 || attIndex >= fields().count() )
2372  return;
2373 
2374  QString name = fields().at( attIndex ).name();
2375  mFields[ attIndex ].setAlias( QString() );
2376  if ( mAttributeAliasMap.contains( name ) )
2377  {
2378  mAttributeAliasMap.remove( name );
2379  updateFields();
2380  mEditFormConfig.setFields( mFields );
2381  emit layerModified();
2382  }
2383 }
2384 
2385 bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
2386 {
2387  if ( index < 0 || index >= fields().count() )
2388  return false;
2389 
2390  switch ( mFields.fieldOrigin( index ) )
2391  {
2393  {
2394  if ( mExpressionFieldBuffer )
2395  {
2396  int oi = mFields.fieldOriginIndex( index );
2397  mExpressionFieldBuffer->renameExpression( oi, newName );
2398  updateFields();
2399  return true;
2400  }
2401  else
2402  {
2403  return false;
2404  }
2405  }
2406 
2408  case QgsFields::OriginEdit:
2409 
2410  if ( !mEditBuffer || !mDataProvider )
2411  return false;
2412 
2413  return mEditBuffer->renameAttribute( index, newName );
2414 
2415  case QgsFields::OriginJoin:
2417  return false;
2418 
2419  }
2420 
2421  return false; // avoid warning
2422 }
2423 
2424 void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
2425 {
2426  if ( attIndex < 0 || attIndex >= fields().count() )
2427  return;
2428 
2429  QString name = fields().at( attIndex ).name();
2430 
2431  mAttributeAliasMap.insert( name, aliasString );
2432  mFields[ attIndex ].setAlias( aliasString );
2433  mEditFormConfig.setFields( mFields );
2434  emit layerModified(); // TODO[MD]: should have a different signal?
2435 }
2436 
2437 QString QgsVectorLayer::attributeAlias( int index ) const
2438 {
2439  if ( index < 0 || index >= fields().count() )
2440  return QString();
2441 
2442  return fields().at( index ).alias();
2443 }
2444 
2445 QString QgsVectorLayer::attributeDisplayName( int index ) const
2446 {
2447  if ( index >= 0 && index < mFields.count() )
2448  return mFields.at( index ).displayName();
2449  else
2450  return QString();
2451 }
2452 
2454 {
2455  QgsStringMap map;
2456  Q_FOREACH ( const QgsField &field, fields() )
2457  {
2458  if ( !field.alias().isEmpty() )
2459  map.insert( field.name(), field.alias() );
2460  }
2461  return map;
2462 }
2463 
2465 {
2466  if ( index < 0 || index >= fields().count() )
2467  return false;
2468 
2469  if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2470  {
2471  removeExpressionField( index );
2472  return true;
2473  }
2474 
2475  if ( !mEditBuffer || !mDataProvider )
2476  return false;
2477 
2478  return mEditBuffer->deleteAttribute( index );
2479 }
2480 
2481 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
2482 {
2483  bool deleted = false;
2484 
2485  // Remove multiple occurrences of same attribute
2486  attrs = attrs.toSet().toList();
2487 
2488  std::sort( attrs.begin(), attrs.end(), std::greater<int>() );
2489 
2490  Q_FOREACH ( int attr, attrs )
2491  {
2492  if ( deleteAttribute( attr ) )
2493  {
2494  deleted = true;
2495  }
2496  }
2497 
2498  return deleted;
2499 }
2500 
2502 {
2503  if ( !mEditBuffer )
2504  return false;
2505 
2506  if ( mJoinBuffer->containsJoins() )
2507  mJoinBuffer->deleteFeature( fid );
2508 
2509  bool res = mEditBuffer->deleteFeature( fid );
2510  if ( res )
2511  {
2512  mSelectedFeatureIds.remove( fid ); // remove it from selection
2513  updateExtents();
2514  }
2515 
2516  return res;
2517 }
2518 
2520 {
2521  if ( !mEditBuffer )
2522  {
2523  QgsDebugMsg( "Cannot delete features (mEditBuffer==NULL)" );
2524  return false;
2525  }
2526 
2527  if ( mJoinBuffer->containsJoins() )
2528  mJoinBuffer->deleteFeatures( fids );
2529 
2530  bool res = mEditBuffer->deleteFeatures( fids );
2531 
2532  if ( res )
2533  {
2534  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2535  updateExtents();
2536  }
2537 
2538  return res;
2539 }
2540 
2542 {
2543  QgsAttributeList pkAttributesList;
2544 
2545  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2546  for ( int i = 0; i < mFields.count(); ++i )
2547  {
2548  if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2549  providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
2550  pkAttributesList << i;
2551  }
2552 
2553  return pkAttributesList;
2554 }
2555 
2557 {
2558  return mDataProvider->featureCount() +
2559  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2560 }
2561 
2563 {
2564  mCommitErrors.clear();
2565 
2566  if ( !mDataProvider )
2567  {
2568  mCommitErrors << tr( "ERROR: no provider" );
2569  return false;
2570  }
2571 
2572  if ( !mEditBuffer )
2573  {
2574  mCommitErrors << tr( "ERROR: layer not editable" );
2575  return false;
2576  }
2577 
2578  emit beforeCommitChanges();
2579 
2580  bool success = mEditBuffer->commitChanges( mCommitErrors );
2581 
2582  if ( success )
2583  {
2584  delete mEditBuffer;
2585  mEditBuffer = nullptr;
2586  undoStack()->clear();
2587  emit editingStopped();
2588  }
2589  else
2590  {
2591  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QStringLiteral( "\n " ) ) ) );
2592  }
2593 
2594  updateFields();
2595  mDataProvider->updateExtents();
2596 
2597  mDataProvider->leaveUpdateMode();
2598 
2599  emit repaintRequested();
2600 
2601  return success;
2602 }
2603 
2604 QStringList QgsVectorLayer::commitErrors() const
2605 {
2606  return mCommitErrors;
2607 }
2608 
2609 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2610 {
2611  if ( !mEditBuffer )
2612  {
2613  return false;
2614  }
2615 
2616  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2617  !mEditBuffer->mAddedFeatures.isEmpty() ||
2618  !mEditBuffer->mChangedGeometries.isEmpty();
2619 
2620  emit beforeRollBack();
2621 
2622  mEditBuffer->rollBack();
2623 
2624  if ( isModified() )
2625  {
2626  // new undo stack roll back method
2627  // old method of calling every undo could cause many canvas refreshes
2628  undoStack()->setIndex( 0 );
2629  }
2630 
2631  updateFields();
2632 
2633  if ( deleteBuffer )
2634  {
2635  delete mEditBuffer;
2636  mEditBuffer = nullptr;
2637  undoStack()->clear();
2638  }
2639  emit editingStopped();
2640 
2641  if ( rollbackExtent )
2642  updateExtents();
2643 
2644  mDataProvider->leaveUpdateMode();
2645 
2646  emit repaintRequested();
2647  return true;
2648 }
2649 
2651 {
2652  return mSelectedFeatureIds.size();
2653 }
2654 
2656 {
2657  return mSelectedFeatureIds;
2658 }
2659 
2661 {
2662  QgsFeatureList features;
2663  QgsFeature f;
2664 
2665  if ( mSelectedFeatureIds.count() <= 8 )
2666  {
2667  // for small amount of selected features, fetch them directly
2668  // because request with FilterFids would go iterate over the whole layer
2669  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2670  {
2671  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2672  features << f;
2673  }
2674  }
2675  else
2676  {
2678 
2679  while ( it.nextFeature( f ) )
2680  {
2681  features.push_back( f );
2682  }
2683  }
2684 
2685  return features;
2686 }
2687 
2689 {
2690  if ( mSelectedFeatureIds.isEmpty() )
2691  return QgsFeatureIterator();
2692 
2695 
2696  if ( mSelectedFeatureIds.count() == 1 )
2697  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2698  else
2699  request.setFilterFids( mSelectedFeatureIds );
2700 
2701  return getFeatures( request );
2702 }
2703 
2705 {
2706  if ( !mEditBuffer || !mDataProvider )
2707  return false;
2708 
2709  bool res = mEditBuffer->addFeatures( features );
2710  updateExtents();
2711 
2712  if ( res && mJoinBuffer->containsJoins() )
2713  res = mJoinBuffer->addFeatures( features );
2714 
2715  return res;
2716 }
2717 
2719 {
2720  QgsDebugMsgLevel( "----- Computing Coordinate System", 4 );
2721 
2722  //
2723  // Get the layers project info and set up the QgsCoordinateTransform
2724  // for this layer
2725  //
2726 
2727  if ( isSpatial() )
2728  {
2729  // get CRS directly from provider
2730  setCrs( mDataProvider->crs() );
2731  }
2732  else
2733  {
2735  }
2736 }
2737 
2738 
2740 {
2741  QgsExpression exp( mDisplayExpression );
2742  if ( exp.isField() )
2743  {
2744  return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
2745  }
2746 
2747  return QString();
2748 }
2749 
2751 {
2752  if ( mDisplayExpression == displayExpression )
2753  return;
2754 
2755  mDisplayExpression = displayExpression;
2756  emit displayExpressionChanged();
2757 }
2758 
2759 QString QgsVectorLayer::displayExpression() const
2760 {
2761  if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
2762  {
2763  return mDisplayExpression;
2764  }
2765  else
2766  {
2767  QString idxName;
2768 
2769  Q_FOREACH ( const QgsField &field, mFields )
2770  {
2771  QString fldName = field.name();
2772 
2773  // Check the fields and keep the first one that matches.
2774  // We assume that the user has organized the data with the
2775  // more "interesting" field names first. As such, name should
2776  // be selected before oldname, othername, etc.
2777  if ( fldName.indexOf( QLatin1String( "name" ), 0, Qt::CaseInsensitive ) > -1 )
2778  {
2779  idxName = fldName;
2780  break;
2781  }
2782  if ( fldName.indexOf( QLatin1String( "descrip" ), 0, Qt::CaseInsensitive ) > -1 )
2783  {
2784  idxName = fldName;
2785  break;
2786  }
2787  if ( fldName.indexOf( QLatin1String( "id" ), 0, Qt::CaseInsensitive ) > -1 )
2788  {
2789  idxName = fldName;
2790  break;
2791  }
2792  }
2793 
2794  if ( !idxName.isNull() )
2795  {
2796  return QgsExpression::quotedColumnRef( idxName );
2797  }
2798  else
2799  {
2800  return QgsExpression::quotedColumnRef( mFields.at( 0 ).name() );
2801  }
2802  }
2803 }
2804 
2806 {
2807  return ( mEditBuffer && mDataProvider );
2808 }
2809 
2811 {
2814 }
2815 
2816 bool QgsVectorLayer::isReadOnly() const
2817 {
2818  return mReadOnly;
2819 }
2820 
2821 bool QgsVectorLayer::setReadOnly( bool readonly )
2822 {
2823  // exit if the layer is in editing mode
2824  if ( readonly && mEditBuffer )
2825  return false;
2826 
2827  mReadOnly = readonly;
2828  emit readOnlyChanged();
2829  return true;
2830 }
2831 
2833 {
2834  emit beforeModifiedCheck();
2835  return mEditBuffer && mEditBuffer->isModified();
2836 }
2837 
2838 
2839 bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
2840 {
2841  bool auxiliaryField = false;
2842  srcIndex = -1;
2843 
2844  if ( !auxiliaryLayer() )
2845  return auxiliaryField;
2846 
2847  if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
2848  {
2849  const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
2850 
2851  if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
2852  auxiliaryField = true;
2853  }
2854 
2855  return auxiliaryField;
2856 }
2857 
2859 {
2860  if ( !isSpatial() )
2861  return;
2862 
2863  if ( r != mRenderer )
2864  {
2865  delete mRenderer;
2866  mRenderer = r;
2867  mSymbolFeatureCounted = false;
2868  mSymbolFeatureCountMap.clear();
2869 
2870  emit rendererChanged();
2871  emit styleChanged();
2872  }
2873 }
2874 
2875 void QgsVectorLayer::beginEditCommand( const QString &text )
2876 {
2877  if ( !mDataProvider )
2878  {
2879  return;
2880  }
2881  if ( mDataProvider->transaction() )
2882  {
2883  QString ignoredError;
2884  mDataProvider->transaction()->createSavepoint( ignoredError );
2885  }
2886  undoStack()->beginMacro( text );
2887  mEditCommandActive = true;
2888  emit editCommandStarted( text );
2889 }
2890 
2892 {
2893  if ( !mDataProvider )
2894  {
2895  return;
2896  }
2897  undoStack()->endMacro();
2898  mEditCommandActive = false;
2899  if ( !mDeletedFids.isEmpty() )
2900  {
2901  emit featuresDeleted( mDeletedFids );
2902  mDeletedFids.clear();
2903  }
2904  emit editCommandEnded();
2905 }
2906 
2908 {
2909  if ( !mDataProvider )
2910  {
2911  return;
2912  }
2913  undoStack()->endMacro();
2914  undoStack()->undo();
2915  mEditCommandActive = false;
2916  mDeletedFids.clear();
2917  emit editCommandDestroyed();
2918 }
2919 
2921 {
2922  return mJoinBuffer->addJoin( joinInfo );
2923 }
2924 
2925 
2926 bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
2927 {
2928  return mJoinBuffer->removeJoin( joinLayerId );
2929 }
2930 
2931 const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
2932 {
2933  return mJoinBuffer->vectorJoins();
2934 }
2935 
2936 int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
2937 {
2938  emit beforeAddingExpressionField( fld.name() );
2939  mExpressionFieldBuffer->addExpression( exp, fld );
2940  updateFields();
2941  int idx = mFields.indexFromName( fld.name() );
2942  emit attributeAdded( idx );
2943  return idx;
2944 }
2945 
2947 {
2948  emit beforeRemovingExpressionField( index );
2949  int oi = mFields.fieldOriginIndex( index );
2950  mExpressionFieldBuffer->removeExpression( oi );
2951  updateFields();
2952  emit attributeDeleted( index );
2953 }
2954 
2955 QString QgsVectorLayer::expressionField( int index ) const
2956 {
2957  int oi = mFields.fieldOriginIndex( index );
2958  if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
2959  return QString();
2960 
2961  return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
2962 }
2963 
2964 void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
2965 {
2966  int oi = mFields.fieldOriginIndex( index );
2967  mExpressionFieldBuffer->updateExpression( oi, exp );
2968 }
2969 
2971 {
2972  if ( !mDataProvider )
2973  return;
2974 
2975  QgsFields oldFields = mFields;
2976 
2977  mFields = mDataProvider->fields();
2978 
2979  // added / removed fields
2980  if ( mEditBuffer )
2981  mEditBuffer->updateFields( mFields );
2982 
2983  // joined fields
2984  if ( mJoinBuffer->containsJoins() )
2985  mJoinBuffer->updateFields( mFields );
2986 
2987  if ( mExpressionFieldBuffer )
2988  mExpressionFieldBuffer->updateFields( mFields );
2989 
2990  // set aliases and default values
2991  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
2992  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
2993  {
2994  int index = mFields.lookupField( aliasIt.key() );
2995  if ( index < 0 )
2996  continue;
2997 
2998  mFields[ index ].setAlias( aliasIt.value() );
2999  }
3000 
3001  // Update default values
3002  mDefaultValueOnUpdateFields.clear();
3003  QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
3004  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
3005  {
3006  int index = mFields.lookupField( defaultIt.key() );
3007  if ( index < 0 )
3008  continue;
3009 
3010  mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
3011  if ( defaultIt.value().applyOnUpdate() )
3012  mDefaultValueOnUpdateFields.insert( index );
3013  }
3014 
3015  QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
3016  for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
3017  {
3018  int index = mFields.lookupField( constraintIt.key() );
3019  if ( index < 0 )
3020  continue;
3021 
3022  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3023 
3024  // always keep provider constraints intact
3025  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
3027  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
3029  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
3031  mFields[ index ].setConstraints( constraints );
3032  }
3033 
3034  QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
3035  for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
3036  {
3037  int index = mFields.lookupField( constraintExpIt.key() );
3038  if ( index < 0 )
3039  continue;
3040 
3041  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3042 
3043  // always keep provider constraints intact
3045  continue;
3046 
3047  constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
3048  mFields[ index ].setConstraints( constraints );
3049  }
3050 
3051  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
3052  for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
3053  {
3054  int index = mFields.lookupField( constraintStrengthIt.key().first );
3055  if ( index < 0 )
3056  continue;
3057 
3058  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3059 
3060  // always keep provider constraints intact
3062  continue;
3063 
3064  constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
3065  mFields[ index ].setConstraints( constraints );
3066  }
3067 
3068  auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
3069  for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
3070  {
3071  int index = mFields.indexOf( fieldWidgetIterator.key() );
3072  if ( index < 0 )
3073  continue;
3074 
3075  mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
3076  }
3077 
3078  if ( oldFields != mFields )
3079  {
3080  emit updatedFields();
3081  mEditFormConfig.setFields( mFields );
3082  }
3083 }
3084 
3085 
3086 QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
3087 {
3088  if ( index < 0 || index >= mFields.count() )
3089  return QVariant();
3090 
3091  QString expression = mFields.at( index ).defaultValueDefinition().expression();
3092  if ( expression.isEmpty() )
3093  return mDataProvider->defaultValue( index );
3094 
3095  QgsExpressionContext *evalContext = context;
3096  std::unique_ptr< QgsExpressionContext > tempContext;
3097  if ( !evalContext )
3098  {
3099  // no context passed, so we create a default one
3101  evalContext = tempContext.get();
3102  }
3103 
3104  if ( feature.isValid() )
3105  {
3107  featScope->setFeature( feature );
3108  featScope->setFields( feature.fields() );
3109  evalContext->appendScope( featScope );
3110  }
3111 
3112  QVariant val;
3113  QgsExpression exp( expression );
3114  exp.prepare( evalContext );
3115  if ( exp.hasEvalError() )
3116  {
3117  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
3118  }
3119  else
3120  {
3121  val = exp.evaluate( evalContext );
3122  }
3123 
3124  if ( feature.isValid() )
3125  {
3126  delete evalContext->popScope();
3127  }
3128 
3129  return val;
3130 }
3131 
3133 {
3134  if ( index < 0 || index >= mFields.count() )
3135  return;
3136 
3137  if ( definition.isValid() )
3138  {
3139  mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
3140  }
3141  else
3142  {
3143  mDefaultExpressionMap.remove( mFields.at( index ).name() );
3144  }
3145  updateFields();
3146 }
3147 
3149 {
3150  if ( index < 0 || index >= mFields.count() )
3151  return QString();
3152  else
3153  return mFields.at( index ).defaultValueDefinition().expression();
3154 }
3155 
3156 QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
3157 {
3158  QSet<QVariant> uniqueValues;
3159  if ( !mDataProvider )
3160  {
3161  return uniqueValues;
3162  }
3163 
3164  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3165  switch ( origin )
3166  {
3168  return uniqueValues;
3169 
3170  case QgsFields::OriginProvider: //a provider field
3171  {
3172  uniqueValues = mDataProvider->uniqueValues( index, limit );
3173 
3174  if ( mEditBuffer )
3175  {
3176  QSet<QString> vals;
3177  Q_FOREACH ( const QVariant &v, uniqueValues )
3178  {
3179  vals << v.toString();
3180  }
3181 
3182  QgsFeatureMap added = mEditBuffer->addedFeatures();
3183  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3184  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3185  {
3186  addedIt.next();
3187  QVariant v = addedIt.value().attribute( index );
3188  if ( v.isValid() )
3189  {
3190  QString vs = v.toString();
3191  if ( !vals.contains( vs ) )
3192  {
3193  vals << vs;
3194  uniqueValues << v;
3195  }
3196  }
3197  }
3198 
3199  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3200  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3201  {
3202  it.next();
3203  QVariant v = it.value().value( index );
3204  if ( v.isValid() )
3205  {
3206  QString vs = v.toString();
3207  if ( !vals.contains( vs ) )
3208  {
3209  vals << vs;
3210  uniqueValues << v;
3211  }
3212  }
3213  }
3214  }
3215 
3216  return uniqueValues;
3217  }
3218 
3219  case QgsFields::OriginEdit:
3220  // the layer is editable, but in certain cases it can still be avoided going through all features
3221  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3222  mEditBuffer->mAddedFeatures.isEmpty() &&
3223  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3224  mEditBuffer->mChangedAttributeValues.isEmpty() )
3225  {
3226  uniqueValues = mDataProvider->uniqueValues( index, limit );
3227  return uniqueValues;
3228  }
3229  FALLTHROUGH;
3230  //we need to go through each feature
3231  case QgsFields::OriginJoin:
3233  {
3234  QgsAttributeList attList;
3235  attList << index;
3236 
3238  .setFlags( QgsFeatureRequest::NoGeometry )
3239  .setSubsetOfAttributes( attList ) );
3240 
3241  QgsFeature f;
3242  QVariant currentValue;
3243  QHash<QString, QVariant> val;
3244  while ( fit.nextFeature( f ) )
3245  {
3246  currentValue = f.attribute( index );
3247  val.insert( currentValue.toString(), currentValue );
3248  if ( limit >= 0 && val.size() >= limit )
3249  {
3250  break;
3251  }
3252  }
3253 
3254  return val.values().toSet();
3255  }
3256  }
3257 
3258  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3259  return uniqueValues;
3260 }
3261 
3262 QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
3263 {
3264  QStringList results;
3265  if ( !mDataProvider )
3266  {
3267  return results;
3268  }
3269 
3270  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3271  switch ( origin )
3272  {
3274  return results;
3275 
3276  case QgsFields::OriginProvider: //a provider field
3277  {
3278  results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3279 
3280  if ( mEditBuffer )
3281  {
3282  QgsFeatureMap added = mEditBuffer->addedFeatures();
3283  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3284  while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3285  {
3286  addedIt.next();
3287  QVariant v = addedIt.value().attribute( index );
3288  if ( v.isValid() )
3289  {
3290  QString vs = v.toString();
3291  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3292  {
3293  results << vs;
3294  }
3295  }
3296  }
3297 
3298  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3299  while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3300  {
3301  it.next();
3302  QVariant v = it.value().value( index );
3303  if ( v.isValid() )
3304  {
3305  QString vs = v.toString();
3306  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3307  {
3308  results << vs;
3309  }
3310  }
3311  }
3312  }
3313 
3314  return results;
3315  }
3316 
3317  case QgsFields::OriginEdit:
3318  // the layer is editable, but in certain cases it can still be avoided going through all features
3319  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3320  mEditBuffer->mAddedFeatures.isEmpty() &&
3321  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3322  mEditBuffer->mChangedAttributeValues.isEmpty() )
3323  {
3324  return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3325  }
3326  FALLTHROUGH;
3327  //we need to go through each feature
3328  case QgsFields::OriginJoin:
3330  {
3331  QgsAttributeList attList;
3332  attList << index;
3333 
3334  QgsFeatureRequest request;
3335  request.setSubsetOfAttributes( attList );
3337  QString fieldName = mFields.at( index ).name();
3338  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
3339  QgsFeatureIterator fit = getFeatures( request );
3340 
3341  QgsFeature f;
3342  QString currentValue;
3343  while ( fit.nextFeature( f ) )
3344  {
3345  currentValue = f.attribute( index ).toString();
3346  if ( !results.contains( currentValue ) )
3347  results << currentValue;
3348 
3349  if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
3350  {
3351  break;
3352  }
3353  }
3354 
3355  return results;
3356  }
3357  }
3358 
3359  Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
3360  return results;
3361 }
3362 
3363 QVariant QgsVectorLayer::minimumValue( int index ) const
3364 {
3365  if ( !mDataProvider )
3366  {
3367  return QVariant();
3368  }
3369 
3370  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3371 
3372  switch ( origin )
3373  {
3375  return QVariant();
3376 
3377  case QgsFields::OriginProvider: //a provider field
3378  {
3379  QVariant min = mDataProvider->minimumValue( index );
3380  if ( mEditBuffer )
3381  {
3382  QgsFeatureMap added = mEditBuffer->addedFeatures();
3383  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3384  while ( addedIt.hasNext() )
3385  {
3386  addedIt.next();
3387  QVariant v = addedIt.value().attribute( index );
3388  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3389  {
3390  min = v;
3391  }
3392  }
3393 
3394  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3395  while ( it.hasNext() )
3396  {
3397  it.next();
3398  QVariant v = it.value().value( index );
3399  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3400  {
3401  min = v;
3402  }
3403  }
3404  }
3405  return min;
3406  }
3407 
3408  case QgsFields::OriginEdit:
3409  {
3410  // the layer is editable, but in certain cases it can still be avoided going through all features
3411  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3412  mEditBuffer->mAddedFeatures.isEmpty() && !
3413  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3414  mEditBuffer->mChangedAttributeValues.isEmpty() )
3415  {
3416  return mDataProvider->minimumValue( index );
3417  }
3418  }
3419  FALLTHROUGH;
3420  // no choice but to go through all features
3422  case QgsFields::OriginJoin:
3423  {
3424  // we need to go through each feature
3425  QgsAttributeList attList;
3426  attList << index;
3427 
3429  .setFlags( QgsFeatureRequest::NoGeometry )
3430  .setSubsetOfAttributes( attList ) );
3431 
3432  QgsFeature f;
3433  double minimumValue = std::numeric_limits<double>::max();
3434  double currentValue = 0;
3435  while ( fit.nextFeature( f ) )
3436  {
3437  currentValue = f.attribute( index ).toDouble();
3438  if ( currentValue < minimumValue )
3439  {
3440  minimumValue = currentValue;
3441  }
3442  }
3443  return QVariant( minimumValue );
3444  }
3445  }
3446 
3447  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3448  return QVariant();
3449 }
3450 
3451 QVariant QgsVectorLayer::maximumValue( int index ) const
3452 {
3453  if ( !mDataProvider )
3454  {
3455  return QVariant();
3456  }
3457 
3458  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3459  switch ( origin )
3460  {
3462  return QVariant();
3463 
3464  case QgsFields::OriginProvider: //a provider field
3465  {
3466  QVariant min = mDataProvider->maximumValue( index );
3467  if ( mEditBuffer )
3468  {
3469  QgsFeatureMap added = mEditBuffer->addedFeatures();
3470  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3471  while ( addedIt.hasNext() )
3472  {
3473  addedIt.next();
3474  QVariant v = addedIt.value().attribute( index );
3475  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3476  {
3477  min = v;
3478  }
3479  }
3480 
3481  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3482  while ( it.hasNext() )
3483  {
3484  it.next();
3485  QVariant v = it.value().value( index );
3486  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3487  {
3488  min = v;
3489  }
3490  }
3491  }
3492  return min;
3493  }
3494 
3495  case QgsFields::OriginEdit:
3496  // the layer is editable, but in certain cases it can still be avoided going through all features
3497  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3498  mEditBuffer->mAddedFeatures.isEmpty() &&
3499  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3500  mEditBuffer->mChangedAttributeValues.isEmpty() )
3501  {
3502  return mDataProvider->maximumValue( index );
3503  }
3504 
3505  FALLTHROUGH;
3506  //no choice but to go through each feature
3507  case QgsFields::OriginJoin:
3509  {
3510  QgsAttributeList attList;
3511  attList << index;
3512 
3514  .setFlags( QgsFeatureRequest::NoGeometry )
3515  .setSubsetOfAttributes( attList ) );
3516 
3517  QgsFeature f;
3518  double maximumValue = -std::numeric_limits<double>::max();
3519  double currentValue = 0;
3520  while ( fit.nextFeature( f ) )
3521  {
3522  currentValue = f.attribute( index ).toDouble();
3523  if ( currentValue > maximumValue )
3524  {
3525  maximumValue = currentValue;
3526  }
3527  }
3528  return QVariant( maximumValue );
3529  }
3530  }
3531 
3532  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3533  return QVariant();
3534 }
3535 
3536 QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
3537  const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool *ok ) const
3538 {
3539  if ( ok )
3540  *ok = false;
3541 
3542  if ( !mDataProvider )
3543  {
3544  return QVariant();
3545  }
3546 
3547  // test if we are calculating based on a field
3548  int attrIndex = mFields.lookupField( fieldOrExpression );
3549  if ( attrIndex >= 0 )
3550  {
3551  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
3552  // to the provider itself
3553  QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
3554  if ( origin == QgsFields::OriginProvider )
3555  {
3556  bool providerOk = false;
3557  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk );
3558  if ( providerOk )
3559  {
3560  // provider handled calculation
3561  if ( ok )
3562  *ok = true;
3563  return val;
3564  }
3565  }
3566  }
3567 
3568  // fallback to using aggregate calculator to determine aggregate
3569  QgsAggregateCalculator c( this );
3570  c.setParameters( parameters );
3571  return c.calculate( aggregate, fieldOrExpression, context, ok );
3572 }
3573 
3574 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback ) const
3575 {
3576  QList<QVariant> values;
3577 
3578  std::unique_ptr<QgsExpression> expression;
3579  QgsExpressionContext context;
3580 
3581  int attrNum = mFields.lookupField( fieldOrExpression );
3582 
3583  if ( attrNum == -1 )
3584  {
3585  // try to use expression
3586  expression.reset( new QgsExpression( fieldOrExpression ) );
3588 
3589  if ( expression->hasParserError() || !expression->prepare( &context ) )
3590  {
3591  ok = false;
3592  return values;
3593  }
3594  }
3595 
3596  QgsFeature f;
3597  QSet<QString> lst;
3598  if ( !expression )
3599  lst.insert( fieldOrExpression );
3600  else
3601  lst = expression->referencedColumns();
3602 
3604  .setFlags( ( expression && expression->needsGeometry() ) ?
3607  .setSubsetOfAttributes( lst, fields() );
3608 
3609  QgsFeatureIterator fit;
3610  if ( !selectedOnly )
3611  {
3612  fit = getFeatures( request );
3613  }
3614  else
3615  {
3616  fit = getSelectedFeatures( request );
3617  }
3618 
3619  // create list of non-null attribute values
3620  while ( fit.nextFeature( f ) )
3621  {
3622  if ( expression )
3623  {
3624  context.setFeature( f );
3625  QVariant v = expression->evaluate( &context );
3626  values << v;
3627  }
3628  else
3629  {
3630  values << f.attribute( attrNum );
3631  }
3632  if ( feedback && feedback->isCanceled() )
3633  {
3634  ok = false;
3635  return values;
3636  }
3637  }
3638  ok = true;
3639  return values;
3640 }
3641 
3642 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool &ok, bool selectedOnly, int *nullCount, QgsFeedback *feedback ) const
3643 {
3644  QList<double> values;
3645 
3646  if ( nullCount )
3647  *nullCount = 0;
3648 
3649  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3650  if ( !ok )
3651  return values;
3652 
3653  bool convertOk;
3654  Q_FOREACH ( const QVariant &value, variantValues )
3655  {
3656  double val = value.toDouble( &convertOk );
3657  if ( convertOk )
3658  values << val;
3659  else if ( value.isNull() )
3660  {
3661  if ( nullCount )
3662  *nullCount += 1;
3663  }
3664  if ( feedback && feedback->isCanceled() )
3665  {
3666  ok = false;
3667  return values;
3668  }
3669  }
3670  ok = true;
3671  return values;
3672 }
3673 
3675 {
3676  mFeatureBlendMode = featureBlendMode;
3677  emit featureBlendModeChanged( featureBlendMode );
3678  emit styleChanged();
3679 }
3680 
3681 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3682 {
3683  return mFeatureBlendMode;
3684 }
3685 
3687 {
3688  mLayerOpacity = opacity;
3689  emit opacityChanged( opacity );
3690  emit styleChanged();
3691 }
3692 
3693 double QgsVectorLayer::opacity() const
3694 {
3695  return mLayerOpacity;
3696 }
3697 
3698 
3699 
3700 void QgsVectorLayer::readSldLabeling( const QDomNode &node )
3701 {
3702  setLabeling( nullptr ); // start with no labeling
3703 
3704  QDomElement element = node.toElement();
3705  if ( element.isNull() )
3706  return;
3707 
3708  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
3709  if ( userStyleElem.isNull() )
3710  {
3711  QgsDebugMsg( "Info: UserStyle element not found." );
3712  return;
3713  }
3714 
3715  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
3716  if ( featureTypeStyleElem.isNull() )
3717  {
3718  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3719  return;
3720  }
3721 
3722  // use last rule
3723  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( QStringLiteral( "Rule" ) );
3724  if ( ruleElem.isNull() )
3725  {
3726  QgsDebugMsg( "Info: Rule element not found." );
3727  return;
3728  }
3729 
3730  // use last text symbolizer
3731  QDomElement textSymbolizerElem = ruleElem.lastChildElement( QStringLiteral( "TextSymbolizer" ) );
3732  if ( textSymbolizerElem.isNull() )
3733  {
3734  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3735  return;
3736  }
3737 
3738  QgsPalLayerSettings settings;
3739 
3740  // Label
3741  QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
3742  if ( !labelElem.isNull() )
3743  {
3744  QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
3745  if ( !propertyNameElem.isNull() )
3746  {
3747  // set labeling defaults
3748 
3749  // label attribute
3750  QString labelAttribute = propertyNameElem.text();
3751  settings.fieldName = labelAttribute;
3752  settings.isExpression = false;
3753 
3754  int fieldIndex = mFields.lookupField( labelAttribute );
3755  if ( fieldIndex == -1 )
3756  {
3757  // label attribute is not in columns, check if it is an expression
3758  QgsExpression exp( labelAttribute );
3759  if ( !exp.hasEvalError() )
3760  {
3761  settings.isExpression = true;
3762  }
3763  else
3764  {
3765  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3766  }
3767  }
3768  }
3769  else
3770  {
3771  QgsDebugMsg( "Info: PropertyName element not found." );
3772  return;
3773  }
3774  }
3775  else
3776  {
3777  QgsDebugMsg( "Info: Label element not found." );
3778  return;
3779  }
3780 
3781  QString fontFamily = QStringLiteral( "Sans-Serif" );
3782  int fontPointSize = 10;
3783  int fontWeight = -1;
3784  bool fontItalic = false;
3785  bool fontUnderline = false;
3786 
3787  // Font
3788  QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
3789  if ( !fontElem.isNull() )
3790  {
3791  QString cssName;
3792  QString elemText;
3793  QDomElement cssElem = fontElem.firstChildElement( QStringLiteral( "CssParameter" ) );
3794  while ( !cssElem.isNull() )
3795  {
3796  cssName = cssElem.attribute( QStringLiteral( "name" ), QStringLiteral( "not_found" ) );
3797  if ( cssName != QLatin1String( "not_found" ) )
3798  {
3799  elemText = cssElem.text();
3800  if ( cssName == QLatin1String( "font-family" ) )
3801  {
3802  fontFamily = elemText;
3803  }
3804  else if ( cssName == QLatin1String( "font-style" ) )
3805  {
3806  fontItalic = ( elemText == QLatin1String( "italic" ) ) || ( elemText == QLatin1String( "Italic" ) );
3807  }
3808  else if ( cssName == QLatin1String( "font-size" ) )
3809  {
3810  bool ok;
3811  int fontSize = elemText.toInt( &ok );
3812  if ( ok )
3813  {
3814  fontPointSize = fontSize;
3815  }
3816  }
3817  else if ( cssName == QLatin1String( "font-weight" ) )
3818  {
3819  if ( ( elemText == QLatin1String( "bold" ) ) || ( elemText == QLatin1String( "Bold" ) ) )
3820  fontWeight = QFont::Bold;
3821  }
3822  else if ( cssName == QLatin1String( "font-underline" ) )
3823  {
3824  fontUnderline = ( elemText == QLatin1String( "underline" ) ) || ( elemText == QLatin1String( "Underline" ) );
3825  }
3826  }
3827 
3828  cssElem = cssElem.nextSiblingElement( QStringLiteral( "CssParameter" ) );
3829  }
3830  }
3831 
3832  QgsTextFormat format;
3833  QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
3834  font.setUnderline( fontUnderline );
3835  format.setFont( font );
3836  format.setSize( fontPointSize );
3837 
3838  // Fill
3839  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) ) );
3840  if ( textColor.isValid() )
3841  {
3842  format.setColor( textColor );
3843  }
3844 
3845  QgsTextBufferSettings bufferSettings;
3846 
3847  // Halo
3848  QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
3849  if ( !haloElem.isNull() )
3850  {
3851  bufferSettings.setEnabled( true );
3852  bufferSettings.setSize( 1 );
3853 
3854  QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
3855  if ( !radiusElem.isNull() )
3856  {
3857  bool ok;
3858  double bufferSize = radiusElem.text().toDouble( &ok );
3859  if ( ok )
3860  {
3861  bufferSettings.setSize( bufferSize );
3862  }
3863  }
3864 
3865  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( QStringLiteral( "Fill" ) ) );
3866  if ( bufferColor.isValid() )
3867  {
3868  bufferSettings.setColor( bufferColor );
3869  }
3870  }
3871 
3872  // LabelPlacement
3873  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
3874  if ( !labelPlacementElem.isNull() )
3875  {
3876  // PointPlacement
3877  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
3878  if ( !pointPlacementElem.isNull() )
3879  {
3881 
3882  QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
3883  if ( !displacementElem.isNull() )
3884  {
3885  QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
3886  if ( !displacementXElem.isNull() )
3887  {
3888  bool ok;
3889  double xOffset = displacementXElem.text().toDouble( &ok );
3890  if ( ok )
3891  {
3892  settings.xOffset = xOffset;
3893  }
3894  }
3895  QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
3896  if ( !displacementYElem.isNull() )
3897  {
3898  bool ok;
3899  double yOffset = displacementYElem.text().toDouble( &ok );
3900  if ( ok )
3901  {
3902  settings.yOffset = yOffset;
3903  }
3904  }
3905  }
3906 
3907  QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
3908  if ( !rotationElem.isNull() )
3909  {
3910  bool ok;
3911  double rotation = rotationElem.text().toDouble( &ok );
3912  if ( ok )
3913  {
3914  settings.angleOffset = 360 - rotation;
3915  }
3916  }
3917  }
3918  }
3919 
3920  format.setBuffer( bufferSettings );
3921  settings.setFormat( format );
3922  setLabeling( new QgsVectorLayerSimpleLabeling( settings ) );
3923 }
3924 
3926 {
3927  return mEditFormConfig;
3928 }
3929 
3931 {
3932  if ( mEditFormConfig == editFormConfig )
3933  return;
3934 
3935  mEditFormConfig = editFormConfig;
3936  mEditFormConfig.onRelationsLoaded();
3937  emit editFormConfigChanged();
3938 }
3939 
3940 QString QgsVectorLayer::mapTipTemplate() const
3941 {
3942  return mMapTipTemplate;
3943 }
3944 
3945 void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
3946 {
3947  if ( mMapTipTemplate == mapTip )
3948  return;
3949 
3950  mMapTipTemplate = mapTip;
3951  emit mapTipTemplateChanged();
3952 }
3953 
3955 {
3956  QgsAttributeTableConfig config = mAttributeTableConfig;
3957 
3958  if ( config.isEmpty() )
3959  config.update( fields() );
3960 
3961  return config;
3962 }
3963 
3965 {
3966  if ( mAttributeTableConfig != attributeTableConfig )
3967  {
3968  mAttributeTableConfig = attributeTableConfig;
3969  emit configChanged();
3970  }
3971 }
3972 
3974 {
3976 }
3977 
3979 {
3980  if ( !mDiagramLayerSettings )
3981  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3982  *mDiagramLayerSettings = s;
3983 }
3984 
3986 {
3987  QgsLayerMetadataFormatter htmlFormatter( metadata() );
3988  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
3989 
3990  // Begin Provider section
3991  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
3992  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
3993 
3994  // original name
3995  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Original" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
3996 
3997  // name
3998  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
3999 
4000  // data source
4001  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>" ) + publicSource() + QStringLiteral( "</td></tr>\n" );
4002 
4003  // storage type
4004  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
4005 
4006  // comment
4007  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
4008 
4009  // encoding
4010  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + dataProvider()->encoding() + QStringLiteral( "</td></tr>\n" );
4011 
4012  // geom type
4014  if ( type < 0 || type > QgsWkbTypes::NullGeometry )
4015  {
4016  QgsDebugMsg( "Invalid vector type" );
4017  }
4018  else
4019  {
4020  QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
4022  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
4023  }
4024 
4025  // EPSG
4026  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" ) + crs().authid() + QStringLiteral( " - " );
4027  myMetadata += crs().description() + QStringLiteral( " - " );
4028  if ( crs().isGeographic() )
4029  myMetadata += tr( "Geographic" );
4030  else
4031  myMetadata += tr( "Projected" );
4032  myMetadata += QLatin1String( "</td></tr>\n" );
4033 
4034  // Extent
4035  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
4036 
4037  // unit
4038  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
4039 
4040  // feature count
4041  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Feature count" ) + QStringLiteral( "</td><td>" ) + QString::number( featureCount() ) + QStringLiteral( "</td></tr>\n" );
4042 
4043  // End Provider section
4044  myMetadata += QLatin1String( "</table>\n<br><br>" );
4045 
4046  // identification section
4047  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
4048  myMetadata += htmlFormatter.identificationSectionHtml( );
4049  myMetadata += QLatin1String( "<br><br>\n" );
4050 
4051  // extent section
4052  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
4053  myMetadata += htmlFormatter.extentSectionHtml( );
4054  myMetadata += QLatin1String( "<br><br>\n" );
4055 
4056  // Start the Access section
4057  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
4058  myMetadata += htmlFormatter.accessSectionHtml( );
4059  myMetadata += QLatin1String( "<br><br>\n" );
4060 
4061  // Fields section
4062  myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
4063 
4064  // primary key
4065  QgsAttributeList pkAttrList = pkAttributeList();
4066  if ( !pkAttrList.isEmpty() )
4067  {
4068  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
4069  Q_FOREACH ( int idx, pkAttrList )
4070  {
4071  myMetadata += fields().at( idx ).name() + ' ';
4072  }
4073  myMetadata += QLatin1String( "</td></tr>\n" );
4074  }
4075 
4076  const QgsFields &myFields = pendingFields();
4077 
4078  // count fields
4079  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
4080 
4081  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
4082  myMetadata += "<tr><th>" + tr( "Field" ) + "</th><th>" + tr( "Type" ) + "</th><th>" + tr( "Length" ) + "</th><th>" + tr( "Precision" ) + "</th><th>" + tr( "Comment" ) + "</th></tr>\n";
4083 
4084  for ( int i = 0; i < myFields.size(); ++i )
4085  {
4086  QgsField myField = myFields.at( i );
4087  QString rowClass;
4088  if ( i % 2 )
4089  rowClass = QStringLiteral( "class=\"odd-row\"" );
4090  myMetadata += "<tr " + rowClass + "><td>" + myField.name() + "</td><td>" + myField.typeName() + "</td><td>" + QString::number( myField.length() ) + "</td><td>" + QString::number( myField.precision() ) + "</td><td>" + myField.comment() + "</td></tr>\n";
4091  }
4092 
4093  //close field list
4094  myMetadata += QLatin1String( "</table>\n<br><br>" );
4095 
4096  // Start the contacts section
4097  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
4098  myMetadata += htmlFormatter.contactsSectionHtml( );
4099  myMetadata += QLatin1String( "<br><br>\n" );
4100 
4101  // Start the links section
4102  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
4103  myMetadata += htmlFormatter.linksSectionHtml( );
4104  myMetadata += QLatin1String( "<br><br>\n" );
4105 
4106  // Start the history section
4107  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
4108  myMetadata += htmlFormatter.historySectionHtml( );
4109  myMetadata += QLatin1String( "<br><br>\n" );
4110 
4111  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
4112  return myMetadata;
4113 }
4114 
4115 void QgsVectorLayer::invalidateSymbolCountedFlag()
4116 {
4117  mSymbolFeatureCounted = false;
4118 }
4119 
4120 void QgsVectorLayer::onFeatureCounterCompleted()
4121 {
4122  onSymbolsCounted();
4123  mFeatureCounter = nullptr;
4124 }
4125 
4126 void QgsVectorLayer::onFeatureCounterTerminated()
4127 {
4128  mFeatureCounter = nullptr;
4129 }
4130 
4131 void QgsVectorLayer::onJoinedFieldsChanged()
4132 {
4133  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4134  updateFields();
4135 }
4136 
4137 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4138 {
4139  if ( mEditCommandActive )
4140  mDeletedFids << fid;
4141  else
4142  emit featuresDeleted( QgsFeatureIds() << fid );
4143 
4144  emit featureDeleted( fid );
4145 }
4146 
4147 void QgsVectorLayer::onRelationsLoaded()
4148 {
4149  mEditFormConfig.onRelationsLoaded();
4150 }
4151 
4152 void QgsVectorLayer::onSymbolsCounted()
4153 {
4154  if ( mFeatureCounter )
4155  {
4156  mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
4157  mSymbolFeatureCounted = true;
4159  }
4160 }
4161 
4162 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
4163 {
4164  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4165 }
4166 
4167 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
4168 {
4169  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4170  if ( !myLib )
4171  {
4172  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4173  return -1;
4174  }
4175  listStyles_t *listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
4176 
4177  if ( !listStylesExternalMethod )
4178  {
4179  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "listStyles" ) );
4180  return -1;
4181  }
4182 
4183  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
4184 }
4185 
4186 QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
4187 {
4188  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4189  if ( !myLib )
4190  {
4191  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4192  return QString();
4193  }
4194  getStyleById_t *getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
4195 
4196  if ( !getStyleByIdMethod )
4197  {
4198  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "getStyleById" ) );
4199  return QString();
4200  }
4201 
4202  return getStyleByIdMethod( mDataSource, styleId, msgError );
4203 }
4204 
4205 bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
4206 {
4207  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4208  if ( !myLib )
4209  {
4210  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4211  return false;
4212  }
4213  deleteStyleById_t *deleteStyleByIdMethod = reinterpret_cast< deleteStyleById_t * >( cast_to_fptr( myLib->resolve( "deleteStyleById" ) ) );
4214  if ( !deleteStyleByIdMethod )
4215  {
4216  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "deleteStyleById" ) );
4217  return false;
4218  }
4219  return deleteStyleByIdMethod( mDataSource, styleId, msgError );
4220 }
4221 
4222 
4223 void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
4224  bool useAsDefault, const QString &uiFileContent, QString &msgError )
4225 {
4226 
4227  QString sldStyle, qmlStyle;
4228  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4229  if ( !myLib )
4230  {
4231  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4232  return;
4233  }
4234  saveStyle_t *saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4235 
4236  if ( !saveStyleExternalMethod )
4237  {
4238  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "saveStyle" ) );
4239  return;
4240  }
4241 
4242  QDomDocument qmlDocument, sldDocument;
4243  this->exportNamedStyle( qmlDocument, msgError );
4244  if ( !msgError.isNull() )
4245  {
4246  return;
4247  }
4248  qmlStyle = qmlDocument.toString();
4249 
4250  this->exportSldStyle( sldDocument, msgError );
4251  if ( !msgError.isNull() )
4252  {
4253  return;
4254  }
4255  sldStyle = sldDocument.toString();
4256 
4257  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4258  description, uiFileContent, useAsDefault, msgError );
4259 }
4260 
4261 
4262 
4263 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag )
4264 {
4265  return loadNamedStyle( theURI, resultFlag, false );
4266 }
4267 
4268 bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
4269 {
4270  bool rc = false;
4271 
4272  QString joinKey = mAuxiliaryLayerKey;
4273  if ( !key.isEmpty() )
4274  joinKey = key;
4275 
4276  if ( storage.isValid() && !joinKey.isEmpty() )
4277  {
4278  QgsAuxiliaryLayer *alayer = nullptr;
4279 
4280  int idx = fields().lookupField( joinKey );
4281 
4282  if ( idx >= 0 )
4283  {
4284  alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
4285 
4286  if ( alayer )
4287  {
4288  setAuxiliaryLayer( alayer );
4289  rc = true;
4290  }
4291  }
4292  }
4293 
4294  return rc;
4295 }
4296 
4298 {
4299  mAuxiliaryLayerKey.clear();
4300 
4301  if ( mAuxiliaryLayer )
4302  removeJoin( mAuxiliaryLayer->id() );
4303 
4304  if ( alayer )
4305  {
4306  addJoin( alayer->joinInfo() );
4307 
4308  if ( !alayer->isEditable() )
4309  alayer->startEditing();
4310 
4311  mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
4312  }
4313 
4314  mAuxiliaryLayer.reset( alayer );
4315  updateFields();
4316 }
4317 
4319 {
4320  return mAuxiliaryLayer.get();
4321 }
4322 
4324 {
4325  return mAuxiliaryLayer.get();
4326 }
4327 
4328 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB )
4329 {
4330  QgsDataSourceUri dsUri( theURI );
4331  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
4332  {
4333  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4334  if ( myLib )
4335  {
4336  loadStyle_t *loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4337  if ( loadStyleExternalMethod )
4338  {
4339  QString qml, errorMsg;
4340  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4341  if ( !qml.isEmpty() )
4342  {
4343  QDomDocument myDocument( QStringLiteral( "qgis" ) );
4344  myDocument.setContent( qml );
4345  resultFlag = importNamedStyle( myDocument, errorMsg );
4346  return QObject::tr( "Loaded from Provider" );
4347  }
4348  }
4349  }
4350  }
4351 
4352  return QgsMapLayer::loadNamedStyle( theURI, resultFlag );
4353 }
4354 
4355 QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
4356 {
4357  if ( mDataProvider )
4358  return mDataProvider->dependencies() + mDependencies;
4359  return mDependencies;
4360 }
4361 
4362 bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
4363 {
4364  QSet<QgsMapLayerDependency> deps;
4365  Q_FOREACH ( const QgsMapLayerDependency &dep, oDeps )
4366  {
4367  if ( dep.origin() == QgsMapLayerDependency::FromUser )
4368  deps << dep;
4369  }
4370  if ( hasDependencyCycle( deps ) )
4371  return false;
4372 
4373  QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
4374 
4375  // disconnect layers that are not present in the list of dependencies anymore
4376  Q_FOREACH ( const QgsMapLayerDependency &dep, mDependencies )
4377  {
4378  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4379  if ( !lyr )
4380  continue;
4381  disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::dataChanged );
4382  disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::dataChanged );
4384  disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::dataChanged );
4386  }
4387 
4388  // assign new dependencies
4389  if ( mDataProvider )
4390  mDependencies = mDataProvider->dependencies() + deps;
4391  else
4392  mDependencies = deps;
4393  emit dependenciesChanged();
4394 
4395  // connect to new layers
4396  Q_FOREACH ( const QgsMapLayerDependency &dep, mDependencies )
4397  {
4398  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4399  if ( !lyr )
4400  continue;
4406  }
4407 
4408  // if new layers are present, emit a data change
4409  if ( ! toAdd.isEmpty() )
4410  emit dataChanged();
4411 
4412  return true;
4413 }
4414 
4415 QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
4416 {
4417  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4418  return nullptr;
4419 
4420  QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
4421 
4422  // make sure provider constraints are always present!
4423  if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
4424  {
4425  constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
4426  }
4427 
4428  return constraints;
4429 }
4430 
4431 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
4432 {
4433  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
4434 
4435  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4436  return m;
4437 
4438  QString name = mFields.at( fieldIndex ).name();
4439 
4440  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
4441  for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
4442  {
4443  if ( conIt.key().first == name )
4444  {
4445  m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
4446  }
4447  }
4448 
4449  return m;
4450 }
4451 
4453 {
4454  if ( index < 0 || index >= mFields.count() )
4455  return;
4456 
4457  QString name = mFields.at( index ).name();
4458 
4459  // add constraint to existing constraints
4460  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
4461  constraints |= constraint;
4462  mFieldConstraints.insert( name, constraints );
4463 
4464  mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
4465 
4466  updateFields();
4467 }
4468 
4470 {
4471  if ( index < 0 || index >= mFields.count() )
4472  return;
4473 
4474  QString name = mFields.at( index ).name();
4475 
4476  // remove constraint from existing constraints
4477  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
4478  constraints &= ~constraint;
4479  mFieldConstraints.insert( name, constraints );
4480 
4481  mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
4482 
4483  updateFields();
4484 }
4485 
4486 QString QgsVectorLayer::constraintExpression( int index ) const
4487 {
4488  if ( index < 0 || index >= mFields.count() )
4489  return QString();
4490 
4491  return mFields.at( index ).constraints().constraintExpression();
4492 }
4493 
4494 QString QgsVectorLayer::constraintDescription( int index ) const
4495 {
4496  if ( index < 0 || index >= mFields.count() )
4497  return QString();
4498 
4499  return mFields.at( index ).constraints().constraintDescription();
4500 }
4501 
4502 void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
4503 {
4504  if ( index < 0 || index >= mFields.count() )
4505  return;
4506 
4507  if ( expression.isEmpty() )
4508  {
4509  mFieldConstraintExpressions.remove( mFields.at( index ).name() );
4510  }
4511  else
4512  {
4513  mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
4514  }
4515  updateFields();
4516 }
4517 
4519 {
4520  if ( index < 0 || index >= mFields.count() )
4521  return;
4522 
4523  if ( setup.isNull() )
4524  mFieldWidgetSetups.remove( mFields.at( index ).name() );
4525  else
4526  mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
4527  updateFields();
4528 }
4529 
4531 {
4532 
4533  if ( index < 0 || index >= mFields.count() )
4534  return QgsEditorWidgetSetup();
4535 
4536  return mFields.at( index ).editorWidgetSetup();
4537 }
4538 
4539 QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
4540 {
4542  if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
4543  {
4544  if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() == true )
4545  {
4546  // try to load from custom properties
4547  QgsPalLayerSettings settings;
4548  settings.readFromLayerCustomProperties( this );
4549  labeling = new QgsVectorLayerSimpleLabeling( settings );
4550  }
4551 
4552  // also clear old-style labeling config
4553  removeCustomProperty( QStringLiteral( "labeling" ) );
4554  Q_FOREACH ( const QString &key, customPropertyKeys() )
4555  {
4556  if ( key.startsWith( QLatin1String( "labeling/" ) ) )
4557  removeCustomProperty( key );
4558  }
4559  }
4560 
4561  return labeling;
4562 }
4563 
4565 {
4566  mReadExtentFromXml = readExtentFromXml;
4567 }
4568 
4570 {
4571  return mReadExtentFromXml;
4572 }
4573 
4574 void QgsVectorLayer::onDirtyTransaction( const QString &sql )
4575 {
4577  if ( tr && mEditBuffer )
4578  {
4579  qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql );
4580  }
4581 }
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
void setExtent(const QgsRectangle &rect) override
Set the extent.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
Origin origin() const
Return the dependency origin.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:176
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 (...
QgsActionManager * actions()
Get all layer actions defined on this layer.
QgsFeatureId id
Definition: qgsfeature.h:71
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write the symbology for the layer into the docment provided.
double xOffset
Horizontal offset of label.
QString encoding() const
Get encoding which is used for accessing data.
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
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.
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...
A rectangle specified with double values.
Definition: qgsrectangle.h:39
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
Base class for all map layer types.
Definition: qgsmaplayer.h:56
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 setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
QgsVectorLayerFeatureCounter * countSymbolFeatures()
Count features for symbols.
void update(const QgsFields &fields)
Update the configuration with the given fields.
void setRenderer(QgsFeatureRenderer *r)
Set 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
void setExcludeAttributesWms(const QSet< QString > &att)
A set of attributes that are not advertised in WMS requests with QGIS server.
QVariantMap config() const
int size() const
Return number of items.
Definition: qgsfields.cpp:120
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
Get field&#39;s origin (value from an enumeration)
Definition: qgsfields.cpp:171
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
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.
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 committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
bool isValid() const
Returns the status of the auxiliary storage currently definied.
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.
ConstraintStrength constraintStrength(Constraint constraint) const
Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint is not pres...
QString name
Definition: qgsfield.h:56
int splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
int precision
Definition: qgsfield.h:54
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field index.
virtual bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Write vector layer specific state to project file Dom node.
bool isValid() const
Returns if this default value should be applied.
bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom, bool skipDefaultValue=false)
Change feature&#39;s geometry.
void beforeRollBack()
Is emitted, before changes are rolled back.
virtual QgsWkbTypes::Type wkbType() const override=0
Returns the geometry type which is returned by this layer.
bool hasParam(const QString &key) const
Test if param exists (generic mode)
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:55
QStringList customPropertyKeys() const
Returns list of all keys within custom properties.
virtual void resolveReferences(QgsProject *project) override
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects...
double angleOffset
Label rotation, in degrees clockwise.
QString mapTipTemplate() const
The mapTip is a pretty, html representation for feature information.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
QString alias
Definition: qgsfield.h:57
QgsMapLayerLegend * legend() const
Can be null.
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.
The QgsDefaultValue class provides a container for managing client side default values for fields...
Constraint
Constraints which may be present on a field.
int addPart(const QList< QgsPointXY > &ring)
Adds a new part polygon to a multipart feature.
QSet< QString > excludeAttributesWfs() const
A set of attributes that are not advertised in WFS requests with QGIS server.
Field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfields.h:51
Setting options for loading vector layers.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures(QProgressDialog *dialog)
Constructor.
bool deleteFeature(QgsFeatureId fid)
Delete 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:37
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:544
QList< QgsRelation > referencingRelations(const QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Get 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.
void attributeDeleted(int idx)
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:549
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:124
QVariant minimumValue(int index) const override
Returns the minimum value for an attribute column or an invalid variant in case of error...
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).
void invertSelectionInRectangle(QgsRectangle &rect)
Invert selection of features found within the search rectangle (in layer&#39;s coordinates) ...
QgsFeature getFeature(QgsFeatureId fid) const
Query the layer for the feature with the given id.
bool commitChanges()
Attempts to commit any changes to disk.
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
int selectedFeatureCount() const
The number of features that are selected in this layer.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
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()
Make 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.
VertexMarkerType
Editing vertex markers.
void removeExpressionField(int index)
Remove an expression field.
void setFeatureBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering each feature.
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:66
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
Remove from current selection.
static void mergeScaleDependencies(int mScaleMinDenom, int mScaleMaxDenom, QgsStringMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
QString comment
Definition: qgsfield.h:55
virtual void resolveReferences(QgsProject *project)
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects...
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
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 ...
bool deleteAttributes(QList< int > attrs)
Deletes a list of attribute fields (but does not commit it)
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource)
Creates a new instance of a provider.
double yOffset
Vertical offset of label.
void setLabeling(QgsAbstractVectorLayerLabeling *labeling)
Set labeling configuration.
void readCustomSymbology(const QDomElement &element, QString &errorMessage)
Signal emitted whenever the symbology (QML-file) for this layer is being read.
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 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
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
Type type() const
Return the dependency type.
void selectByIds(const QgsFeatureIds &ids, SelectBehavior behavior=SetSelection)
Select 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:204
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:49
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer...
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:6
QgsEditorWidgetSetup editorWidgetSetup() const
Get the editor widget setup for the field.
Definition: qgsfield.cpp:290
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const override
Calculates a list of unique values contained within an attribute in the layer.
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all registered layers by layer ID.
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.
QList< double > getDoubleValues(const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr, QgsFeedback *feedback=nullptr) const
Fetches all double values from a specified field name or expression.
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.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
static const int EditingCapabilities
Bitmask of all provider&#39;s editing capabilities.
virtual ~QgsVectorLayer()
QgsFields fields
Definition: qgsfeature.h:73
void beforeCommitChanges()
Is 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:210
QgsFeatureList selectedFeatures() const
Get a copy of the user-selected features.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
This signal is 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)
This signal is emitted, when attributes are deleted from the provider.
int splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
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)...
QgsMapLayer::LayerType type() const
Returns the type of the layer.
int count() const
Return number of items.
Definition: qgsfields.cpp:115
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:443
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present for a specified field index.
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
void invertSelection()
Select not selected features and deselect 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:142
It has not been specified where the field comes from.
Definition: qgsfields.h:48
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.
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
Return the conditional styles that are set for this layer.
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:145
void setAuxiliaryLayer(QgsAuxiliaryLayer *layer=nullptr)
Sets the current auxiliary layer.
int length
Definition: qgsfield.h:53
static QgsTaskManager * taskManager()
Returns the application&#39;s task manager, used for managing application wide background task handling...
void dataChanged()
This is emitted whenever an asynchronous operation has finished and the data should be redrawn...
Interface that can be optionally attached to an iterator so its nextFeature() implementaton can check...
Base class for feedback objects to be used for cancelation of something running in a worker thread...
Definition: qgsfeedback.h:44
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:1111
void setExcludeAttributesWfs(const QSet< QString > &att)
A set of attributes that are not advertised in WFS requests with QGIS server.
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Return new instance of QgsMapLayerRenderer that will be used for rendering of given context...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Update the data source of the layer.
QgsRectangle sourceExtent() const override
Returns the extent of all geometries from the source.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
bool readSymbology(const QDomNode &layerNode, QString &errorMessage, const QgsReadWriteContext &context) override
Read the symbology for the current layer from the Dom node supplied.
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:67
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.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
void setSize(double size)
Sets the size for rendered text.
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 deselect(const QgsFeatureId featureId)
Deselect feature by its ID.
#define FALLTHROUGH
Definition: qgis.h:512
const QgsFeatureIds & selectedFeatureIds() const
Return reference to identifiers of selected features.
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)
Stop editing and discard the edits.
void attributeAdded(int idx)
QgsFields fields() const override
Returns the list of fields of this layer.
int removeParam(const QString &key)
Remove generic param (generic mode)
void select(QgsFeatureId featureId)
Select feature by its ID.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:38
QgsRectangle extent() const override
Returns the extent of the layer.
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:103
void featureBlendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when setFeatureBlendMode() is called.
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
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:1150
void beforeModifiedCheck() const
Is emitted, when layer is checked for modifications. Use for last-minute additions.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Get an iterator of the selected features.
QString dataComment() const
Returns a description for this layer as defined in the data provider.
QList< QgsRelation > referencingRelations(int idx) const
Get relations, where the foreign key is on this layer.
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
long featureCount() const override
Returns feature count including changes which have not yet been committed If you need only the count ...
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, const bool clearAndSelect)
This signal is emitted when selection was changed.
static QString geometryDisplayString(GeometryType type)
Return a display string for a geometry type.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:138
virtual void setExtent(const QgsRectangle &rect)
Set 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...
void dirtied(const QString &sql)
Emitted if a sql query is executed and the underlying data is modified.
QString extentSectionHtml() const
Formats the "Extents" section according to a metadata object.
double opacity() const
Returns the opacity for the vector layer, where opacity is a value between 0 (totally transparent) an...
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
This signal is emitted, when features are added to the provider.
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.
QgsWkbTypes::Type wkbType() const override
Returns the WKBType or WKBUnknown in case of error.
Defines left outer join from our vector layer to some other vector layer.
QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
virtual bool deleteAttribute(int attr)
Delete an attribute field (but does not commit it)
void editingStopped()
Is emitted, when edited changes successfully have been written to the data provider.
void beforeEditingStarted()
Is 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:663
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)...
void setColor(const QColor &color)
Sets the color that text will be rendered in.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
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 isSpatial() const override
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
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.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
int addRing(const QVector< QgsPointXY > &ring, QgsFeatureId *featureId=nullptr)
Adds a ring to polygon/multipolygon features.
Reads and writes project states.
Definition: qgsproject.h:81
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...
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:69
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Is emitted whenever a geometry change is done in the edit buffer.
bool setReadOnly(bool readonly=true)
Make layer read-only (editing disabled) or not.
virtual QString loadNamedStyle(const QString &theURI, bool &resultFlag, bool loadFromLocalDb)
Load a named style from file/local db/datasource db.
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
QgsFeatureRenderer * renderer()
Return renderer.
x-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.
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)
Is 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
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg)
Import the properties of this layer from a QDomDocument.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
QgsEditFormConfig editFormConfig() const
Get 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.
void rendererChanged()
Signal emitted when renderer is changed.
Single scope for storing variables and functions for use within a QgsExpressionContext.
double minimumScale() const
Returns the minimum map scale (i.e.
Fast access to features using their ID.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
QgsRelationManager relationManager
Definition: qgsproject.h:91
Whether diagram features act as obstacles for other diagrams/labels.
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:1114
#define cast_to_fptr(f)
Definition: qgis.h:146
void raiseError(const QString &msg)
Signals an error related to this vector layer.
Add selection to current selection.
void editingStarted()
Is emitted, when editing on this layer has started.
void setName(const QString &name)
Set the display name of the layer.
QgsAttributeList pkAttributeList() const
Returns list of attributes making up the primary key.
QString capabilitiesString() const
Capabilities for this layer, comma separated and translated.
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y. (Useful to assist vertex editing.)
QVariant calculate(Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr) const
Calculates the value of an aggregate.
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
QgsWkbTypes::GeometryType type() const
Returns type of the geometry as a QgsWkbTypes::GeometryType.
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.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
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)
This signal is emitted, when attribute value changes are saved to the provider.
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.
bool hasDependencyCycle(const QSet< QgsMapLayerDependency > &layers) const
Checks whether a new set of dependencies will introduce a cycle.
Definition for a property.
Definition: qgsproperty.h:46
void fullExtentCalculated()
This is emitted whenever the worker thread has fully calculated the PostGIS extents for this layer...
QgsGeometry::OperationResult addPart(const QList< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
const QgsDiagramRenderer * diagramRenderer() const
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.
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, whan 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.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
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:25
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:126
virtual void reload() override
Synchronises with changes in the datasource.
QString uri(bool expandAuthConfig=true) const
return complete uri
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
void selectByRect(QgsRectangle &rect, SelectBehavior behavior=SetSelection)
Select 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.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void relationsLoaded()
This signal is 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.
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:111
QVector< QgsPoint > QgsPointSequence
void combineExtentWith(const QgsRectangle &rect)
Expand the rectangle so that covers both the original rectangle and the given rectangle.
QString sourceName() const override
Returns a friendly display name for the source.
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:137
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.
QVariant maximumValue(int index) const override
Returns the maximum value for an attribute column or an invalid variant in case of error...
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)...
QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters &parameters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr) const
Calculates an aggregated value from the layer&#39;s features.
QgsAttributeTableConfig attributeTableConfig() const
Get the attribute table configuration object.
void selectByExpression(const QString &expression, SelectBehavior behavior=SetSelection)
Select matching features using an expression.
static void logMessage(const QString &message, const QString &tag=QString(), MessageLevel level=QgsMessageLog::WARNING)
add a message to the instance (and create it if necessary)
virtual bool readXml(const QDomNode &layer_node, const QgsReadWriteContext &context) override
Reads vector layer specific state from project file Dom node.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
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.
Contains information about the context of a rendering operation.
QgsFieldConstraints constraints
Definition: qgsfield.h:59
bool updateFeature(const QgsFeature &feature, bool skipDefaultValues=false)
Updates an existing feature.
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.
const_iterator constBegin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfields.cpp:207
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)
Set feature IDs that should be fetched.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
virtual QSet< QgsMapLayerDependency > dependencies() const override
Gets the list of dependencies.
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.
QgsGeometry::OperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1117
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
QString source() const
Returns the source for the layer.
const QgsDiagramLayerSettings * diagramLayerSettings() const
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...
ConstraintStrength
Strength of constraints.
Holder for the widget type and its configuration for a field.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
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.
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...
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 appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
This signal is emitted, when attributes are added to the provider.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=0) override
Adds a list of features to the sink.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:383
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
virtual QString dataComment() const
Return a short comment for the data that this provider is providing access to (e.g.
This class represents a coordinate reference system (CRS).
QString layerId() const
Return the ID of the layer this dependency depends on.
virtual QString subsetString() const
Get the string (typically sql) used to define a subset of the layer.
friend class QgsVectorLayerEditBuffer
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
void removeFieldAlias(int index)
Removes an alias (a display name) for attributes to display in dialogs.
QgsVectorDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
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)
Set the string (typically sql) used to define a subset of the layer.
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:116
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)
Will return the named style corresponding to style id provided.
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Set the simplification settings for fast rendering of features.
bool readSld(const QDomNode &node, QString &errorMessage) override
Class for metadata formatter.
Basic implementation of the labeling interface.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
QgsFields pendingFields() const
Returns the list of fields of this layer.
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.
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())
Set the constraint expression for the specified field index.
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:121
bool mustStop() const override
return true if the iterator must stop as soon as possible
QList< QVariant > getValues(const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, QgsFeedback *feedback=nullptr) const
Fetches all values from a specified field name or expression.
bool isExpression
True if this label is made from a expression string, e.g., FieldName || &#39;mm&#39;.
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value (but does not commit it)
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
Edit failed due to invalid layer.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QUndoStack * undoStack()
Return 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)
QList< int > QgsAttributeList
Definition: qgsfield.h:27
virtual bool setDependencies(const QSet< QgsMapLayerDependency > &layers) override
Sets the list of dependencies.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
QString providerType() const
Return the provider type for this layer.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
void normalize()
Normalize the rectangle so it has non-negative width/height.
virtual bool deleteStyleFromDatabase(const QString &styleId, QString &msgError)
Delete a style from the database.
bool readStyle(const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context) override
Read the style for the current layer from the Dom node supplied.
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.
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)
return a new renderer - used by default in vector layers
Definition: qgsrenderer.cpp:75
Geometry is not required. It may still be returned if e.g. required for a filter condition.
void setEditFormConfig(const QgsEditFormConfig &editFormConfig)
Get the 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 PostgreSQL/RDBMS datasource URI.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
This signal is emitted, when geometry changes are saved to the provider.
A vector of attributes.
Definition: qgsattributes.h:58
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=0) override
Adds a single feature to the sink.
This class models dependencies with or between map layers.
QString displayExpression() const
Get the preview expression, used to create a human readable preview string.
void layerModified()
This signal is 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.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:255
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.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write just the style information for the layer into the document.
Field is calculated from an expression.
Definition: qgsfields.h:52
void updatedFields()
Is 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.
QgsCoordinateReferenceSystem sourceCrs() const override
Returns the coordinate reference system for features in the source.
EditResult
Result of an edit operation.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Set the attribute table configuration object.
void layerModified()
This signal is emitted when modifications has been done on layer.
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:36
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.
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:58
void set(const QgsPointXY &p1, const QgsPointXY &p2)
Sets the rectangle from two QgsPoints.
QString authid() const
Returns the authority identifier for the CRS.
QgsAttributes attributes
Definition: qgsfeature.h:72
static QgsAbstractVectorLayerLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Try to create instance of an implementation based on the XML data.
virtual QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
Aggregate
Available aggregates to calculate.
Used by QgsVectorLayer::countSymbolFeatures() to provide an interruption checker. ...
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:145
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Set flags that affect how features will be fetched.
void setReadExtentFromXml(bool readExtentFromXml)
Flag allowing to indicate if the extent has to be read from the XML document when data source has no ...
QString joinLayerId() const
ID of the joined layer - may be used to resolve reference to the joined layer.
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.
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError)
Save 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.
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...
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as named style in a QDomDocument.