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