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