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