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