QGIS API Documentation  2.99.0-Master (7fe5405)
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 pkeyElem = pkeyNode.toElement();
1389  if ( !pkeyElem.isNull() )
1390  {
1391  QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1392  if ( !encodingString.isEmpty() )
1393  {
1394  mDataProvider->setEncoding( encodingString );
1395  }
1396  }
1397 
1398  //load vector joins
1399  if ( !mJoinBuffer )
1400  {
1401  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1402  connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
1403  }
1404  mJoinBuffer->readXml( layer_node );
1405 
1406  updateFields();
1407  connect( QgsProject::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1408 
1409  QString errorMsg;
1410  if ( !readSymbology( layer_node, errorMsg ) )
1411  {
1412  return false;
1413  }
1414 
1415  readStyleManager( layer_node );
1416 
1417  QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1418  QDomNodeList depsNodes = depsNode.childNodes();
1419  QSet<QgsMapLayerDependency> sources;
1420  for ( int i = 0; i < depsNodes.count(); i++ )
1421  {
1422  QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1423  sources << QgsMapLayerDependency( source );
1424  }
1425  setDependencies( sources );
1426 
1428 
1429  return mValid; // should be true if read successfully
1430 
1431 } // void QgsVectorLayer::readXml
1432 
1433 
1434 void QgsVectorLayer::setDataSource( const QString& dataSource, const QString& baseName, const QString& provider, bool loadDefaultStyleFlag )
1435 {
1437 
1438  mDataSource = dataSource;
1439  mLayerName = capitalizeLayerName( baseName );
1440  setName( mLayerName );
1441  setDataProvider( provider );
1442 
1443  if ( !mValid )
1444  return;
1445 
1446  // Always set crs
1448 
1449  // reset style if loading default style, style is missing, or geometry type has changed
1450  if ( !renderer() || !legend() || geomType != geometryType() || loadDefaultStyleFlag )
1451  {
1452  // check if there is a default style / propertysheet defined
1453  // for this layer and if so apply it
1454  bool defaultLoadedFlag = false;
1455  if ( loadDefaultStyleFlag )
1456  {
1457  loadDefaultStyle( defaultLoadedFlag );
1458  }
1459 
1460  // if the default style failed to load or was disabled use some very basic defaults
1461  if ( !defaultLoadedFlag && hasGeometryType() )
1462  {
1463  // add single symbol renderer
1465  }
1466 
1468  }
1469 
1470  connect( QgsProject::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1471  emit repaintRequested();
1472 }
1473 
1474 
1475 bool QgsVectorLayer::setDataProvider( QString const & provider )
1476 {
1477  mProviderKey = provider; // XXX is this necessary? Usually already set
1478  // XXX when execution gets here.
1479 
1480  //XXX - This was a dynamic cast but that kills the Windows
1481  // version big-time with an abnormal termination error
1482  delete mDataProvider;
1483  mDataProvider = ( QgsVectorDataProvider* )( QgsProviderRegistry::instance()->provider( provider, mDataSource ) );
1484  if ( !mDataProvider )
1485  {
1486  QgsDebugMsg( " unable to get data provider" );
1487  return false;
1488  }
1489 
1490  connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1491 
1492  QgsDebugMsg( "Instantiated the data provider plugin" );
1493 
1494  mValid = mDataProvider->isValid();
1495  if ( !mValid )
1496  {
1497  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1498  return false;
1499  }
1500 
1501  // TODO: Check if the provider has the capability to send fullExtentCalculated
1503 
1504  // get and store the feature type
1505  mWkbType = mDataProvider->wkbType();
1506 
1507  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1508  connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
1509  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1510  updateFields();
1511 
1512  if ( mProviderKey == QLatin1String( "postgres" ) )
1513  {
1514  QgsDebugMsg( "Beautifying layer name " + name() );
1515 
1516  // adjust the display name for postgres layers
1517  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1518  if ( reg.indexIn( name() ) >= 0 )
1519  {
1520  QStringList stuff = reg.capturedTexts();
1521  QString lName = stuff[1];
1522 
1523  const QMap<QString, QgsMapLayer*> &layers = QgsProject::instance()->mapLayers();
1524 
1525  QMap<QString, QgsMapLayer*>::const_iterator it;
1526  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1527  ;
1528 
1529  if ( it != layers.constEnd() && stuff.size() > 2 )
1530  {
1531  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1532  }
1533 
1534  if ( !lName.isEmpty() )
1535  setName( lName );
1536  }
1537 
1538  QgsDebugMsg( "Beautified layer name " + name() );
1539 
1540  // deal with unnecessary schema qualification to make v.in.ogr happy
1541  mDataSource = mDataProvider->dataSourceUri();
1542  }
1543  else if ( mProviderKey == QLatin1String( "osm" ) )
1544  {
1545  // make sure that the "observer" has been removed from URI to avoid crashes
1546  mDataSource = mDataProvider->dataSourceUri();
1547  }
1548  else if ( provider == QLatin1String( "ogr" ) )
1549  {
1550  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1551  mDataSource = mDataProvider->dataSourceUri();
1552  if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1553  mDataSource.chop( 10 );
1554  }
1555 
1556  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::dataChanged );
1557  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
1558 
1559  return true;
1560 } // QgsVectorLayer:: setDataProvider
1561 
1562 
1563 
1564 
1565 /* virtual */
1566 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
1567  QDomDocument & document ) const
1568 {
1569  // first get the layer element so that we can append the type attribute
1570 
1571  QDomElement mapLayerNode = layer_node.toElement();
1572 
1573  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1574  {
1575  QgsDebugMsg( "can't find <maplayer>" );
1576  return false;
1577  }
1578 
1579  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "vector" ) );
1580 
1581  // set the geometry type
1582  mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1583 
1584  // add provider node
1585  if ( mDataProvider )
1586  {
1587  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1588  provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1589  QDomText providerText = document.createTextNode( providerType() );
1590  provider.appendChild( providerText );
1591  layer_node.appendChild( provider );
1592  }
1593 
1594  //save joins
1595  mJoinBuffer->writeXml( layer_node, document );
1596 
1597  // dependencies
1598  QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1599  Q_FOREACH ( const QgsMapLayerDependency& dep, dependencies() )
1600  {
1602  continue;
1603  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1604  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1605  dependenciesElement.appendChild( depElem );
1606  }
1607  layer_node.appendChild( dependenciesElement );
1608 
1609  // change dependencies
1610  QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1611  Q_FOREACH ( const QgsMapLayerDependency& dep, dependencies() )
1612  {
1614  continue;
1615  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1616  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1617  dataDependenciesElement.appendChild( depElem );
1618  }
1619  layer_node.appendChild( dataDependenciesElement );
1620 
1621  // save expression fields
1622  mExpressionFieldBuffer->writeXml( layer_node, document );
1623 
1624  writeStyleManager( layer_node, document );
1625 
1626  // renderer specific settings
1627  QString errorMsg;
1628  return writeSymbology( layer_node, document, errorMsg );
1629 } // bool QgsVectorLayer::writeXml
1630 
1631 
1632 bool QgsVectorLayer::readSymbology( const QDomNode& layerNode, QString& errorMessage )
1633 {
1634  if ( !mExpressionFieldBuffer )
1635  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1636  mExpressionFieldBuffer->readXml( layerNode );
1637 
1638  updateFields();
1639 
1640  readStyle( layerNode, errorMessage );
1641 
1642  mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
1643  mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
1644 
1645  QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
1646 
1647  // Try to migrate pre QGIS 3.0 display field property
1648  if ( mFields.lookupField( displayField ) < 0 )
1649  {
1650  // if it's not a field, it's a maptip
1651  if ( mMapTipTemplate.isEmpty() )
1652  mMapTipTemplate = displayField;
1653  }
1654  else
1655  {
1656  if ( mDisplayExpression.isEmpty() )
1657  mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
1658  }
1659 
1660  // process the attribute actions
1661  mActions->readXml( layerNode );
1662 
1663  QDomNode annotationFormNode = layerNode.namedItem( QStringLiteral( "annotationform" ) );
1664  if ( !annotationFormNode.isNull() )
1665  {
1666  QDomElement e = annotationFormNode.toElement();
1667  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1668  }
1669 
1670  mAttributeAliasMap.clear();
1671  QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
1672  if ( !aliasesNode.isNull() )
1673  {
1674  QDomElement aliasElem;
1675 
1676  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
1677  for ( int i = 0; i < aliasNodeList.size(); ++i )
1678  {
1679  aliasElem = aliasNodeList.at( i ).toElement();
1680 
1681  QString field;
1682  if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
1683  {
1684  field = aliasElem.attribute( QStringLiteral( "field" ) );
1685  }
1686  else
1687  {
1688  int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
1689 
1690  if ( index >= 0 && index < fields().count() )
1691  field = fields().at( index ).name();
1692  }
1693 
1694  mAttributeAliasMap.insert( field, aliasElem.attribute( QStringLiteral( "name" ) ) );
1695  }
1696  }
1697 
1698  // default expressions
1699  mDefaultExpressionMap.clear();
1700  QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
1701  if ( !defaultsNode.isNull() )
1702  {
1703  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
1704  for ( int i = 0; i < defaultNodeList.size(); ++i )
1705  {
1706  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
1707 
1708  QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
1709  QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
1710  if ( field.isEmpty() || expression.isEmpty() )
1711  continue;
1712 
1713  mDefaultExpressionMap.insert( field, expression );
1714  }
1715  }
1716 
1717  // constraints
1718  mFieldConstraints.clear();
1719  mFieldConstraintStrength.clear();
1720  QDomNode constraintsNode = layerNode.namedItem( "constraints" );
1721  if ( !constraintsNode.isNull() )
1722  {
1723  QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( "constraint" );
1724  for ( int i = 0; i < constraintNodeList.size(); ++i )
1725  {
1726  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
1727 
1728  QString field = constraintElem.attribute( "field", QString() );
1729  int constraints = constraintElem.attribute( "constraints", QString( "0" ) ).toInt();
1730  if ( field.isEmpty() || constraints == 0 )
1731  continue;
1732 
1733  mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
1734 
1735  int uniqueStrength = constraintElem.attribute( "unique_strength", QString( "1" ) ).toInt();
1736  int notNullStrength = constraintElem.attribute( "notnull_strength", QString( "1" ) ).toInt();
1737  int expStrength = constraintElem.attribute( "exp_strength", QString( "1" ) ).toInt();
1738 
1739  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
1740  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
1741  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
1742  }
1743  }
1744  mFieldConstraintExpressions.clear();
1745  QDomNode constraintExpressionsNode = layerNode.namedItem( "constraintExpressions" );
1746  if ( !constraintExpressionsNode.isNull() )
1747  {
1748  QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( "constraint" );
1749  for ( int i = 0; i < constraintNodeList.size(); ++i )
1750  {
1751  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
1752 
1753  QString field = constraintElem.attribute( "field", QString() );
1754  QString exp = constraintElem.attribute( "exp", QString() );
1755  QString desc = constraintElem.attribute( "desc", QString() );
1756  if ( field.isEmpty() || exp.isEmpty() )
1757  continue;
1758 
1759  mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
1760  }
1761  }
1762 
1763  updateFields();
1764 
1765  //Attributes excluded from WMS and WFS
1766  mExcludeAttributesWMS.clear();
1767  QDomNode excludeWMSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWMS" ) );
1768  if ( !excludeWMSNode.isNull() )
1769  {
1770  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
1771  for ( int i = 0; i < attributeNodeList.size(); ++i )
1772  {
1773  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1774  }
1775  }
1776 
1777  mExcludeAttributesWFS.clear();
1778  QDomNode excludeWFSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWFS" ) );
1779  if ( !excludeWFSNode.isNull() )
1780  {
1781  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
1782  for ( int i = 0; i < attributeNodeList.size(); ++i )
1783  {
1784  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1785  }
1786  }
1787 
1788  // Load editor widget configuration
1789  QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
1790 
1791  QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
1792 
1793  for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
1794  {
1795  const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
1796  const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
1797 
1798  QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
1799 
1800  const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
1801  const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
1802  const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
1803  QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
1804  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
1805  mFieldWidgetSetups[fieldName] = setup;
1806  }
1807 
1808  mEditFormConfig.readXml( layerNode );
1809 
1810  mAttributeTableConfig.readXml( layerNode );
1811 
1812  mConditionalStyles->readXml( layerNode );
1813 
1814  readCustomProperties( layerNode, QStringLiteral( "variable" ) );
1815 
1816  QDomElement mapLayerNode = layerNode.toElement();
1817  if ( mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
1818  mReadOnly = true;
1819 
1820  updateFields();
1821 
1822  return true;
1823 }
1824 
1825 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage )
1826 {
1827  bool result = true;
1828  emit readCustomSymbology( node.toElement(), errorMessage );
1829 
1830  if ( hasGeometryType() )
1831  {
1832  // try renderer v2 first
1833  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1834  if ( !rendererElement.isNull() )
1835  {
1836  QgsFeatureRenderer* r = QgsFeatureRenderer::load( rendererElement );
1837  if ( r )
1838  {
1839  setRenderer( r );
1840  }
1841  else
1842  {
1843  result = false;
1844  }
1845  }
1846  else
1847  {
1849  if ( r )
1850  {
1851  setRenderer( r );
1852  }
1853  }
1854 
1855  // make sure layer has a renderer - if none exists, fallback to a default renderer
1856  if ( !renderer() )
1857  {
1859  }
1860 
1861  QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
1862  if ( !labelingElement.isNull() )
1863  {
1866  }
1867 
1868  // get and set the blend mode if it exists
1869  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1870  if ( !blendModeNode.isNull() )
1871  {
1872  QDomElement e = blendModeNode.toElement();
1873  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1874  }
1875 
1876  // get and set the feature blend mode if it exists
1877  QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
1878  if ( !featureBlendModeNode.isNull() )
1879  {
1880  QDomElement e = featureBlendModeNode.toElement();
1881  setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1882  }
1883 
1884  // get and set the layer transparency if it exists
1885  QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
1886  if ( !layerTransparencyNode.isNull() )
1887  {
1888  QDomElement e = layerTransparencyNode.toElement();
1889  setLayerTransparency( e.text().toInt() );
1890  }
1891 
1892  QDomElement e = node.toElement();
1893 
1894  // get the simplification drawing settings
1895  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
1896  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
1897  mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
1898  mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
1899  mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
1900 
1901  //also restore custom properties (for labeling-ng)
1902  readCustomProperties( node, QStringLiteral( "labeling" ) );
1903 
1904  //diagram renderer and diagram layer settings
1905  delete mDiagramRenderer;
1906  mDiagramRenderer = nullptr;
1907  QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
1908  if ( !singleCatDiagramElem.isNull() )
1909  {
1910  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1911  mDiagramRenderer->readXml( singleCatDiagramElem, this );
1912  }
1913  QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
1914  if ( !linearDiagramElem.isNull() )
1915  {
1916  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
1917  mDiagramRenderer->readXml( linearDiagramElem, this );
1918  }
1919 
1920  if ( mDiagramRenderer )
1921  {
1922  QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
1923  if ( !diagramSettingsElem.isNull() )
1924  {
1925  delete mDiagramLayerSettings;
1926  mDiagramLayerSettings = new QgsDiagramLayerSettings();
1927  mDiagramLayerSettings->readXml( diagramSettingsElem, this );
1928  }
1929  }
1930  }
1931  return result;
1932 }
1933 
1934 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1935 {
1936  ( void )writeStyle( node, doc, errorMessage );
1937 
1938  QDomElement fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
1939  node.appendChild( fieldConfigurationElement );
1940 
1941  int index = 0;
1942  Q_FOREACH ( const QgsField& field, mFields )
1943  {
1944 
1945  QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
1946  fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
1947 
1948  fieldConfigurationElement.appendChild( fieldElement );
1949 
1950  QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
1951 
1952  // TODO : wrap this part in an if to only save if it was user-modified
1953  QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
1954  fieldElement.appendChild( editWidgetElement );
1955  editWidgetElement.setAttribute( "type", field.editorWidgetSetup().type() );
1956  QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
1957 
1958  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config() , doc ) );
1959  editWidgetElement.appendChild( editWidgetConfigElement );
1960  // END TODO : wrap this part in an if to only save if it was user-modified
1961 
1962  ++index;
1963  }
1964 
1965  QDomElement afField = doc.createElement( QStringLiteral( "annotationform" ) );
1966  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
1967  afField.appendChild( afText );
1968  node.appendChild( afField );
1969 
1970  //attribute aliases
1971  QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
1972  Q_FOREACH ( const QgsField& field, mFields )
1973  {
1974  QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
1975  aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
1976  aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
1977  aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
1978  aliasElem.appendChild( aliasEntryElem );
1979  }
1980  node.appendChild( aliasElem );
1981 
1982  //exclude attributes WMS
1983  QDomElement excludeWMSElem = doc.createElement( QStringLiteral( "excludeAttributesWMS" ) );
1984  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
1985  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
1986  {
1987  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
1988  QDomText attrText = doc.createTextNode( *attWMSIt );
1989  attrElem.appendChild( attrText );
1990  excludeWMSElem.appendChild( attrElem );
1991  }
1992  node.appendChild( excludeWMSElem );
1993 
1994  //exclude attributes WFS
1995  QDomElement excludeWFSElem = doc.createElement( QStringLiteral( "excludeAttributesWFS" ) );
1996  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
1997  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
1998  {
1999  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2000  QDomText attrText = doc.createTextNode( *attWFSIt );
2001  attrElem.appendChild( attrText );
2002  excludeWFSElem.appendChild( attrElem );
2003  }
2004  node.appendChild( excludeWFSElem );
2005 
2006  //default expressions
2007  QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2008  Q_FOREACH ( const QgsField& field, mFields )
2009  {
2010  QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2011  defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2012  defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueExpression() );
2013  defaultsElem.appendChild( defaultElem );
2014  }
2015  node.appendChild( defaultsElem );
2016 
2017  // constraints
2018  QDomElement constraintsElem = doc.createElement( "constraints" );
2019  Q_FOREACH ( const QgsField& field, mFields )
2020  {
2021  QDomElement constraintElem = doc.createElement( "constraint" );
2022  constraintElem.setAttribute( "field", field.name() );
2023  constraintElem.setAttribute( "constraints", field.constraints().constraints() );
2024  constraintElem.setAttribute( "unique_strength", field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2025  constraintElem.setAttribute( "notnull_strength", field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2026  constraintElem.setAttribute( "exp_strength", field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2027  constraintsElem.appendChild( constraintElem );
2028  }
2029  node.appendChild( constraintsElem );
2030 
2031  // constraint expressions
2032  QDomElement constraintExpressionsElem = doc.createElement( "constraintExpressions" );
2033  Q_FOREACH ( const QgsField& field, mFields )
2034  {
2035  QDomElement constraintExpressionElem = doc.createElement( "constraint" );
2036  constraintExpressionElem.setAttribute( "field", field.name() );
2037  constraintExpressionElem.setAttribute( "exp", field.constraints().constraintExpression() );
2038  constraintExpressionElem.setAttribute( "desc", field.constraints().constraintDescription() );
2039  constraintExpressionsElem.appendChild( constraintExpressionElem );
2040  }
2041  node.appendChild( constraintExpressionsElem );
2042 
2043  // add attribute actions
2044  mActions->writeXml( node );
2045  mAttributeTableConfig.writeXml( node );
2046  mEditFormConfig.writeXml( node );
2047  mConditionalStyles->writeXml( node, doc );
2048 
2049  // save expression fields
2050  if ( !mExpressionFieldBuffer )
2051  {
2052  // can happen when saving style on a invalid layer
2054  dummy.writeXml( node, doc );
2055  }
2056  else
2057  mExpressionFieldBuffer->writeXml( node, doc );
2058 
2059  // save readonly state
2060  node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2061 
2062  // save preview expression
2063  QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2064  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2065  prevExpElem.appendChild( prevExpText );
2066  node.appendChild( prevExpElem );
2067 
2068  // save map tip
2069  QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2070  QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2071  mapTipElem.appendChild( mapTipText );
2072  node.toElement().appendChild( mapTipElem );
2073 
2074  return true;
2075 }
2076 
2077 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage ) const
2078 {
2079  QDomElement mapLayerNode = node.toElement();
2080 
2081  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2082 
2083  if ( hasGeometryType() )
2084  {
2085  if ( mRenderer )
2086  {
2087  QDomElement rendererElement = mRenderer->save( doc );
2088  node.appendChild( rendererElement );
2089  }
2090 
2091  if ( mLabeling )
2092  {
2093  QDomElement labelingElement = mLabeling->save( doc );
2094  node.appendChild( labelingElement );
2095  }
2096 
2097  // save the simplification drawing settings
2098  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2099  mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2100  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2101  mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2102  mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2103 
2104  //save customproperties (for labeling ng)
2105  writeCustomProperties( node, doc );
2106 
2107  // add the blend mode field
2108  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2109  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2110  blendModeElem.appendChild( blendModeText );
2111  node.appendChild( blendModeElem );
2112 
2113  // add the feature blend mode field
2114  QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2115  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2116  featureBlendModeElem.appendChild( featureBlendModeText );
2117  node.appendChild( featureBlendModeElem );
2118 
2119  // add the layer transparency
2120  QDomElement layerTransparencyElem = doc.createElement( QStringLiteral( "layerTransparency" ) );
2121  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
2122  layerTransparencyElem.appendChild( layerTransparencyText );
2123  node.appendChild( layerTransparencyElem );
2124 
2125  if ( mDiagramRenderer )
2126  {
2127  mDiagramRenderer->writeXml( mapLayerNode, doc, this );
2128  if ( mDiagramLayerSettings )
2129  mDiagramLayerSettings->writeXml( mapLayerNode, doc, this );
2130  }
2131  }
2132  return true;
2133 }
2134 
2135 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2136 {
2137  // get the Name element
2138  QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2139  if ( nameElem.isNull() )
2140  {
2141  errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2142  }
2143 
2144  if ( hasGeometryType() )
2145  {
2146  QgsFeatureRenderer* r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
2147  if ( !r )
2148  return false;
2149 
2150  setRenderer( r );
2151 
2152  // labeling
2153  readSldLabeling( node );
2154  }
2155  return true;
2156 }
2157 
2158 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, const QgsStringMap& props ) const
2159 {
2160  Q_UNUSED( errorMessage );
2161 
2162  // store the Name element
2163  QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
2164  nameNode.appendChild( doc.createTextNode( name() ) );
2165  node.appendChild( nameNode );
2166 
2167  QgsStringMap localProps = QgsStringMap( props );
2168  if ( hasScaleBasedVisibility() )
2169  {
2171  }
2172 
2173  if ( hasGeometryType() )
2174  {
2175  node.appendChild( mRenderer->writeSld( doc, name(), localProps ) );
2176  }
2177  return true;
2178 }
2179 
2180 
2182 {
2183  if ( !mEditBuffer || !mDataProvider )
2184  {
2185  return false;
2186  }
2187 
2188  updateExtents();
2189 
2190  bool result = mEditBuffer->changeGeometry( fid, geom );
2191 
2192  if ( result )
2193  updateExtents();
2194  return result;
2195 }
2196 
2197 
2198 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2199 {
2200  if ( !mEditBuffer || !mDataProvider )
2201  return false;
2202 
2203  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2204 }
2205 
2207 {
2208  if ( !mEditBuffer || !mDataProvider )
2209  return false;
2210 
2211  return mEditBuffer->addAttribute( field );
2212 }
2213 
2215 {
2216  if ( attIndex < 0 || attIndex >= fields().count() )
2217  return;
2218 
2219  QString name = fields().at( attIndex ).name();
2220  mFields[ attIndex ].setAlias( QString() );
2221  if ( mAttributeAliasMap.contains( name ) )
2222  {
2223  mAttributeAliasMap.remove( name );
2224  updateFields();
2225  mEditFormConfig.setFields( mFields );
2226  emit layerModified();
2227  }
2228 }
2229 
2230 bool QgsVectorLayer::renameAttribute( int index, const QString& newName )
2231 {
2232  if ( index < 0 || index >= fields().count() )
2233  return false;
2234 
2235  switch ( mFields.fieldOrigin( index ) )
2236  {
2238  {
2239  if ( mExpressionFieldBuffer )
2240  {
2241  int oi = mFields.fieldOriginIndex( index );
2242  mExpressionFieldBuffer->renameExpression( oi, newName );
2243  updateFields();
2244  return true;
2245  }
2246  else
2247  {
2248  return false;
2249  }
2250  }
2251 
2253  case QgsFields::OriginEdit:
2254 
2255  if ( !mEditBuffer || !mDataProvider )
2256  return false;
2257 
2258  return mEditBuffer->renameAttribute( index, newName );
2259 
2260  case QgsFields::OriginJoin:
2262  return false;
2263 
2264  }
2265 
2266  return false; // avoid warning
2267 }
2268 
2269 void QgsVectorLayer::setFieldAlias( int attIndex, const QString& aliasString )
2270 {
2271  if ( attIndex < 0 || attIndex >= fields().count() )
2272  return;
2273 
2274  QString name = fields().at( attIndex ).name();
2275 
2276  mAttributeAliasMap.insert( name, aliasString );
2277  mFields[ attIndex ].setAlias( aliasString );
2278  mEditFormConfig.setFields( mFields );
2279  emit layerModified(); // TODO[MD]: should have a different signal?
2280 }
2281 
2283 {
2284  if ( index < 0 || index >= fields().count() )
2285  return QString();
2286 
2287  return fields().at( index ).alias();
2288 }
2289 
2291 {
2292  if ( index >= 0 && index < mFields.count() )
2293  return mFields.at( index ).displayName();
2294  else
2295  return QString();
2296 }
2297 
2299 {
2300  QgsStringMap map;
2301  Q_FOREACH ( const QgsField& field, fields() )
2302  {
2303  if ( !field.alias().isEmpty() )
2304  map.insert( field.name(), field.alias() );
2305  }
2306  return map;
2307 }
2308 
2310 {
2311  if ( index < 0 || index >= fields().count() )
2312  return false;
2313 
2314  if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2315  {
2316  removeExpressionField( index );
2317  return true;
2318  }
2319 
2320  if ( !mEditBuffer || !mDataProvider )
2321  return false;
2322 
2323  return mEditBuffer->deleteAttribute( index );
2324 }
2325 
2326 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
2327 {
2328  bool deleted = false;
2329 
2330  // Remove multiple occurrences of same attribute
2331  attrs = attrs.toSet().toList();
2332 
2333  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2334 
2335  Q_FOREACH ( int attr, attrs )
2336  {
2337  if ( deleteAttribute( attr ) )
2338  {
2339  deleted = true;
2340  }
2341  }
2342 
2343  return deleted;
2344 }
2345 
2347 {
2348  if ( !mEditBuffer )
2349  return false;
2350 
2351  bool res = mEditBuffer->deleteFeature( fid );
2352  if ( res )
2353  {
2354  mSelectedFeatureIds.remove( fid ); // remove it from selection
2355  updateExtents();
2356  }
2357 
2358  return res;
2359 }
2360 
2362 {
2363  if ( !mEditBuffer )
2364  {
2365  QgsDebugMsg( "Cannot delete features (mEditBuffer==NULL)" );
2366  return false;
2367  }
2368 
2369  bool res = mEditBuffer->deleteFeatures( fids );
2370 
2371  if ( res )
2372  {
2373  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2374  updateExtents();
2375  }
2376 
2377  return res;
2378 }
2379 
2381 {
2382  QgsAttributeList pkAttributesList;
2383 
2384  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2385  for ( int i = 0; i < mFields.count(); ++i )
2386  {
2387  if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2388  providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
2389  pkAttributesList << i;
2390  }
2391 
2392  return pkAttributesList;
2393 }
2394 
2396 {
2397  return mDataProvider->featureCount() +
2398  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2399 }
2400 
2402 {
2403  mCommitErrors.clear();
2404 
2405  if ( !mDataProvider )
2406  {
2407  mCommitErrors << tr( "ERROR: no provider" );
2408  return false;
2409  }
2410 
2411  if ( !mEditBuffer )
2412  {
2413  mCommitErrors << tr( "ERROR: layer not editable" );
2414  return false;
2415  }
2416 
2417  emit beforeCommitChanges();
2418 
2419  bool success = mEditBuffer->commitChanges( mCommitErrors );
2420 
2421  if ( success )
2422  {
2423  delete mEditBuffer;
2424  mEditBuffer = nullptr;
2425  undoStack()->clear();
2426  emit editingStopped();
2427  }
2428  else
2429  {
2430  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QStringLiteral( "\n " ) ) ) );
2431  }
2432 
2433  if ( mCache )
2434  {
2435  mCache->deleteCachedGeometries();
2436  }
2437 
2438  updateFields();
2439  mDataProvider->updateExtents();
2440 
2441  mDataProvider->leaveUpdateMode();
2442 
2443  emit repaintRequested();
2444 
2445  return success;
2446 }
2447 
2448 QStringList QgsVectorLayer::commitErrors() const
2449 {
2450  return mCommitErrors;
2451 }
2452 
2453 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2454 {
2455  if ( !mEditBuffer )
2456  {
2457  return false;
2458  }
2459 
2460  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2461  !mEditBuffer->mAddedFeatures.isEmpty() ||
2462  !mEditBuffer->mChangedGeometries.isEmpty();
2463 
2464  emit beforeRollBack();
2465 
2466  mEditBuffer->rollBack();
2467 
2468  if ( isModified() )
2469  {
2470  // new undo stack roll back method
2471  // old method of calling every undo could cause many canvas refreshes
2472  undoStack()->setIndex( 0 );
2473  }
2474 
2475  updateFields();
2476 
2477  if ( deleteBuffer )
2478  {
2479  delete mEditBuffer;
2480  mEditBuffer = nullptr;
2481  undoStack()->clear();
2482  }
2483  emit editingStopped();
2484 
2485  if ( mCache )
2486  {
2487  mCache->deleteCachedGeometries();
2488  }
2489 
2490  if ( rollbackExtent )
2491  updateExtents();
2492 
2493  mDataProvider->leaveUpdateMode();
2494 
2495  emit repaintRequested();
2496  return true;
2497 }
2498 
2500 {
2501  return mSelectedFeatureIds.size();
2502 }
2503 
2505 {
2506  return mSelectedFeatureIds;
2507 }
2508 
2510 {
2511  QgsFeatureList features;
2512  QgsFeature f;
2513 
2514  if ( mSelectedFeatureIds.count() <= 8 )
2515  {
2516  // for small amount of selected features, fetch them directly
2517  // because request with FilterFids would go iterate over the whole layer
2518  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2519  {
2520  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2521  features << f;
2522  }
2523  }
2524  else
2525  {
2527 
2528  while ( it.nextFeature( f ) )
2529  {
2530  features.push_back( f );
2531  }
2532  }
2533 
2534  return features;
2535 }
2536 
2538 {
2539  if ( mSelectedFeatureIds.isEmpty() )
2540  return QgsFeatureIterator();
2541 
2544 
2545  if ( mSelectedFeatureIds.count() == 1 )
2546  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2547  else
2548  request.setFilterFids( mSelectedFeatureIds );
2549 
2550  return getFeatures( request );
2551 }
2552 
2553 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2554 {
2555  if ( !mEditBuffer || !mDataProvider )
2556  return false;
2557 
2558  bool res = mEditBuffer->addFeatures( features );
2559 
2560  if ( makeSelected )
2561  {
2562  QgsFeatureIds ids;
2563 
2564  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2565  ids << iter->id();
2566 
2567  selectByIds( ids );
2568  }
2569 
2570  updateExtents();
2571 
2572  return res;
2573 }
2574 
2575 
2576 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2577 {
2578  if ( !hasGeometryType() )
2579  return false;
2580 
2581  QMultiMap<double, QgsSnappingResult> snapResults;
2582  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2583 
2584  if ( result != 0 )
2585  {
2586  return false;
2587  }
2588 
2589  if ( snapResults.size() < 1 )
2590  {
2591  return false;
2592  }
2593 
2594  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
2595  point.setX( snap_it.value().snappedVertex.x() );
2596  point.setY( snap_it.value().snappedVertex.y() );
2597  return true;
2598 }
2599 
2600 
2601 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2602  QMultiMap<double, QgsSnappingResult>& snappingResults,
2603  QgsSnapper::SnappingType snap_to )
2604 {
2605  if ( !hasGeometryType() )
2606  return 1;
2607 
2608  if ( snappingTolerance <= 0 || !mDataProvider )
2609  {
2610  return 1;
2611  }
2612 
2613  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2614  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2615  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2616 
2617  int n = 0;
2618  QgsFeature f;
2619 
2620  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2621  {
2622  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2623  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2624  {
2625  QgsGeometry g = it.value();
2626  if ( g.boundingBox().intersects( searchRect ) )
2627  {
2628  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2629  ++n;
2630  }
2631  }
2632  }
2633  else
2634  {
2635  // snapping outside cached area
2636 
2638  .setFilterRect( searchRect )
2640  .setSubsetOfAttributes( QgsAttributeList() ) );
2641 
2642  while ( fit.nextFeature( f ) )
2643  {
2644  snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
2645  ++n;
2646  }
2647  }
2648 
2649  return n == 0 ? 2 : 0;
2650 }
2651 
2652 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2653  QgsFeatureId featureId,
2654  const QgsGeometry& geom,
2655  double sqrSnappingTolerance,
2656  QMultiMap<double, QgsSnappingResult>& snappingResults,
2657  QgsSnapper::SnappingType snap_to ) const
2658 {
2659  if ( geom.isEmpty() )
2660  {
2661  return;
2662  }
2663 
2664  int atVertex, beforeVertex, afterVertex;
2665  double sqrDistVertexSnap, sqrDistSegmentSnap;
2666  QgsPoint snappedPoint;
2667  QgsSnappingResult snappingResultVertex;
2668  QgsSnappingResult snappingResultSegment;
2669 
2670  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2671  {
2672  snappedPoint = geom.closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2673  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2674  {
2675  snappingResultVertex.snappedVertex = snappedPoint;
2676  snappingResultVertex.snappedVertexNr = atVertex;
2677  snappingResultVertex.beforeVertexNr = beforeVertex;
2678  if ( beforeVertex != -1 ) // make sure the vertex is valid
2679  {
2680  snappingResultVertex.beforeVertex = geom.vertexAt( beforeVertex );
2681  }
2682  snappingResultVertex.afterVertexNr = afterVertex;
2683  if ( afterVertex != -1 ) // make sure the vertex is valid
2684  {
2685  snappingResultVertex.afterVertex = geom.vertexAt( afterVertex );
2686  }
2687  snappingResultVertex.snappedAtGeometry = featureId;
2688  snappingResultVertex.layer = this;
2689  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2690  return;
2691  }
2692  }
2693  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2694  {
2695  if ( geometryType() != QgsWkbTypes::PointGeometry ) // cannot snap to segment for points/multipoints
2696  {
2697  sqrDistSegmentSnap = geom.closestSegmentWithContext( startPoint, snappedPoint, afterVertex, nullptr, crs().isGeographic() ? 1e-12 : 1e-8 );
2698 
2699  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2700  {
2701  snappingResultSegment.snappedVertex = snappedPoint;
2702  snappingResultSegment.snappedVertexNr = -1;
2703  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2704  snappingResultSegment.afterVertexNr = afterVertex;
2705  snappingResultSegment.snappedAtGeometry = featureId;
2706  snappingResultSegment.beforeVertex = geom.vertexAt( afterVertex - 1 );
2707  snappingResultSegment.afterVertex = geom.vertexAt( afterVertex );
2708  snappingResultSegment.layer = this;
2709  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2710  }
2711  }
2712  }
2713 }
2714 
2715 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
2716 {
2717  QgsVectorLayerEditUtils utils( this );
2718  return utils.insertSegmentVerticesForSnap( snapResults );
2719 }
2720 
2721 
2723 {
2724  QgsDebugMsg( "----- Computing Coordinate System" );
2725 
2726  //
2727  // Get the layers project info and set up the QgsCoordinateTransform
2728  // for this layer
2729  //
2730 
2731  if ( hasGeometryType() )
2732  {
2733  // get CRS directly from provider
2734  setCrs( mDataProvider->crs() );
2735  }
2736  else
2737  {
2739  }
2740 }
2741 
2742 
2744 {
2745  QgsExpression exp( mDisplayExpression );
2746  if ( exp.isField() )
2747  {
2748  return static_cast<const QgsExpression::NodeColumnRef*>( exp.rootNode() )->name();
2749  }
2750 
2751  return QString();
2752 }
2753 
2755 {
2756  if ( mDisplayExpression == displayExpression )
2757  return;
2758 
2759  mDisplayExpression = displayExpression;
2760  emit displayExpressionChanged();
2761 }
2762 
2763 QString QgsVectorLayer::displayExpression() const
2764 {
2765  if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
2766  {
2767  return mDisplayExpression;
2768  }
2769  else
2770  {
2771  QString idxName;
2772 
2773  Q_FOREACH ( const QgsField& field, mFields )
2774  {
2775  QString fldName = field.name();
2776 
2777  // Check the fields and keep the first one that matches.
2778  // We assume that the user has organized the data with the
2779  // more "interesting" field names first. As such, name should
2780  // be selected before oldname, othername, etc.
2781  if ( fldName.indexOf( QLatin1String( "name" ), 0, Qt::CaseInsensitive ) > -1 )
2782  {
2783  idxName = fldName;
2784  break;
2785  }
2786  if ( fldName.indexOf( QLatin1String( "descrip" ), 0, Qt::CaseInsensitive ) > -1 )
2787  {
2788  idxName = fldName;
2789  break;
2790  }
2791  if ( fldName.indexOf( QLatin1String( "id" ), 0, Qt::CaseInsensitive ) > -1 )
2792  {
2793  idxName = fldName;
2794  break;
2795  }
2796  }
2797 
2798  if ( !idxName.isNull() )
2799  {
2800  return QgsExpression::quotedColumnRef( idxName );
2801  }
2802  else
2803  {
2804  return QgsExpression::quotedColumnRef( mFields.at( 0 ).name() );
2805  }
2806  }
2807 }
2808 
2810 {
2811  return ( mEditBuffer && mDataProvider );
2812 }
2813 
2815 {
2817 }
2818 
2819 bool QgsVectorLayer::isReadOnly() const
2820 {
2821  return mReadOnly;
2822 }
2823 
2824 bool QgsVectorLayer::setReadOnly( bool readonly )
2825 {
2826  // exit if the layer is in editing mode
2827  if ( readonly && mEditBuffer )
2828  return false;
2829 
2830  mReadOnly = readonly;
2831  emit readOnlyChanged();
2832  return true;
2833 }
2834 
2836 {
2837  emit beforeModifiedCheck();
2838  return mEditBuffer && mEditBuffer->isModified();
2839 }
2840 
2841 void QgsVectorLayer::setAnnotationForm( const QString& ui )
2842 {
2843  mAnnotationForm = ui;
2844 }
2845 
2847 {
2848  if ( !hasGeometryType() )
2849  return;
2850 
2851  if ( r != mRenderer )
2852  {
2853  delete mRenderer;
2854  mRenderer = r;
2855  mSymbolFeatureCounted = false;
2856  mSymbolFeatureCountMap.clear();
2857 
2858  emit rendererChanged();
2859  emit styleChanged();
2860  }
2861 }
2862 
2863 void QgsVectorLayer::beginEditCommand( const QString& text )
2864 {
2865  if ( !mDataProvider )
2866  {
2867  return;
2868  }
2869  if ( !mDataProvider->transaction() )
2870  {
2871  undoStack()->beginMacro( text );
2872  mEditCommandActive = true;
2873  emit editCommandStarted( text );
2874  }
2875 }
2876 
2878 {
2879  if ( !mDataProvider )
2880  {
2881  return;
2882  }
2883  if ( !mDataProvider->transaction() )
2884  {
2885  undoStack()->endMacro();
2886  mEditCommandActive = false;
2887  if ( !mDeletedFids.isEmpty() )
2888  {
2889  emit featuresDeleted( mDeletedFids );
2890  mDeletedFids.clear();
2891  }
2892  emit editCommandEnded();
2893  }
2894 }
2895 
2897 {
2898  if ( !mDataProvider )
2899  {
2900  return;
2901  }
2902  if ( !mDataProvider->transaction() )
2903  {
2904  undoStack()->endMacro();
2905  undoStack()->undo();
2906  mEditCommandActive = false;
2907  mDeletedFids.clear();
2908  emit editCommandDestroyed();
2909  }
2910 }
2911 
2913 {
2914  return mJoinBuffer && mJoinBuffer->addJoin( joinInfo );
2915 }
2916 
2917 void QgsVectorLayer::checkJoinLayerRemove( const QString& theLayerId )
2918 {
2919  removeJoin( theLayerId );
2920 }
2921 
2922 bool QgsVectorLayer::removeJoin( const QString& joinLayerId )
2923 {
2924  bool res = false;
2925  if ( mJoinBuffer )
2926  {
2927  res = mJoinBuffer->removeJoin( joinLayerId );
2928  }
2929  return res;
2930 }
2931 
2932 const QList< QgsVectorJoinInfo > QgsVectorLayer::vectorJoins() const
2933 {
2934  if ( mJoinBuffer )
2935  return mJoinBuffer->vectorJoins();
2936  else
2937  return QList< QgsVectorJoinInfo >();
2938 }
2939 
2940 int QgsVectorLayer::addExpressionField( const QString& exp, const QgsField& fld )
2941 {
2942  emit beforeAddingExpressionField( fld.name() );
2943  mExpressionFieldBuffer->addExpression( exp, fld );
2944  updateFields();
2945  int idx = mFields.indexFromName( fld.name() );
2946  emit attributeAdded( idx );
2947  return idx;
2948 }
2949 
2951 {
2952  emit beforeRemovingExpressionField( index );
2953  int oi = mFields.fieldOriginIndex( index );
2954  mExpressionFieldBuffer->removeExpression( oi );
2955  updateFields();
2956  emit attributeDeleted( index );
2957 }
2958 
2960 {
2961  int oi = mFields.fieldOriginIndex( index );
2962  if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
2963  return QString();
2964 
2965  return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
2966 }
2967 
2968 void QgsVectorLayer::updateExpressionField( int index, const QString& exp )
2969 {
2970  int oi = mFields.fieldOriginIndex( index );
2971  mExpressionFieldBuffer->updateExpression( oi, exp );
2972 }
2973 
2975 {
2976  if ( !mDataProvider )
2977  return;
2978 
2979  QgsFields oldFields = mFields;
2980 
2981  mFields = mDataProvider->fields();
2982 
2983  // added / removed fields
2984  if ( mEditBuffer )
2985  mEditBuffer->updateFields( mFields );
2986 
2987  // joined fields
2988  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
2989  mJoinBuffer->updateFields( mFields );
2990 
2991  if ( mExpressionFieldBuffer )
2992  mExpressionFieldBuffer->updateFields( mFields );
2993 
2994  // set aliases and default values
2995  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
2996  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
2997  {
2998  int index = mFields.lookupField( aliasIt.key() );
2999  if ( index < 0 )
3000  continue;
3001 
3002  mFields[ index ].setAlias( aliasIt.value() );
3003  }
3004  QMap< QString, QString >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
3005  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
3006  {
3007  int index = mFields.lookupField( defaultIt.key() );
3008  if ( index < 0 )
3009  continue;
3010 
3011  mFields[ index ].setDefaultValueExpression( defaultIt.value() );
3012  }
3013 
3014  QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
3015  for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
3016  {
3017  int index = mFields.lookupField( constraintIt.key() );
3018  if ( index < 0 )
3019  continue;
3020 
3021  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3022 
3023  // always keep provider constraints intact
3024  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
3026  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
3028  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
3030  mFields[ index ].setConstraints( constraints );
3031  }
3032 
3033  QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
3034  for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
3035  {
3036  int index = mFields.lookupField( constraintExpIt.key() );
3037  if ( index < 0 )
3038  continue;
3039 
3040  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3041 
3042  // always keep provider constraints intact
3044  continue;
3045 
3046  constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
3047  mFields[ index ].setConstraints( constraints );
3048  }
3049 
3050  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
3051  for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
3052  {
3053  int index = mFields.lookupField( constraintStrengthIt.key().first );
3054  if ( index < 0 )
3055  continue;
3056 
3057  QgsFieldConstraints constraints = mFields.at( index ).constraints();
3058 
3059  // always keep provider constraints intact
3061  continue;
3062 
3063  constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
3064  mFields[ index ].setConstraints( constraints );
3065  }
3066 
3067  auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
3068  for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
3069  {
3070  int index = mFields.indexOf( fieldWidgetIterator.key() );
3071  if ( index < 0 )
3072  continue;
3073 
3074  mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
3075  }
3076 
3077  if ( oldFields != mFields )
3078  {
3079  emit updatedFields();
3080  mEditFormConfig.setFields( mFields );
3081  }
3082 }
3083 
3084 
3086 {
3087  if ( mJoinBuffer->containsJoins() )
3088  {
3089  mJoinBuffer->createJoinCaches();
3090  }
3091 }
3092 
3093 QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature& feature, QgsExpressionContext* context ) const
3094 {
3095  if ( index < 0 || index >= mFields.count() )
3096  return QVariant();
3097 
3098  QString expression = mFields.at( index ).defaultValueExpression();
3099  if ( expression.isEmpty() )
3100  return mDataProvider->defaultValue( index );
3101 
3102  QgsExpressionContext* evalContext = context;
3103  QScopedPointer< QgsExpressionContext > tempContext;
3104  if ( !evalContext )
3105  {
3106  // no context passed, so we create a default one
3108  evalContext = tempContext.data();
3109  }
3110 
3111  if ( feature.isValid() )
3112  {
3114  featScope->setFeature( feature );
3115  featScope->setFields( feature.fields() );
3116  evalContext->appendScope( featScope );
3117  }
3118 
3119  QVariant val;
3120  QgsExpression exp( expression );
3121  exp.prepare( evalContext );
3122  if ( exp.hasEvalError() )
3123  {
3124  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
3125  }
3126  else
3127  {
3128  val = exp.evaluate( evalContext );
3129  }
3130 
3131  if ( feature.isValid() )
3132  {
3133  delete evalContext->popScope();
3134  }
3135 
3136  return val;
3137 }
3138 
3139 void QgsVectorLayer::setDefaultValueExpression( int index, const QString& expression )
3140 {
3141  if ( index < 0 || index >= mFields.count() )
3142  return;
3143 
3144  if ( expression.isEmpty() )
3145  {
3146  mDefaultExpressionMap.remove( mFields.at( index ).name() );
3147  }
3148  else
3149  {
3150  mDefaultExpressionMap.insert( mFields.at( index ).name(), expression );
3151  }
3152  updateFields();
3153 }
3154 
3156 {
3157  if ( index < 0 || index >= mFields.count() )
3158  return QString();
3159  else
3160  return mFields.at( index ).defaultValueExpression();
3161 }
3162 
3163 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit ) const
3164 {
3165  uniqueValues.clear();
3166  if ( !mDataProvider )
3167  {
3168  return;
3169  }
3170 
3171  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3172  switch ( origin )
3173  {
3175  return;
3176 
3177  case QgsFields::OriginProvider: //a provider field
3178  {
3179  mDataProvider->uniqueValues( index, uniqueValues, limit );
3180 
3181  if ( mEditBuffer )
3182  {
3183  QSet<QString> vals;
3184  Q_FOREACH ( const QVariant& v, uniqueValues )
3185  {
3186  vals << v.toString();
3187  }
3188 
3189  QgsFeatureMap added = mEditBuffer->addedFeatures();
3190  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3191  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3192  {
3193  addedIt.next();
3194  QVariant v = addedIt.value().attribute( index );
3195  if ( v.isValid() )
3196  {
3197  QString vs = v.toString();
3198  if ( !vals.contains( vs ) )
3199  {
3200  vals << vs;
3201  uniqueValues << v;
3202  }
3203  }
3204  }
3205 
3206  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3207  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3208  {
3209  it.next();
3210  QVariant v = it.value().value( index );
3211  if ( v.isValid() )
3212  {
3213  QString vs = v.toString();
3214  if ( !vals.contains( vs ) )
3215  {
3216  vals << vs;
3217  uniqueValues << v;
3218  }
3219  }
3220  }
3221  }
3222 
3223  return;
3224  }
3225 
3226  case QgsFields::OriginEdit:
3227  // the layer is editable, but in certain cases it can still be avoided going through all features
3228  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3229  mEditBuffer->mAddedFeatures.isEmpty() &&
3230  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3231  mEditBuffer->mChangedAttributeValues.isEmpty() )
3232  {
3233  mDataProvider->uniqueValues( index, uniqueValues, limit );
3234  return;
3235  }
3236  FALLTHROUGH;
3237  //we need to go through each feature
3238  case QgsFields::OriginJoin:
3240  {
3241  QgsAttributeList attList;
3242  attList << index;
3243 
3245  .setFlags( QgsFeatureRequest::NoGeometry )
3246  .setSubsetOfAttributes( attList ) );
3247 
3248  QgsFeature f;
3249  QVariant currentValue;
3250  QHash<QString, QVariant> val;
3251  while ( fit.nextFeature( f ) )
3252  {
3253  currentValue = f.attribute( index );
3254  val.insert( currentValue.toString(), currentValue );
3255  if ( limit >= 0 && val.size() >= limit )
3256  {
3257  break;
3258  }
3259  }
3260 
3261  uniqueValues = val.values();
3262  return;
3263  }
3264  }
3265 
3266  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3267 }
3268 
3269 QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString& substring, int limit, QgsFeedback* feedback ) const
3270 {
3271  QStringList results;
3272  if ( !mDataProvider )
3273  {
3274  return results;
3275  }
3276 
3277  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3278  switch ( origin )
3279  {
3281  return results;
3282 
3283  case QgsFields::OriginProvider: //a provider field
3284  {
3285  results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3286 
3287  if ( mEditBuffer )
3288  {
3289  QgsFeatureMap added = mEditBuffer->addedFeatures();
3290  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3291  while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3292  {
3293  addedIt.next();
3294  QVariant v = addedIt.value().attribute( index );
3295  if ( v.isValid() )
3296  {
3297  QString vs = v.toString();
3298  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3299  {
3300  results << vs;
3301  }
3302  }
3303  }
3304 
3305  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3306  while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3307  {
3308  it.next();
3309  QVariant v = it.value().value( index );
3310  if ( v.isValid() )
3311  {
3312  QString vs = v.toString();
3313  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3314  {
3315  results << vs;
3316  }
3317  }
3318  }
3319  }
3320 
3321  return results;
3322  }
3323 
3324  case QgsFields::OriginEdit:
3325  // the layer is editable, but in certain cases it can still be avoided going through all features
3326  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3327  mEditBuffer->mAddedFeatures.isEmpty() &&
3328  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3329  mEditBuffer->mChangedAttributeValues.isEmpty() )
3330  {
3331  return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3332  }
3333  FALLTHROUGH;
3334  //we need to go through each feature
3335  case QgsFields::OriginJoin:
3337  {
3338  QgsAttributeList attList;
3339  attList << index;
3340 
3341  QgsFeatureRequest request;
3342  request.setSubsetOfAttributes( attList );
3344  QString fieldName = mFields.at( index ).name();
3345  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
3346  QgsFeatureIterator fit = getFeatures( request );
3347 
3348  QgsFeature f;
3349  QString currentValue;
3350  while ( fit.nextFeature( f ) )
3351  {
3352  currentValue = f.attribute( index ).toString();
3353  if ( !results.contains( currentValue ) )
3354  results << currentValue;
3355 
3356  if (( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
3357  {
3358  break;
3359  }
3360  }
3361 
3362  return results;
3363  }
3364  }
3365 
3366  Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
3367  return results;
3368 }
3369 
3371 {
3372  if ( !mDataProvider )
3373  {
3374  return QVariant();
3375  }
3376 
3377  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3378 
3379  switch ( origin )
3380  {
3382  return QVariant();
3383 
3384  case QgsFields::OriginProvider: //a provider field
3385  {
3386  QVariant min = mDataProvider->minimumValue( index );
3387  if ( mEditBuffer )
3388  {
3389  QgsFeatureMap added = mEditBuffer->addedFeatures();
3390  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3391  while ( addedIt.hasNext() )
3392  {
3393  addedIt.next();
3394  QVariant v = addedIt.value().attribute( index );
3395  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3396  {
3397  min = v;
3398  }
3399  }
3400 
3401  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3402  while ( it.hasNext() )
3403  {
3404  it.next();
3405  QVariant v = it.value().value( index );
3406  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3407  {
3408  min = v;
3409  }
3410  }
3411  }
3412  return min;
3413  }
3414 
3415  case QgsFields::OriginEdit:
3416  {
3417  // the layer is editable, but in certain cases it can still be avoided going through all features
3418  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3419  mEditBuffer->mAddedFeatures.isEmpty() && !
3420  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3421  mEditBuffer->mChangedAttributeValues.isEmpty() )
3422  {
3423  return mDataProvider->minimumValue( index );
3424  }
3425  }
3426  FALLTHROUGH;
3427  // no choice but to go through all features
3429  case QgsFields::OriginJoin:
3430  {
3431  // we need to go through each feature
3432  QgsAttributeList attList;
3433  attList << index;
3434 
3436  .setFlags( QgsFeatureRequest::NoGeometry )
3437  .setSubsetOfAttributes( attList ) );
3438 
3439  QgsFeature f;
3441  double currentValue = 0;
3442  while ( fit.nextFeature( f ) )
3443  {
3444  currentValue = f.attribute( index ).toDouble();
3445  if ( currentValue < minimumValue )
3446  {
3447  minimumValue = currentValue;
3448  }
3449  }
3450  return QVariant( minimumValue );
3451  }
3452  }
3453 
3454  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3455  return QVariant();
3456 }
3457 
3459 {
3460  if ( !mDataProvider )
3461  {
3462  return QVariant();
3463  }
3464 
3465  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3466  switch ( origin )
3467  {
3469  return QVariant();
3470 
3471  case QgsFields::OriginProvider: //a provider field
3472  {
3473  QVariant min = mDataProvider->maximumValue( index );
3474  if ( mEditBuffer )
3475  {
3476  QgsFeatureMap added = mEditBuffer->addedFeatures();
3477  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3478  while ( addedIt.hasNext() )
3479  {
3480  addedIt.next();
3481  QVariant v = addedIt.value().attribute( index );
3482  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3483  {
3484  min = v;
3485  }
3486  }
3487 
3488  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3489  while ( it.hasNext() )
3490  {
3491  it.next();
3492  QVariant v = it.value().value( index );
3493  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3494  {
3495  min = v;
3496  }
3497  }
3498  }
3499  return min;
3500  }
3501 
3502  case QgsFields::OriginEdit:
3503  // the layer is editable, but in certain cases it can still be avoided going through all features
3504  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3505  mEditBuffer->mAddedFeatures.isEmpty() &&
3506  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3507  mEditBuffer->mChangedAttributeValues.isEmpty() )
3508  {
3509  return mDataProvider->maximumValue( index );
3510  }
3511 
3512  FALLTHROUGH;
3513  //no choice but to go through each feature
3514  case QgsFields::OriginJoin:
3516  {
3517  QgsAttributeList attList;
3518  attList << index;
3519 
3521  .setFlags( QgsFeatureRequest::NoGeometry )
3522  .setSubsetOfAttributes( attList ) );
3523 
3524  QgsFeature f;
3526  double currentValue = 0;
3527  while ( fit.nextFeature( f ) )
3528  {
3529  currentValue = f.attribute( index ).toDouble();
3530  if ( currentValue > maximumValue )
3531  {
3532  maximumValue = currentValue;
3533  }
3534  }
3535  return QVariant( maximumValue );
3536  }
3537  }
3538 
3539  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3540  return QVariant();
3541 }
3542 
3543 QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString& fieldOrExpression,
3544  const QgsAggregateCalculator::AggregateParameters& parameters, QgsExpressionContext* context, bool* ok ) const
3545 {
3546  if ( ok )
3547  *ok = false;
3548 
3549  if ( !mDataProvider )
3550  {
3551  return QVariant();
3552  }
3553 
3554  // test if we are calculating based on a field
3555  int attrIndex = mFields.lookupField( fieldOrExpression );
3556  if ( attrIndex >= 0 )
3557  {
3558  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
3559  // to the provider itself
3560  QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
3561  if ( origin == QgsFields::OriginProvider )
3562  {
3563  bool providerOk = false;
3564  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk );
3565  if ( providerOk )
3566  {
3567  // provider handled calculation
3568  if ( ok )
3569  *ok = true;
3570  return val;
3571  }
3572  }
3573  }
3574 
3575  // fallback to using aggregate calculator to determine aggregate
3576  QgsAggregateCalculator c( this );
3577  c.setParameters( parameters );
3578  return c.calculate( aggregate, fieldOrExpression, context, ok );
3579 }
3580 
3581 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly ) const
3582 {
3583  QList<QVariant> values;
3584 
3585  QScopedPointer<QgsExpression> expression;
3586  QgsExpressionContext context;
3587 
3588  int attrNum = mFields.lookupField( fieldOrExpression );
3589 
3590  if ( attrNum == -1 )
3591  {
3592  // try to use expression
3593  expression.reset( new QgsExpression( fieldOrExpression ) );
3595 
3596  if ( expression->hasParserError() || !expression->prepare( &context ) )
3597  {
3598  ok = false;
3599  return values;
3600  }
3601  }
3602 
3603  QgsFeature f;
3604  QSet<QString> lst;
3605  if ( expression.isNull() )
3606  lst.insert( fieldOrExpression );
3607  else
3608  lst = expression->referencedColumns();
3609 
3611  .setFlags(( expression && expression->needsGeometry() ) ?
3614  .setSubsetOfAttributes( lst, fields() );
3615 
3616  QgsFeatureIterator fit;
3617  if ( !selectedOnly )
3618  {
3619  fit = getFeatures( request );
3620  }
3621  else
3622  {
3623  fit = selectedFeaturesIterator( request );
3624  }
3625 
3626  // create list of non-null attribute values
3627  while ( fit.nextFeature( f ) )
3628  {
3629  if ( expression )
3630  {
3631  context.setFeature( f );
3632  QVariant v = expression->evaluate( &context );
3633  values << v;
3634  }
3635  else
3636  {
3637  values << f.attribute( attrNum );
3638  }
3639  }
3640  ok = true;
3641  return values;
3642 }
3643 
3644 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly, int* nullCount ) const
3645 {
3646  QList<double> values;
3647 
3648  if ( nullCount )
3649  *nullCount = 0;
3650 
3651  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3652  if ( !ok )
3653  return values;
3654 
3655  bool convertOk;
3656  Q_FOREACH ( const QVariant& value, variantValues )
3657  {
3658  double val = value.toDouble( &convertOk );
3659  if ( convertOk )
3660  values << val;
3661  else if ( value.isNull() )
3662  {
3663  if ( nullCount )
3664  *nullCount += 1;
3665  }
3666  }
3667  ok = true;
3668  return values;
3669 }
3670 
3671 
3674 {
3675  mFeatureBlendMode = featureBlendMode;
3676  emit featureBlendModeChanged( featureBlendMode );
3677  emit styleChanged();
3678 }
3679 
3681 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3682 {
3683  return mFeatureBlendMode;
3684 }
3685 
3688 {
3689  mLayerTransparency = layerTransparency;
3690  emit layerTransparencyChanged( layerTransparency );
3691  emit styleChanged();
3692 }
3693 
3696 {
3697  return mLayerTransparency;
3698 }
3699 
3700 
3701 
3702 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3703 {
3704  QDomElement element = node.toElement();
3705  if ( element.isNull() )
3706  return;
3707 
3708  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
3709  if ( userStyleElem.isNull() )
3710  {
3711  QgsDebugMsg( "Info: UserStyle element not found." );
3712  return;
3713  }
3714 
3715  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
3716  if ( featureTypeStyleElem.isNull() )
3717  {
3718  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3719  return;
3720  }
3721 
3722  // use last rule
3723  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( QStringLiteral( "Rule" ) );
3724  if ( ruleElem.isNull() )
3725  {
3726  QgsDebugMsg( "Info: Rule element not found." );
3727  return;
3728  }
3729 
3730  // use last text symbolizer
3731  QDomElement textSymbolizerElem = ruleElem.lastChildElement( QStringLiteral( "TextSymbolizer" ) );
3732  if ( textSymbolizerElem.isNull() )
3733  {
3734  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3735  return;
3736  }
3737 
3738  // Label
3739  setCustomProperty( QStringLiteral( "labeling/enabled" ), false );
3740  QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
3741  if ( !labelElem.isNull() )
3742  {
3743  QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
3744  if ( !propertyNameElem.isNull() )
3745  {
3746  // enable labeling
3747  setCustomProperty( QStringLiteral( "labeling" ), "pal" );
3748  setCustomProperty( QStringLiteral( "labeling/enabled" ), true );
3749 
3750  // set labeling defaults
3751  setCustomProperty( QStringLiteral( "labeling/fontFamily" ), "Sans-Serif" );
3752  setCustomProperty( QStringLiteral( "labeling/fontItalic" ), false );
3753  setCustomProperty( QStringLiteral( "labeling/fontSize" ), 10 );
3754  setCustomProperty( QStringLiteral( "labeling/fontSizeInMapUnits" ), false );
3755  setCustomProperty( QStringLiteral( "labeling/fontBold" ), false );
3756  setCustomProperty( QStringLiteral( "labeling/fontUnderline" ), false );
3757  setCustomProperty( QStringLiteral( "labeling/textColorR" ), 0 );
3758  setCustomProperty( QStringLiteral( "labeling/textColorG" ), 0 );
3759  setCustomProperty( QStringLiteral( "labeling/textColorB" ), 0 );
3760  setCustomProperty( QStringLiteral( "labeling/textTransp" ), 0 );
3761  setCustomProperty( QStringLiteral( "labeling/bufferDraw" ), false );
3762  setCustomProperty( QStringLiteral( "labeling/bufferSize" ), 1 );
3763  setCustomProperty( QStringLiteral( "labeling/bufferSizeInMapUnits" ), false );
3764  setCustomProperty( QStringLiteral( "labeling/bufferColorR" ), 255 );
3765  setCustomProperty( QStringLiteral( "labeling/bufferColorG" ), 255 );
3766  setCustomProperty( QStringLiteral( "labeling/bufferColorB" ), 255 );
3767  setCustomProperty( QStringLiteral( "labeling/bufferTransp" ), 0 );
3768  setCustomProperty( QStringLiteral( "labeling/placement" ), QgsPalLayerSettings::AroundPoint );
3769  setCustomProperty( QStringLiteral( "labeling/xOffset" ), 0 );
3770  setCustomProperty( QStringLiteral( "labeling/yOffset" ), 0 );
3771  setCustomProperty( QStringLiteral( "labeling/labelOffsetInMapUnits" ), false );
3772  setCustomProperty( QStringLiteral( "labeling/angleOffset" ), 0 );
3773 
3774  // label attribute
3775  QString labelAttribute = propertyNameElem.text();
3776  setCustomProperty( QStringLiteral( "labeling/fieldName" ), labelAttribute );
3777  setCustomProperty( QStringLiteral( "labeling/isExpression" ), false );
3778 
3779  int fieldIndex = mFields.lookupField( labelAttribute );
3780  if ( fieldIndex == -1 )
3781  {
3782  // label attribute is not in columns, check if it is an expression
3783  QgsExpression exp( labelAttribute );
3784  if ( !exp.hasEvalError() )
3785  {
3786  setCustomProperty( QStringLiteral( "labeling/isExpression" ), true );
3787  }
3788  else
3789  {
3790  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3791  }
3792  }
3793  }
3794  else
3795  {
3796  QgsDebugMsg( "Info: PropertyName element not found." );
3797  return;
3798  }
3799  }
3800  else
3801  {
3802  QgsDebugMsg( "Info: Label element not found." );
3803  return;
3804  }
3805 
3806  // Font
3807  QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
3808  if ( !fontElem.isNull() )
3809  {
3810  QString cssName;
3811  QString elemText;
3812  QDomElement cssElem = fontElem.firstChildElement( QStringLiteral( "CssParameter" ) );
3813  while ( !cssElem.isNull() )
3814  {
3815  cssName = cssElem.attribute( QStringLiteral( "name" ), QStringLiteral( "not_found" ) );
3816  if ( cssName != QLatin1String( "not_found" ) )
3817  {
3818  elemText = cssElem.text();
3819  if ( cssName == QLatin1String( "font-family" ) )
3820  {
3821  setCustomProperty( QStringLiteral( "labeling/fontFamily" ), elemText );
3822  }
3823  else if ( cssName == QLatin1String( "font-style" ) )
3824  {
3825  setCustomProperty( QStringLiteral( "labeling/fontItalic" ), ( elemText == QLatin1String( "italic" ) ) || ( elemText == QLatin1String( "Italic" ) ) );
3826  }
3827  else if ( cssName == QLatin1String( "font-size" ) )
3828  {
3829  bool ok;
3830  int fontSize = elemText.toInt( &ok );
3831  if ( ok )
3832  {
3833  setCustomProperty( QStringLiteral( "labeling/fontSize" ), fontSize );
3834  }
3835  }
3836  else if ( cssName == QLatin1String( "font-weight" ) )
3837  {
3838  setCustomProperty( QStringLiteral( "labeling/fontBold" ), ( elemText == QLatin1String( "bold" ) ) || ( elemText == QLatin1String( "Bold" ) ) );
3839  }
3840  else if ( cssName == QLatin1String( "font-underline" ) )
3841  {
3842  setCustomProperty( QStringLiteral( "labeling/fontUnderline" ), ( elemText == QLatin1String( "underline" ) ) || ( elemText == QLatin1String( "Underline" ) ) );
3843  }
3844  }
3845 
3846  cssElem = cssElem.nextSiblingElement( QStringLiteral( "CssParameter" ) );
3847  }
3848  }
3849 
3850  // Fill
3851  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) ) );
3852  if ( textColor.isValid() )
3853  {
3854  setCustomProperty( QStringLiteral( "labeling/textColorR" ), textColor.red() );
3855  setCustomProperty( QStringLiteral( "labeling/textColorG" ), textColor.green() );
3856  setCustomProperty( QStringLiteral( "labeling/textColorB" ), textColor.blue() );
3857  setCustomProperty( QStringLiteral( "labeling/textTransp" ), 100 - static_cast< int >( 100 * textColor.alphaF() ) );
3858  }
3859 
3860  // Halo
3861  QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
3862  if ( !haloElem.isNull() )
3863  {
3864  setCustomProperty( QStringLiteral( "labeling/bufferDraw" ), true );
3865  setCustomProperty( QStringLiteral( "labeling/bufferSize" ), 1 );
3866 
3867  QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
3868  if ( !radiusElem.isNull() )
3869  {
3870  bool ok;
3871  double bufferSize = radiusElem.text().toDouble( &ok );
3872  if ( ok )
3873  {
3874  setCustomProperty( QStringLiteral( "labeling/bufferSize" ), bufferSize );
3875  }
3876  }
3877 
3878  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( QStringLiteral( "Fill" ) ) );
3879  if ( bufferColor.isValid() )
3880  {
3881  setCustomProperty( QStringLiteral( "labeling/bufferColorR" ), bufferColor.red() );
3882  setCustomProperty( QStringLiteral( "labeling/bufferColorG" ), bufferColor.green() );
3883  setCustomProperty( QStringLiteral( "labeling/bufferColorB" ), bufferColor.blue() );
3884  setCustomProperty( QStringLiteral( "labeling/bufferTransp" ), 100 - static_cast< int >( 100 * bufferColor.alphaF() ) );
3885  }
3886  }
3887 
3888  // LabelPlacement
3889  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
3890  if ( !labelPlacementElem.isNull() )
3891  {
3892  // PointPlacement
3893  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
3894  if ( !pointPlacementElem.isNull() )
3895  {
3896  setCustomProperty( QStringLiteral( "labeling/placement" ), QgsPalLayerSettings::OverPoint );
3897 
3898  QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
3899  if ( !displacementElem.isNull() )
3900  {
3901  QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
3902  if ( !displacementXElem.isNull() )
3903  {
3904  bool ok;
3905  double xOffset = displacementXElem.text().toDouble( &ok );
3906  if ( ok )
3907  {
3908  setCustomProperty( QStringLiteral( "labeling/xOffset" ), xOffset );
3909  }
3910  }
3911  QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
3912  if ( !displacementYElem.isNull() )
3913  {
3914  bool ok;
3915  double yOffset = displacementYElem.text().toDouble( &ok );
3916  if ( ok )
3917  {
3918  setCustomProperty( QStringLiteral( "labeling/yOffset" ), yOffset );
3919  }
3920  }
3921  }
3922 
3923  QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
3924  if ( !rotationElem.isNull() )
3925  {
3926  bool ok;
3927  double rotation = rotationElem.text().toDouble( &ok );
3928  if ( ok )
3929  {
3930  setCustomProperty( QStringLiteral( "labeling/angleOffset" ), rotation );
3931  }
3932  }
3933  }
3934  }
3935 }
3936 
3938 {
3939  return mEditFormConfig;
3940 }
3941 
3943 {
3944  if ( mEditFormConfig == editFormConfig )
3945  return;
3946 
3947  mEditFormConfig = editFormConfig;
3948  emit editFormConfigChanged();
3949 }
3950 
3951 QString QgsVectorLayer::mapTipTemplate() const
3952 {
3953  return mMapTipTemplate;
3954 }
3955 
3956 void QgsVectorLayer::setMapTipTemplate( const QString& mapTip )
3957 {
3958  if ( mMapTipTemplate == mapTip )
3959  return;
3960 
3961  mMapTipTemplate = mapTip;
3962  emit mapTipTemplateChanged();
3963 }
3964 
3966 {
3967  QgsAttributeTableConfig config = mAttributeTableConfig;
3968 
3969  if ( config.isEmpty() )
3970  config.update( fields() );
3971 
3972  return config;
3973 }
3974 
3976 {
3977  if ( mAttributeTableConfig != attributeTableConfig )
3978  {
3979  mAttributeTableConfig = attributeTableConfig;
3980  emit configChanged();
3981  }
3982 }
3983 
3985 {
3987 }
3988 
3990 {
3991  if ( !mDiagramLayerSettings )
3992  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3993  *mDiagramLayerSettings = s;
3994 }
3995 
3997 {
3998  QString myMetadata = QStringLiteral( "<html><body>" );
3999 
4000  //-------------
4001 
4002  myMetadata += QLatin1String( "<p class=\"subheaderglossy\">" );
4003  myMetadata += tr( "General" );
4004  myMetadata += QLatin1String( "</p>\n" );
4005 
4006  // data comment
4007  if ( !( dataComment().isEmpty() ) )
4008  {
4009  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
4010  myMetadata += QLatin1String( "<p>" );
4011  myMetadata += dataComment();
4012  myMetadata += QLatin1String( "</p>\n" );
4013  }
4014 
4015  //storage type
4016  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
4017  myMetadata += QLatin1String( "<p>" );
4018  myMetadata += storageType();
4019  myMetadata += QLatin1String( "</p>\n" );
4020 
4021  if ( dataProvider() )
4022  {
4023  //provider description
4024  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
4025  myMetadata += QLatin1String( "<p>" );
4026  myMetadata += dataProvider()->description().replace( '\n', QLatin1String( "<br>" ) );
4027  myMetadata += QLatin1String( "</p>\n" );
4028 
4029  QVariantMap dataProviderMetadata = mDataProvider->metadata();
4030  if ( !dataProviderMetadata.isEmpty() )
4031  {
4032  myMetadata += "<p class=\"glossy\">" + tr( "Provider Metadata" ) + "</p>\n";
4033  myMetadata += "<p><table><tr><th>" + tr( "Metadata name" ) + "</th><th>" + tr( "Metadata value" ) + "</th></tr>\n";
4034  QMapIterator<QString, QVariant> i( dataProviderMetadata );
4035  while ( i.hasNext() )
4036  {
4037  i.next();
4038  myMetadata += "<tr>";
4039  myMetadata += "<td>" + mDataProvider->translateMetadataKey( i.key() ) + ":</td>";
4040  myMetadata += "<td>" + mDataProvider->translateMetadataValue( i.key(), i.value() ) + "</td>";
4041  myMetadata += "</tr>\n";
4042  }
4043  myMetadata += QLatin1String( "</table></p>\n" );
4044  }
4045  }
4046 
4047  // data source
4048  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
4049  myMetadata += QLatin1String( "<p>" );
4050  myMetadata += publicSource();
4051  myMetadata += QLatin1String( "</p>\n" );
4052 
4053  //geom type
4054 
4056 
4057  if ( type < 0 || type > QgsWkbTypes::NullGeometry )
4058  {
4059  QgsDebugMsg( "Invalid vector type" );
4060  }
4061  else
4062  {
4063  QString typeString( QgsWkbTypes::geometryDisplayString( geometryType() ) );
4064 
4065  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
4066  myMetadata += QStringLiteral( "<p>%1</p>\n" ).arg( typeString );
4067  }
4068 
4069  QgsAttributeList pkAttrList = pkAttributeList();
4070  if ( !pkAttrList.isEmpty() )
4071  {
4072  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
4073  myMetadata += QLatin1String( "<p>" );
4074  Q_FOREACH ( int idx, pkAttrList )
4075  {
4076  myMetadata += fields().at( idx ).name() + ' ';
4077  }
4078  myMetadata += QLatin1String( "</p>\n" );
4079  }
4080 
4081 
4082  //feature count
4083  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
4084  myMetadata += QLatin1String( "<p>" );
4085  myMetadata += QString::number( featureCount() );
4086  myMetadata += QLatin1String( "</p>\n" );
4087  //capabilities
4088  myMetadata += "<p class=\"glossy\">" + tr( "Capabilities of this layer" ) + "</p>\n";
4089  myMetadata += QLatin1String( "<p>" );
4090  myMetadata += capabilitiesString();
4091  myMetadata += QLatin1String( "</p>\n" );
4092 
4093  //-------------
4094 
4095  QgsRectangle myExtent = extent();
4096  myMetadata += QLatin1String( "<p class=\"subheaderglossy\">" );
4097  myMetadata += tr( "Extents" );
4098  myMetadata += QLatin1String( "</p>\n" );
4099 
4100  //extents in layer cs TODO...maybe make a little nested table to improve layout...
4101  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
4102  myMetadata += QLatin1String( "<p>" );
4103  // Try to be a bit clever over what number format we use for the
4104  // extents. Some people don't like it using scientific notation when the
4105  // numbers get large, but for small numbers this is the more practical
4106  // option (so we can't force the format to 'f' for all values).
4107  // The scheme:
4108  // - for all numbers with more than 5 digits, force non-scientific notation
4109  // and 2 digits after the decimal point.
4110  // - for all smaller numbers let the OS decide which format to use (it will
4111  // generally use non-scientific unless the number gets much less than 1).
4112 
4113  if ( !myExtent.isEmpty() )
4114  {
4115  QString xMin, yMin, xMax, yMax;
4116  double changeoverValue = 99999; // The 'largest' 5 digit number
4117  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
4118  {
4119  xMin = QStringLiteral( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
4120  }
4121  else
4122  {
4123  xMin = QStringLiteral( "%1" ).arg( myExtent.xMinimum() );
4124  }
4125  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
4126  {
4127  yMin = QStringLiteral( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
4128  }
4129  else
4130  {
4131  yMin = QStringLiteral( "%1" ).arg( myExtent.yMinimum() );
4132  }
4133  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
4134  {
4135  xMax = QStringLiteral( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
4136  }
4137  else
4138  {
4139  xMax = QStringLiteral( "%1" ).arg( myExtent.xMaximum() );
4140  }
4141  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
4142  {
4143  yMax = QStringLiteral( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
4144  }
4145  else
4146  {
4147  yMax = QStringLiteral( "%1" ).arg( myExtent.yMaximum() );
4148  }
4149 
4150  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
4151  .arg( xMin, yMin, xMax, yMax );
4152  }
4153  else
4154  {
4155  myMetadata += tr( "unknown extent" );
4156  }
4157 
4158  myMetadata += QLatin1String( "</p>\n" );
4159 
4160  //extents in project cs
4161 
4162  try
4163  {
4164 #if 0
4165  // TODO: currently disabled, will revisit later [MD]
4166  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
4167  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
4168  myMetadata += "<p>";
4169  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
4170  .arg( myProjectedExtent.xMinimum() )
4171  .arg( myProjectedExtent.yMinimum() )
4172  .arg( myProjectedExtent.xMaximum() )
4173  .arg( myProjectedExtent.yMaximum() );
4174  myMetadata += "</p>\n";
4175 #endif
4176 
4177  //
4178  // Display layer spatial ref system
4179  //
4180  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
4181  myMetadata += QLatin1String( "<p>" );
4182  myMetadata += crs().toProj4().replace( '"', QLatin1String( " \"" ) );
4183  myMetadata += QLatin1String( "</p>\n" );
4184 
4185  //
4186  // Display project (output) spatial ref system
4187  //
4188 #if 0
4189  // TODO: disabled for now, will revisit later [MD]
4190  //myMetadata += "<tr><td bgcolor=\"gray\">";
4191  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
4192  myMetadata += "<p>";
4193  myMetadata += coordinateTransform->destCRS().toProj4().replace( '"', " \"" );
4194  myMetadata += "</p>\n";
4195 #endif
4196  }
4197  catch ( QgsCsException &cse )
4198  {
4199  Q_UNUSED( cse );
4200  QgsDebugMsg( cse.what() );
4201 
4202  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
4203  myMetadata += QLatin1String( "<p>" );
4204  myMetadata += tr( "(Invalid transformation of layer extents)" );
4205  myMetadata += QLatin1String( "</p>\n" );
4206 
4207  }
4208 
4209 #if 0
4210  //
4211  // Add the info about each field in the attribute table
4212  //
4213  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
4214  myMetadata += "<p>";
4215 
4216  // Start a nested table in this trow
4217  myMetadata += "<table width=\"100%\">";
4218  myMetadata += "<tr><th>";
4219  myMetadata += tr( "Field" );
4220  myMetadata += "</th>";
4221  myMetadata += "<th>";
4222  myMetadata += tr( "Type" );
4223  myMetadata += "</th>";
4224  myMetadata += "<th>";
4225  myMetadata += tr( "Length" );
4226  myMetadata += "</th>";
4227  myMetadata += "<th>";
4228  myMetadata += tr( "Precision" );
4229  myMetadata += "</th>";
4230  myMetadata += "<th>";
4231  myMetadata += tr( "Comment" );
4232  myMetadata += "</th>";
4233 
4234  //get info for each field by looping through them
4235  const QgsFields& myFields = pendingFields();
4236  for ( int i = 0, n = myFields.size(); i < n; ++i )
4237  {
4238  QgsField myField = fields.at( i );
4239 
4240  myMetadata += "<tr><td>";
4241  myMetadata += myField.name();
4242  myMetadata += "</td>";
4243  myMetadata += "<td>";
4244  myMetadata += myField.typeName();
4245  myMetadata += "</td>";
4246  myMetadata += "<td>";
4247  myMetadata += QString( "%1" ).arg( myField.length() );
4248  myMetadata += "</td>";
4249  myMetadata += "<td>";
4250  myMetadata += QString( "%1" ).arg( myField.precision() );
4251  myMetadata += "</td>";
4252  myMetadata += "<td>";
4253  myMetadata += QString( "%1" ).arg( myField.comment() );
4254  myMetadata += "</td></tr>";
4255  }
4256 
4257  //close field list
4258  myMetadata += "</table>"; //end of nested table
4259 #endif
4260 
4261  myMetadata += QLatin1String( "</body></html>" );
4262  return myMetadata;
4263 }
4264 
4266 {
4267  mSymbolFeatureCounted = false;
4268 }
4269 
4270 void QgsVectorLayer::onJoinedFieldsChanged()
4271 {
4272  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4273  updateFields();
4274 }
4275 
4276 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4277 {
4278  if ( mEditCommandActive )
4279  mDeletedFids << fid;
4280  else
4281  emit featuresDeleted( QgsFeatureIds() << fid );
4282 
4283  emit featureDeleted( fid );
4284 }
4285 
4286 void QgsVectorLayer::onRelationsLoaded()
4287 {
4288  mEditFormConfig.onRelationsLoaded();
4289 }
4290 
4291 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
4292 {
4293  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4294 }
4295 
4296 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
4297 {
4299  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4300  if ( !myLib )
4301  {
4302  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4303  return -1;
4304  }
4305  listStyles_t* listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
4306 
4307  if ( !listStylesExternalMethod )
4308  {
4309  delete myLib;
4310  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "listStyles" ) );
4311  return -1;
4312  }
4313 
4314  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
4315 }
4316 
4317 QString QgsVectorLayer::getStyleFromDatabase( const QString& styleId, QString &msgError )
4318 {
4320  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4321  if ( !myLib )
4322  {
4323  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4324  return QObject::tr( "" );
4325  }
4326  getStyleById_t* getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
4327 
4328  if ( !getStyleByIdMethod )
4329  {
4330  delete myLib;
4331  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "getStyleById" ) );
4332  return QObject::tr( "" );
4333  }
4334 
4335  return getStyleByIdMethod( mDataSource, styleId, msgError );
4336 }
4337 
4338 
4339 void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& description,
4340  bool useAsDefault, const QString& uiFileContent, QString &msgError )
4341 {
4342 
4343  QString sldStyle, qmlStyle;
4345  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4346  if ( !myLib )
4347  {
4348  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4349  return;
4350  }
4351  saveStyle_t* saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4352 
4353  if ( !saveStyleExternalMethod )
4354  {
4355  delete myLib;
4356  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "saveStyle" ) );
4357  return;
4358  }
4359 
4360  QDomDocument qmlDocument, sldDocument;
4361  this->exportNamedStyle( qmlDocument, msgError );
4362  if ( !msgError.isNull() )
4363  {
4364  return;
4365  }
4366  qmlStyle = qmlDocument.toString();
4367 
4368  this->exportSldStyle( sldDocument, msgError );
4369  if ( !msgError.isNull() )
4370  {
4371  return;
4372  }
4373  sldStyle = sldDocument.toString();
4374 
4375  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4376  description, uiFileContent, useAsDefault, msgError );
4377 }
4378 
4379 
4380 
4381 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
4382 {
4383  return loadNamedStyle( theURI, theResultFlag, false );
4384 }
4385 
4386 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
4387 {
4388  QgsDataSourceUri dsUri( theURI );
4389  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDBSupported() )
4390  {
4392  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4393  if ( myLib )
4394  {
4395  loadStyle_t* loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4396  if ( loadStyleExternalMethod )
4397  {
4398  QString qml, errorMsg;
4399  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4400  if ( !qml.isEmpty() )
4401  {
4402  QDomDocument myDocument( QStringLiteral( "qgis" ) );
4403  myDocument.setContent( qml );
4404  theResultFlag = importNamedStyle( myDocument, errorMsg );
4405  return QObject::tr( "Loaded from Provider" );
4406  }
4407  }
4408  }
4409  }
4410 
4411  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
4412 }
4413 
4414 QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
4415 {
4416  if ( mDataProvider )
4417  return mDataProvider->dependencies() + mDependencies;
4418  return mDependencies;
4419 }
4420 
4421 bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency>& oDeps )
4422 {
4423  QSet<QgsMapLayerDependency> deps;
4424  Q_FOREACH ( const QgsMapLayerDependency& dep, oDeps )
4425  {
4426  if ( dep.origin() == QgsMapLayerDependency::FromUser )
4427  deps << dep;
4428  }
4429  if ( hasDependencyCycle( deps ) )
4430  return false;
4431 
4432  QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
4433 
4434  // disconnect layers that are not present in the list of dependencies anymore
4435  Q_FOREACH ( const QgsMapLayerDependency& dep, mDependencies )
4436  {
4437  QgsVectorLayer* lyr = static_cast<QgsVectorLayer*>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4438  if ( lyr == nullptr )
4439  continue;
4440  disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::dataChanged );
4441  disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::dataChanged );
4443  disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::dataChanged );
4445  }
4446 
4447  // assign new dependencies
4448  if ( mDataProvider )
4449  mDependencies = mDataProvider->dependencies() + deps;
4450  else
4451  mDependencies = deps;
4452  emit dependenciesChanged();
4453 
4454  // connect to new layers
4455  Q_FOREACH ( const QgsMapLayerDependency& dep, mDependencies )
4456  {
4457  QgsVectorLayer* lyr = static_cast<QgsVectorLayer*>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4458  if ( lyr == nullptr )
4459  continue;
4465  }
4466 
4467  // if new layers are present, emit a data change
4468  if ( ! toAdd.isEmpty() )
4469  emit dataChanged();
4470 
4471  return true;
4472 }
4473 
4474 QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
4475 {
4476  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4477  return 0;
4478 
4479  QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
4480 
4481  // make sure provider constraints are always present!
4482  if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
4483  {
4484  constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
4485  }
4486 
4487  return constraints;
4488 }
4489 
4491 {
4492  if ( index < 0 || index >= mFields.count() )
4493  return;
4494 
4495  QString name = mFields.at( index ).name();
4496 
4497  // add constraint to existing constraints
4498  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, 0 );
4499  constraints |= constraint;
4500  mFieldConstraints.insert( name, constraints );
4501 
4502  mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
4503 
4504  updateFields();
4505 }
4506 
4508 {
4509  if ( index < 0 || index >= mFields.count() )
4510  return;
4511 
4512  QString name = mFields.at( index ).name();
4513 
4514  // remove constraint from existing constraints
4515  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, 0 );
4516  constraints &= ~constraint;
4517  mFieldConstraints.insert( name, constraints );
4518 
4519  mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
4520 
4521  updateFields();
4522 }
4523 
4525 {
4526  if ( index < 0 || index >= mFields.count() )
4527  return QString();
4528 
4529  return mFields.at( index ).constraints().constraintExpression();
4530 }
4531 
4533 {
4534  if ( index < 0 || index >= mFields.count() )
4535  return QString();
4536 
4537  return mFields.at( index ).constraints().constraintDescription();
4538 }
4539 
4540 void QgsVectorLayer::setConstraintExpression( int index, const QString& expression, const QString& description )
4541 {
4542  if ( index < 0 || index >= mFields.count() )
4543  return;
4544 
4545  if ( expression.isEmpty() )
4546  {
4547  mFieldConstraintExpressions.remove( mFields.at( index ).name() );
4548  }
4549  else
4550  {
4551  mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
4552  }
4553  updateFields();
4554 }
4555 
4557 {
4558  if ( index < 0 || index >= mFields.count() )
4559  return;
4560 
4561  if ( setup.isNull() )
4562  mFieldWidgetSetups.remove( mFields.at( index ).name() );
4563  else
4564  mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
4565  updateFields();
4566 }
4567 
4569 {
4570 
4571  if ( index < 0 || index >= mFields.count() )
4572  return QgsEditorWidgetSetup();
4573 
4574  return mFields.at( index ).editorWidgetSetup();
4575 }
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.
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 cancelation of something running in a worker thread...
Definition: qgsfeedback.h:42
void setFieldConstraint(int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthHard)
Sets a constraint for a specified field index.
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.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:62
virtual QSet< QgsMapLayerDependency > dependencies() const override
Gets the list of dependencies.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
void displayExpressionChanged()
Emitted when the display expression changes.
void setAnnotationForm(const QString &ui)
Set annotation form for layer.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h: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.