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