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