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