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