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