QGIS API Documentation  2.99.0-Master (7705179)
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 "qgsexception.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"
55 #include "qgslogger.h"
56 #include "qgsmaplayerlegend.h"
57 #include "qgsmaptopixel.h"
58 #include "qgsmessagelog.h"
59 #include "qgsogcutils.h"
60 #include "qgspainting.h"
61 #include "qgspointxy.h"
62 #include "qgsproject.h"
63 #include "qgsproviderregistry.h"
64 #include "qgsrectangle.h"
65 #include "qgsrelationmanager.h"
66 #include "qgsrendercontext.h"
67 #include "qgsvectordataprovider.h"
73 #include "qgsvectorlayerlabeling.h"
74 #include "qgsvectorlayerrenderer.h"
77 #include "qgspoint.h"
78 #include "qgsrenderer.h"
79 #include "qgssymbollayer.h"
81 #include "qgsdiagramrenderer.h"
82 #include "qgsstyle.h"
83 #include "qgspallabeling.h"
84 #include "qgssimplifymethod.h"
85 #include "qgsexpressioncontext.h"
86 #include "qgsfeedback.h"
87 #include "qgsxmlutils.h"
88 #include "qgsunittypes.h"
89 #include "qgstaskmanager.h"
90 #include "qgstransaction.h"
91 
92 #include "diagram/qgsdiagram.h"
93 
94 #ifdef TESTPROVIDERLIB
95 #include <dlfcn.h>
96 #endif
97 
98 typedef bool saveStyle_t(
99  const QString &uri,
100  const QString &qmlStyle,
101  const QString &sldStyle,
102  const QString &styleName,
103  const QString &styleDescription,
104  const QString &uiFileContent,
105  bool useAsDefault,
106  QString &errCause
107 );
108 
109 typedef QString loadStyle_t(
110  const QString &uri,
111  QString &errCause
112 );
113 
114 typedef int listStyles_t(
115  const QString &uri,
116  QStringList &ids,
117  QStringList &names,
118  QStringList &descriptions,
119  QString &errCause
120 );
121 
122 typedef QString getStyleById_t(
123  const QString &uri,
124  QString styleID,
125  QString &errCause
126 );
127 
128 typedef bool deleteStyleById_t(
129  const QString &uri,
130  QString styleID,
131  QString &errCause
132 );
133 
134 
135 QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
136  const QString &baseName,
137  const QString &providerKey,
138  bool loadDefaultStyleFlag,
139  bool readExtentFromXml )
140  : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
141  , mProviderKey( providerKey )
142  , mReadOnly( false )
143  , mWkbType( QgsWkbTypes::Unknown )
144  , mLabelFontNotFoundNotified( false )
145  , mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
146  , mVertexMarkerOnlyForSelection( false )
147  , mValidExtent( false )
148  , mLazyExtent( true )
149  , mSymbolFeatureCounted( false )
150  , mEditCommandActive( false )
151  , mReadExtentFromXml( readExtentFromXml )
152 {
153  mActions = new QgsActionManager( this );
154  mConditionalStyles = new QgsConditionalLayerStyles();
155 
156  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
157  connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
158 
159  // if we're given a provider type, try to create and bind one to this layer
160  if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
161  {
162  setDataSource( vectorLayerPath, baseName, providerKey, loadDefaultStyleFlag );
163  }
164 
165  connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { emit repaintRequested(); } );
166  connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
167 
168  // Default simplify drawing settings
169  QgsSettings settings;
170  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( settings.value( QStringLiteral( "qgis/simplifyDrawingHints" ), static_cast< int>( mSimplifyMethod.simplifyHints() ) ).toInt() ) );
171  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( settings.value( QStringLiteral( "qgis/simplifyAlgorithm" ), static_cast< int>( mSimplifyMethod.simplifyAlgorithm() ) ).toInt() ) );
172  mSimplifyMethod.setThreshold( settings.value( QStringLiteral( "qgis/simplifyDrawingTol" ), mSimplifyMethod.threshold() ).toFloat() );
173  mSimplifyMethod.setForceLocalOptimization( settings.value( QStringLiteral( "qgis/simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ).toBool() );
174  mSimplifyMethod.setMaximumScale( settings.value( QStringLiteral( "qgis/simplifyMaxScale" ), mSimplifyMethod.maximumScale() ).toFloat() );
175 } // QgsVectorLayer ctor
176 
177 
178 
180 {
181  emit willBeDeleted();
182 
183  mValid = false;
184 
185  delete mDataProvider;
186  delete mEditBuffer;
187  delete mJoinBuffer;
188  delete mExpressionFieldBuffer;
189  delete mLabeling;
190  delete mDiagramLayerSettings;
191  delete mDiagramRenderer;
192 
193  delete mActions;
194 
195  delete mRenderer;
196  delete mConditionalStyles;
197 
198  if ( mFeatureCounter )
199  mFeatureCounter->cancel();
200 }
201 
203 {
204  QgsVectorLayer *layer = new QgsVectorLayer( source(), originalName(), mProviderKey );
205  QgsMapLayer::clone( layer );
206 
207  QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
208  Q_FOREACH ( const QgsVectorLayerJoinInfo &join, joins )
209  {
210  layer->addJoin( join );
211  }
212 
213  layer->setProviderEncoding( dataProvider()->encoding() );
215  layer->setMapTipTemplate( mapTipTemplate() );
216  layer->setReadOnly( isReadOnly() );
217  layer->selectByIds( selectedFeatureIds() );
222  layer->setOpacity( opacity() );
224 
225  Q_FOREACH ( const QgsAction &action, actions()->actions() )
226  {
227  layer->actions()->addAction( action );
228  }
229 
230  if ( renderer() )
231  {
232  layer->setRenderer( renderer()->clone() );
233  }
234 
235  if ( labeling() )
236  {
237  layer->setLabeling( labeling()->clone() );
238  }
239  layer->setSimplifyMethod( simplifyMethod() );
240 
241  if ( diagramRenderer() )
242  {
244  }
245 
246  if ( diagramLayerSettings() )
247  {
249  }
250 
251  for ( int i = 0; i < fields().count(); i++ )
252  {
253  layer->setFieldAlias( i, attributeAlias( i ) );
254  layer->setEditorWidgetSetup( i, editorWidgetSetup( i ) );
257 
258  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> constraints = fieldConstraintsAndStrength( i );
259  auto constraintIt = constraints.constBegin();
260  for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
261  {
262  layer->setFieldConstraint( i, constraintIt.key(), constraintIt.value() );
263  }
264 
266  {
267  layer->addExpressionField( expressionField( i ), fields().at( i ) );
268  }
269  }
270 
271  layer->setEditFormConfig( editFormConfig() );
272 
273  return layer;
274 }
275 
277 {
278  if ( mDataProvider )
279  {
280  return mDataProvider->storageType();
281  }
282  return QString();
283 }
284 
285 
287 {
288  if ( mDataProvider )
289  {
290  return mDataProvider->capabilitiesString();
291  }
292  return QString();
293 }
294 
296 {
297  if ( mDataProvider )
298  {
299  return mDataProvider->dataComment();
300  }
301  return QString();
302 }
303 
304 
306 {
307  return mProviderKey;
308 }
309 
311 {
312  return crs();
313 }
314 
316 {
317  return name();
318 }
319 
321 {
322  if ( mDataProvider )
323  {
324  mDataProvider->reloadData();
325  updateFields();
326  }
327 }
328 
330 {
331  return new QgsVectorLayerRenderer( this, rendererContext );
332 }
333 
334 
335 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int m )
336 {
338  {
339  p.setPen( QColor( 50, 100, 120, 200 ) );
340  p.setBrush( QColor( 200, 200, 210, 120 ) );
341  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
342  }
343  else if ( type == QgsVectorLayer::Cross )
344  {
345  p.setPen( QColor( 255, 0, 0 ) );
346  p.drawLine( x - m, y + m, x + m, y - m );
347  p.drawLine( x - m, y - m, x + m, y + m );
348  }
349 }
350 
352 {
353  mSelectedFeatureIds.insert( fid );
354 
355  emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
356 }
357 
358 void QgsVectorLayer::select( const QgsFeatureIds &featureIds )
359 {
360  mSelectedFeatureIds.unite( featureIds );
361 
362  emit selectionChanged( featureIds, QgsFeatureIds(), false );
363 }
364 
366 {
367  mSelectedFeatureIds.remove( fid );
368 
369  emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
370 }
371 
372 void QgsVectorLayer::deselect( const QgsFeatureIds &featureIds )
373 {
374  mSelectedFeatureIds.subtract( featureIds );
375 
376  emit selectionChanged( QgsFeatureIds(), featureIds, false );
377 }
378 
380 {
381  // normalize the rectangle
382  rect.normalize();
383 
384  QgsFeatureIds newSelection;
385 
387  .setFilterRect( rect )
389  .setSubsetOfAttributes( QgsAttributeList() ) );
390 
391  QgsFeature feat;
392  while ( features.nextFeature( feat ) )
393  {
394  newSelection << feat.id();
395  }
396  features.close();
397 
398  selectByIds( newSelection, behavior );
399 }
400 
401 void QgsVectorLayer::selectByExpression( const QString &expression, QgsVectorLayer::SelectBehavior behavior )
402 {
403  QgsFeatureIds newSelection;
404 
406 
407  if ( behavior == SetSelection || behavior == AddToSelection )
408  {
410  .setExpressionContext( context )
413 
414  QgsFeatureIterator features = getFeatures( request );
415 
416  if ( behavior == AddToSelection )
417  {
418  newSelection = selectedFeatureIds();
419  }
420  QgsFeature feat;
421  while ( features.nextFeature( feat ) )
422  {
423  newSelection << feat.id();
424  }
425  features.close();
426  }
427  else if ( behavior == IntersectSelection || behavior == RemoveFromSelection )
428  {
429  QgsExpression exp( expression );
430  exp.prepare( &context );
431 
432  QgsFeatureIds oldSelection = selectedFeatureIds();
433  QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
434 
435  //refine request
436  if ( !exp.needsGeometry() )
438  request.setSubsetOfAttributes( exp.referencedColumns(), fields() );
439 
440  QgsFeatureIterator features = getFeatures( request );
441  QgsFeature feat;
442  while ( features.nextFeature( feat ) )
443  {
444  context.setFeature( feat );
445  bool matches = exp.evaluate( &context ).toBool();
446 
447  if ( matches && behavior == IntersectSelection )
448  {
449  newSelection << feat.id();
450  }
451  else if ( !matches && behavior == RemoveFromSelection )
452  {
453  newSelection << feat.id();
454  }
455  }
456  }
457 
458  selectByIds( newSelection );
459 }
460 
462 {
463  QgsFeatureIds newSelection;
464 
465  switch ( behavior )
466  {
467  case SetSelection:
468  newSelection = ids;
469  break;
470 
471  case AddToSelection:
472  newSelection = mSelectedFeatureIds + ids;
473  break;
474 
475  case RemoveFromSelection:
476  newSelection = mSelectedFeatureIds - ids;
477  break;
478 
479  case IntersectSelection:
480  newSelection = mSelectedFeatureIds.intersect( ids );
481  break;
482  }
483 
484  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
485  mSelectedFeatureIds = newSelection;
486 
487  emit selectionChanged( newSelection, deselectedFeatures, true );
488 }
489 
490 void QgsVectorLayer::modifySelection( const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds )
491 {
492  QgsFeatureIds intersectingIds = selectIds & deselectIds;
493  if ( !intersectingIds.isEmpty() )
494  {
495  QgsDebugMsg( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." );
496  }
497 
498  mSelectedFeatureIds -= deselectIds;
499  mSelectedFeatureIds += selectIds;
500 
501  emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
502 }
503 
505 {
507  ids.subtract( mSelectedFeatureIds );
508  selectByIds( ids );
509 }
510 
512 {
514 }
515 
517 {
518  // normalize the rectangle
519  rect.normalize();
520 
522  .setFilterRect( rect )
524  .setSubsetOfAttributes( QgsAttributeList() ) );
525 
526  QgsFeatureIds selectIds;
527  QgsFeatureIds deselectIds;
528 
529  QgsFeature fet;
530  while ( fit.nextFeature( fet ) )
531  {
532  if ( mSelectedFeatureIds.contains( fet.id() ) )
533  {
534  deselectIds << fet.id();
535  }
536  else
537  {
538  selectIds << fet.id();
539  }
540  }
541 
542  modifySelection( selectIds, deselectIds );
543 }
544 
546 {
547  if ( mSelectedFeatureIds.isEmpty() )
548  return;
549 
551 }
552 
554 {
555  return mDataProvider;
556 }
557 
559 {
560  return mDataProvider;
561 }
562 
563 void QgsVectorLayer::setProviderEncoding( const QString &encoding )
564 {
565  if ( mValid && mDataProvider && mDataProvider->encoding() != encoding )
566  {
567  mDataProvider->setEncoding( encoding );
568  updateFields();
569  }
570 }
571 
573 {
574  delete mDiagramRenderer;
575  mDiagramRenderer = r;
576  emit rendererChanged();
577  emit styleChanged();
578 }
579 
581 {
582  if ( mValid && mDataProvider )
583  {
584  return QgsWkbTypes::geometryType( mDataProvider->wkbType() );
585  }
586  else
587  {
588  QgsDebugMsg( "invalid layer or pointer to mDataProvider is null" );
589  }
590 
591  // We shouldn't get here, and if we have, other things are likely to
592  // go wrong. Code that uses the type() return value should be
593  // rewritten to cope with a value of Qgis::Unknown. To make this
594  // need known, the following message is printed every time we get
595  // here.
596  QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
597 
599 }
600 
602 {
603  return mWkbType;
604 }
605 
607 {
608  if ( !mValid || !isSpatial() || mSelectedFeatureIds.isEmpty() ) //no selected features
609  {
610  return QgsRectangle( 0, 0, 0, 0 );
611  }
612 
613  QgsRectangle r, retval;
614  retval.setMinimal();
615 
616  QgsFeature fet;
617  if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
618  {
620  .setFilterFids( mSelectedFeatureIds )
621  .setSubsetOfAttributes( QgsAttributeList() ) );
622 
623  while ( fit.nextFeature( fet ) )
624  {
625  if ( !fet.hasGeometry() )
626  continue;
627  r = fet.geometry().boundingBox();
628  retval.combineExtentWith( r );
629  }
630  }
631  else
632  {
634  .setSubsetOfAttributes( QgsAttributeList() ) );
635 
636  while ( fit.nextFeature( fet ) )
637  {
638  if ( mSelectedFeatureIds.contains( fet.id() ) )
639  {
640  if ( fet.hasGeometry() )
641  {
642  r = fet.geometry().boundingBox();
643  retval.combineExtentWith( r );
644  }
645  }
646  }
647  }
648 
649  if ( retval.width() == 0.0 || retval.height() == 0.0 )
650  {
651  // If all of the features are at the one point, buffer the
652  // rectangle a bit. If they are all at zero, do something a bit
653  // more crude.
654 
655  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
656  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
657  {
658  retval.set( -1.0, -1.0, 1.0, 1.0 );
659  }
660  }
661 
662  return retval;
663 }
664 
666 {
667  return static_cast< bool >( mLabeling );
668 }
669 
671 {
672  if ( !mDiagramRenderer || !mDiagramLayerSettings )
673  return false;
674 
675  QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
676  if ( !settingList.isEmpty() )
677  {
678  return settingList.at( 0 ).enabled;
679  }
680  return false;
681 }
682 
683 long QgsVectorLayer::featureCount( const QString &legendKey ) const
684 {
685  if ( !mSymbolFeatureCounted )
686  return -1;
687 
688  return mSymbolFeatureCountMap.value( legendKey );
689 }
690 
696 {
697  public:
698 
701  : mDialog( dialog )
702  {
703  }
704 
705  bool mustStop() const override
706  {
707  if ( mDialog->isVisible() )
708  {
709  // So that we get a chance of hitting the Abort button
710 #ifdef Q_OS_LINUX
711  // For some reason on Windows hasPendingEvents() always return true,
712  // but one iteration is actually enough on Windows to get good interactivity
713  // whereas on Linux we must allow for far more iterations.
714  // For safety limit the number of iterations
715  int nIters = 0;
716  while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
717 #endif
718  {
719  QCoreApplication::processEvents();
720  }
721  return mDialog->wasCanceled();
722  }
723  return false;
724  }
725 
726  private:
727  QProgressDialog *mDialog = nullptr;
728 };
729 
731 {
732  if ( mSymbolFeatureCounted || mFeatureCounter )
733  return mFeatureCounter;
734 
735  mSymbolFeatureCountMap.clear();
736 
737  if ( !mValid )
738  {
739  QgsDebugMsg( "invoked with invalid layer" );
740  return mFeatureCounter;
741  }
742  if ( !mDataProvider )
743  {
744  QgsDebugMsg( "invoked with null mDataProvider" );
745  return mFeatureCounter;
746  }
747  if ( !mRenderer )
748  {
749  QgsDebugMsg( "invoked with null mRenderer" );
750  return mFeatureCounter;
751  }
752 
753  if ( !mFeatureCounter )
754  {
755  mFeatureCounter = new QgsVectorLayerFeatureCounter( this );
756  connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted );
757  connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated );
758 
759  QgsApplication::taskManager()->addTask( mFeatureCounter );
760  }
761 
762  return mFeatureCounter;
763 }
764 
766 {
767  // do not update extent by default when trust project option is activated
768  if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.isNull() ) )
769  mValidExtent = false;
770 }
771 
773 {
775  mValidExtent = true;
776 }
777 
779 {
780  QgsRectangle rect;
781  rect.setMinimal();
782 
783  if ( !isSpatial() )
784  return rect;
785 
786 
787  if ( !mValidExtent && mLazyExtent && mDataProvider && !mDataProvider->hasMetadata() && mReadExtentFromXml && !mXmlExtent.isNull() )
788  {
789  mExtent = mXmlExtent;
790  mValidExtent = true;
791  mLazyExtent = false;
792  }
793 
794  if ( !mValidExtent && mLazyExtent && mDataProvider )
795  {
796  // get the extent
797  QgsRectangle mbr = mDataProvider->extent();
798 
799  // show the extent
800  QgsDebugMsg( "Extent of layer: " + mbr.toString() );
801  // store the extent
802  mValidExtent = true;
803  mExtent = mbr;
804 
805  mLazyExtent = false;
806  }
807 
808  if ( mValidExtent )
809  return QgsMapLayer::extent();
810 
811  if ( !mValid || !mDataProvider )
812  {
813  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
814  return rect;
815  }
816 
817  if ( !mEditBuffer ||
818  ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() ) ||
819  QgsDataSourceUri( mDataProvider->dataSourceUri() ).useEstimatedMetadata() )
820  {
821  mDataProvider->updateExtents();
822 
823  // get the extent of the layer from the provider
824  // but only when there are some features already
825  if ( mDataProvider->featureCount() != 0 )
826  {
827  QgsRectangle r = mDataProvider->extent();
828  rect.combineExtentWith( r );
829  }
830 
831  if ( mEditBuffer )
832  {
833  for ( QgsFeatureMap::const_iterator it = mEditBuffer->mAddedFeatures.constBegin(); it != mEditBuffer->mAddedFeatures.constEnd(); ++it )
834  {
835  if ( it->hasGeometry() )
836  {
837  QgsRectangle r = it->geometry().boundingBox();
838  rect.combineExtentWith( r );
839  }
840  }
841  }
842  }
843  else
844  {
846  .setSubsetOfAttributes( QgsAttributeList() ) );
847 
848  QgsFeature fet;
849  while ( fit.nextFeature( fet ) )
850  {
851  if ( fet.hasGeometry() && fet.geometry().type() != QgsWkbTypes::UnknownGeometry )
852  {
853  QgsRectangle bb = fet.geometry().boundingBox();
854  rect.combineExtentWith( bb );
855  }
856  }
857  }
858 
859  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
860  {
861  // special case when there are no features in provider nor any added
862  rect = QgsRectangle(); // use rectangle with zero coordinates
863  }
864 
865  mValidExtent = true;
866  mExtent = rect;
867 
868  // Send this (hopefully) up the chain to the map canvas
869  emit recalculateExtents();
870 
871  return rect;
872 }
873 
875 {
876  return extent();
877 }
878 
880 {
881  if ( !mValid || !mDataProvider )
882  {
883  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
884  return QString();
885  }
886  return mDataProvider->subsetString();
887 }
888 
889 bool QgsVectorLayer::setSubsetString( const QString &subset )
890 {
891  if ( !mValid || !mDataProvider )
892  {
893  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
894  return false;
895  }
896 
897  bool res = mDataProvider->setSubsetString( subset );
898 
899  // get the updated data source string from the provider
900  mDataSource = mDataProvider->dataSourceUri();
901  updateExtents();
902  updateFields();
903 
904  if ( res )
905  emit repaintRequested();
906 
907  return res;
908 }
909 
911 {
912  if ( mValid && mDataProvider && !mEditBuffer && ( isSpatial() && geometryType() != QgsWkbTypes::PointGeometry ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
913  {
914  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
915 
916  // check maximum scale at which generalisation should be carried out
917  return !( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale );
918  }
919  return false;
920 }
921 
923 {
924  return mConditionalStyles;
925 }
926 
928 {
929  if ( !mValid || !mDataProvider )
930  return QgsFeatureIterator();
931 
932  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
933 }
934 
935 bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
936 {
937  if ( !mValid || !mEditBuffer || !mDataProvider )
938  return false;
939 
940  bool success = mEditBuffer->addFeature( feature );
941 
942  if ( success )
943  {
944  updateExtents();
945 
946  if ( mJoinBuffer->containsJoins() )
947  success = mJoinBuffer->addFeature( feature );
948  }
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 QgsPoint &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 QgsPoint &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<QgsPointXY> &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<QgsPointXY> &points )
1157 {
1158  if ( !mValid || !mEditBuffer || !mDataProvider )
1159  return 7;
1160 
1161  //number of selected features must be 1
1162 
1163  if ( mSelectedFeatureIds.empty() )
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.empty() )
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.empty() )
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<QgsPointXY> &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<QgsPointXY> &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
1329  connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
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  // read extent
1425  if ( mReadExtentFromXml )
1426  {
1427  QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1428  if ( !extentNode.isNull() )
1429  {
1430  mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1431  }
1432  }
1433 
1434  return mValid; // should be true if read successfully
1435 
1436 } // void QgsVectorLayer::readXml
1437 
1438 
1439 void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag )
1440 {
1442 
1443  mDataSource = dataSource;
1444  mLayerName = capitalizeLayerName( baseName );
1445  setName( mLayerName );
1446  setDataProvider( provider );
1447 
1448  if ( !mValid )
1449  return;
1450 
1451  // Always set crs
1453 
1454  // reset style if loading default style, style is missing, or geometry type has changed
1455  if ( !renderer() || !legend() || geomType != geometryType() || loadDefaultStyleFlag )
1456  {
1457  // check if there is a default style / propertysheet defined
1458  // for this layer and if so apply it
1459  bool defaultLoadedFlag = false;
1460  if ( loadDefaultStyleFlag )
1461  {
1462  loadDefaultStyle( defaultLoadedFlag );
1463  }
1464 
1465  // if the default style failed to load or was disabled use some very basic defaults
1466  if ( !defaultLoadedFlag && isSpatial() )
1467  {
1468  // add single symbol renderer
1470  }
1471 
1473  }
1474 
1475  emit repaintRequested();
1476 }
1477 
1478 
1479 bool QgsVectorLayer::setDataProvider( QString const &provider )
1480 {
1481  mProviderKey = provider; // XXX is this necessary? Usually already set
1482 
1483  // primary key unicity is tested at construction time, so it has to be set
1484  // before initializing postgres provider
1485  QString checkUnicityKey = QStringLiteral( "checkPrimaryKeyUnicity" );
1486  QString dataSource = mDataSource;
1487  if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
1488  {
1489  QgsDataSourceUri uri( dataSource );
1490 
1491  if ( uri.hasParam( checkUnicityKey ) )
1492  uri.removeParam( checkUnicityKey );
1493 
1494  uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
1495  dataSource = uri.uri( false );
1496  }
1497 
1498  // XXX when execution gets here.
1499 
1500  //XXX - This was a dynamic cast but that kills the Windows
1501  // version big-time with an abnormal termination error
1502  delete mDataProvider;
1503  mDataProvider = ( QgsVectorDataProvider * )( QgsProviderRegistry::instance()->createProvider( provider, dataSource ) );
1504  if ( !mDataProvider )
1505  {
1506  QgsDebugMsg( " unable to get data provider" );
1507  return false;
1508  }
1509 
1510  connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1511 
1512  QgsDebugMsg( "Instantiated the data provider plugin" );
1513 
1514  mValid = mDataProvider->isValid();
1515  if ( !mValid )
1516  {
1517  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1518  return false;
1519  }
1520 
1521  // TODO: Check if the provider has the capability to send fullExtentCalculated
1522  connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
1523 
1524  // get and store the feature type
1525  mWkbType = mDataProvider->wkbType();
1526 
1527  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1528  updateFields();
1529 
1530  if ( mProviderKey == QLatin1String( "postgres" ) )
1531  {
1532  QgsDebugMsg( "Beautifying layer name " + name() );
1533 
1534  // adjust the display name for postgres layers
1535  QRegExp reg( R"lit("[^"]+"\."([^"] + )"( \([^)]+\))?)lit" );
1536  if ( reg.indexIn( name() ) >= 0 )
1537  {
1538  QStringList stuff = reg.capturedTexts();
1539  QString lName = stuff[1];
1540 
1541  const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
1542 
1543  QMap<QString, QgsMapLayer *>::const_iterator it;
1544  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1545  ;
1546 
1547  if ( it != layers.constEnd() && stuff.size() > 2 )
1548  {
1549  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1550  }
1551 
1552  if ( !lName.isEmpty() )
1553  setName( lName );
1554  }
1555 
1556  QgsDebugMsg( "Beautified layer name " + name() );
1557 
1558  // deal with unnecessary schema qualification to make v.in.ogr happy
1559  // and remove unnecessary key
1560  QgsDataSourceUri dataProviderUri( mDataProvider->dataSourceUri() );
1561  if ( dataProviderUri.hasParam( checkUnicityKey ) )
1562  dataProviderUri.removeParam( checkUnicityKey );
1563  mDataSource = dataProviderUri.uri( false );
1564  }
1565  else if ( mProviderKey == QLatin1String( "osm" ) )
1566  {
1567  // make sure that the "observer" has been removed from URI to avoid crashes
1568  mDataSource = mDataProvider->dataSourceUri();
1569  }
1570  else if ( provider == QLatin1String( "ogr" ) )
1571  {
1572  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1573  mDataSource = mDataProvider->dataSourceUri();
1574  if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1575  mDataSource.chop( 10 );
1576  }
1577  else if ( provider == QStringLiteral( "memory" ) )
1578  {
1579  // required so that source differs between memory layers
1580  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1581  }
1582 
1583  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::dataChanged );
1584  connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::removeSelection );
1585 
1586  return true;
1587 } // QgsVectorLayer:: setDataProvider
1588 
1589 
1590 
1591 
1592 /* virtual */
1593 bool QgsVectorLayer::writeXml( QDomNode &layer_node,
1594  QDomDocument &document,
1595  const QgsReadWriteContext &context ) const
1596 {
1597  // first get the layer element so that we can append the type attribute
1598 
1599  QDomElement mapLayerNode = layer_node.toElement();
1600 
1601  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1602  {
1603  QgsDebugMsg( "can't find <maplayer>" );
1604  return false;
1605  }
1606 
1607  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "vector" ) );
1608 
1609  // set the geometry type
1610  mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1611 
1612  // add provider node
1613  if ( mDataProvider )
1614  {
1615  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1616  provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1617  QDomText providerText = document.createTextNode( providerType() );
1618  provider.appendChild( providerText );
1619  layer_node.appendChild( provider );
1620  }
1621 
1622  //save joins
1623  mJoinBuffer->writeXml( layer_node, document );
1624 
1625  // dependencies
1626  QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1627  Q_FOREACH ( const QgsMapLayerDependency &dep, dependencies() )
1628  {
1630  continue;
1631  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1632  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1633  dependenciesElement.appendChild( depElem );
1634  }
1635  layer_node.appendChild( dependenciesElement );
1636 
1637  // change dependencies
1638  QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1639  Q_FOREACH ( const QgsMapLayerDependency &dep, dependencies() )
1640  {
1642  continue;
1643  QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1644  depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1645  dataDependenciesElement.appendChild( depElem );
1646  }
1647  layer_node.appendChild( dataDependenciesElement );
1648 
1649  // save expression fields
1650  mExpressionFieldBuffer->writeXml( layer_node, document );
1651 
1652  writeStyleManager( layer_node, document );
1653 
1654  // renderer specific settings
1655  QString errorMsg;
1656  return writeSymbology( layer_node, document, errorMsg, context );
1657 } // bool QgsVectorLayer::writeXml
1658 
1659 
1661 {
1662  mJoinBuffer->resolveReferences( project );
1663 }
1664 
1665 
1666 bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage, const QgsReadWriteContext &context )
1667 {
1668  if ( !mExpressionFieldBuffer )
1669  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1670  mExpressionFieldBuffer->readXml( layerNode );
1671 
1672  updateFields();
1673 
1674  readStyle( layerNode, errorMessage, context );
1675 
1676  mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
1677  mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
1678 
1679  QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
1680 
1681  // Try to migrate pre QGIS 3.0 display field property
1682  if ( mFields.lookupField( displayField ) < 0 )
1683  {
1684  // if it's not a field, it's a maptip
1685  if ( mMapTipTemplate.isEmpty() )
1686  mMapTipTemplate = displayField;
1687  }
1688  else
1689  {
1690  if ( mDisplayExpression.isEmpty() )
1691  mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
1692  }
1693 
1694  // process the attribute actions
1695  mActions->readXml( layerNode );
1696 
1697  mAttributeAliasMap.clear();
1698  QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
1699  if ( !aliasesNode.isNull() )
1700  {
1701  QDomElement aliasElem;
1702 
1703  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
1704  for ( int i = 0; i < aliasNodeList.size(); ++i )
1705  {
1706  aliasElem = aliasNodeList.at( i ).toElement();
1707 
1708  QString field;
1709  if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
1710  {
1711  field = aliasElem.attribute( QStringLiteral( "field" ) );
1712  }
1713  else
1714  {
1715  int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
1716 
1717  if ( index >= 0 && index < fields().count() )
1718  field = fields().at( index ).name();
1719  }
1720 
1721  mAttributeAliasMap.insert( field, aliasElem.attribute( QStringLiteral( "name" ) ) );
1722  }
1723  }
1724 
1725  // default expressions
1726  mDefaultExpressionMap.clear();
1727  QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
1728  if ( !defaultsNode.isNull() )
1729  {
1730  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
1731  for ( int i = 0; i < defaultNodeList.size(); ++i )
1732  {
1733  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
1734 
1735  QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
1736  QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
1737  if ( field.isEmpty() || expression.isEmpty() )
1738  continue;
1739 
1740  mDefaultExpressionMap.insert( field, expression );
1741  }
1742  }
1743 
1744  // constraints
1745  mFieldConstraints.clear();
1746  mFieldConstraintStrength.clear();
1747  QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
1748  if ( !constraintsNode.isNull() )
1749  {
1750  QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
1751  for ( int i = 0; i < constraintNodeList.size(); ++i )
1752  {
1753  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
1754 
1755  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
1756  int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
1757  if ( field.isEmpty() || constraints == 0 )
1758  continue;
1759 
1760  mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
1761 
1762  int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
1763  int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
1764  int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
1765 
1766  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
1767  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
1768  mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
1769  }
1770  }
1771  mFieldConstraintExpressions.clear();
1772  QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
1773  if ( !constraintExpressionsNode.isNull() )
1774  {
1775  QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
1776  for ( int i = 0; i < constraintNodeList.size(); ++i )
1777  {
1778  QDomElement constraintElem = constraintNodeList.at( i ).toElement();
1779 
1780  QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
1781  QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
1782  QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
1783  if ( field.isEmpty() || exp.isEmpty() )
1784  continue;
1785 
1786  mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
1787  }
1788  }
1789 
1790  updateFields();
1791 
1792  //Attributes excluded from WMS and WFS
1793  mExcludeAttributesWMS.clear();
1794  QDomNode excludeWMSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWMS" ) );
1795  if ( !excludeWMSNode.isNull() )
1796  {
1797  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
1798  for ( int i = 0; i < attributeNodeList.size(); ++i )
1799  {
1800  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1801  }
1802  }
1803 
1804  mExcludeAttributesWFS.clear();
1805  QDomNode excludeWFSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWFS" ) );
1806  if ( !excludeWFSNode.isNull() )
1807  {
1808  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
1809  for ( int i = 0; i < attributeNodeList.size(); ++i )
1810  {
1811  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1812  }
1813  }
1814 
1815  // Load editor widget configuration
1816  QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
1817 
1818  QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
1819 
1820  for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
1821  {
1822  const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
1823  const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
1824 
1825  QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
1826 
1827  const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
1828  const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
1829  const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
1830  QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
1831  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
1832  mFieldWidgetSetups[fieldName] = setup;
1833  }
1834 
1835  mEditFormConfig.readXml( layerNode, context );
1836 
1837  mAttributeTableConfig.readXml( layerNode );
1838 
1839  mConditionalStyles->readXml( layerNode, context );
1840 
1841  readCustomProperties( layerNode, QStringLiteral( "variable" ) );
1842 
1843  QDomElement mapLayerNode = layerNode.toElement();
1844  if ( mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
1845  mReadOnly = true;
1846 
1847  updateFields();
1848 
1849  return true;
1850 }
1851 
1852 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context )
1853 {
1854  bool result = true;
1855  emit readCustomSymbology( node.toElement(), errorMessage );
1856 
1857  if ( isSpatial() )
1858  {
1859  // try renderer v2 first
1860  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1861  if ( !rendererElement.isNull() )
1862  {
1863  QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
1864  if ( r )
1865  {
1866  setRenderer( r );
1867  }
1868  else
1869  {
1870  result = false;
1871  }
1872  }
1873 
1874  // make sure layer has a renderer - if none exists, fallback to a default renderer
1875  if ( !renderer() )
1876  {
1878  }
1879 
1880  // read labeling definition
1881  QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
1883  if ( labelingElement.isNull() ||
1884  ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
1885  {
1886  // make sure we have custom properties for labeling for 2.x projects
1887  // (custom properties should be already loaded when reading the whole layer from XML,
1888  // but when reading style, custom properties are not read)
1889  readCustomProperties( node, QStringLiteral( "labeling" ) );
1890 
1891  // support for pre-QGIS 3 labeling configurations written in custom properties
1892  labeling = readLabelingFromCustomProperties();
1893  }
1894  else
1895  {
1896  labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
1897  }
1898  setLabeling( labeling );
1899 
1900  // get and set the blend mode if it exists
1901  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1902  if ( !blendModeNode.isNull() )
1903  {
1904  QDomElement e = blendModeNode.toElement();
1905  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1906  }
1907 
1908  // get and set the feature blend mode if it exists
1909  QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
1910  if ( !featureBlendModeNode.isNull() )
1911  {
1912  QDomElement e = featureBlendModeNode.toElement();
1913  setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1914  }
1915 
1916  // get and set the layer transparency if it exists
1917  QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
1918  if ( !layerTransparencyNode.isNull() )
1919  {
1920  QDomElement e = layerTransparencyNode.toElement();
1921  setOpacity( 1.0 - e.text().toInt() / 100.0 );
1922  }
1923  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1924  if ( !layerOpacityNode.isNull() )
1925  {
1926  QDomElement e = layerOpacityNode.toElement();
1927  setOpacity( e.text().toDouble() );
1928  }
1929 
1930  QDomElement e = node.toElement();
1931 
1932  // get the simplification drawing settings
1933  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
1934  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
1935  mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
1936  mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
1937  mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
1938 
1939  //diagram renderer and diagram layer settings
1940  delete mDiagramRenderer;
1941  mDiagramRenderer = nullptr;
1942  QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
1943  if ( !singleCatDiagramElem.isNull() )
1944  {
1945  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1946  mDiagramRenderer->readXml( singleCatDiagramElem, context );
1947  }
1948  QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
1949  if ( !linearDiagramElem.isNull() )
1950  {
1951  if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
1952  {
1953  // fix project from before QGIS 3.0
1954  int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
1955  if ( idx >= 0 && idx < mFields.count() )
1956  linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
1957  }
1958 
1959  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
1960  mDiagramRenderer->readXml( linearDiagramElem, context );
1961  }
1962 
1963  if ( mDiagramRenderer )
1964  {
1965  QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
1966  if ( !diagramSettingsElem.isNull() )
1967  {
1968  bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
1969  bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
1970  bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
1971  if ( oldXPos || oldYPos || oldShow )
1972  {
1973  // fix project from before QGIS 3.0
1975  if ( oldXPos )
1976  {
1977  int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
1978  if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
1979  ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
1980  }
1981  if ( oldYPos )
1982  {
1983  int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
1984  if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
1985  ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
1986  }
1987  if ( oldShow )
1988  {
1989  int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
1990  if ( showColumn >= 0 && showColumn < mFields.count() )
1991  ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
1992  }
1993  QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
1995  {
1996  { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
1997  { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
1998  { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
1999  };
2000  ddp.writeXml( propertiesElem, defs );
2001  diagramSettingsElem.appendChild( propertiesElem );
2002  }
2003 
2004  delete mDiagramLayerSettings;
2005  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2006  mDiagramLayerSettings->readXml( diagramSettingsElem );
2007  }
2008  }
2009  }
2010  return result;
2011 }
2012 
2013 bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
2014 {
2015  ( void )writeStyle( node, doc, errorMessage, context );
2016 
2017  QDomElement fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2018  node.appendChild( fieldConfigurationElement );
2019 
2020  int index = 0;
2021  Q_FOREACH ( const QgsField &field, mFields )
2022  {
2023 
2024  QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2025  fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2026 
2027  fieldConfigurationElement.appendChild( fieldElement );
2028 
2029  QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
2030 
2031  // TODO : wrap this part in an if to only save if it was user-modified
2032  QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2033  fieldElement.appendChild( editWidgetElement );
2034  editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2035  QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2036 
2037  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2038  editWidgetElement.appendChild( editWidgetConfigElement );
2039  // END TODO : wrap this part in an if to only save if it was user-modified
2040 
2041  ++index;
2042  }
2043 
2044  //attribute aliases
2045  QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2046  Q_FOREACH ( const QgsField &field, mFields )
2047  {
2048  QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2049  aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2050  aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2051  aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2052  aliasElem.appendChild( aliasEntryElem );
2053  }
2054  node.appendChild( aliasElem );
2055 
2056  //exclude attributes WMS
2057  QDomElement excludeWMSElem = doc.createElement( QStringLiteral( "excludeAttributesWMS" ) );
2058  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2059  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2060  {
2061  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2062  QDomText attrText = doc.createTextNode( *attWMSIt );
2063  attrElem.appendChild( attrText );
2064  excludeWMSElem.appendChild( attrElem );
2065  }
2066  node.appendChild( excludeWMSElem );
2067 
2068  //exclude attributes WFS
2069  QDomElement excludeWFSElem = doc.createElement( QStringLiteral( "excludeAttributesWFS" ) );
2070  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2071  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2072  {
2073  QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
2074  QDomText attrText = doc.createTextNode( *attWFSIt );
2075  attrElem.appendChild( attrText );
2076  excludeWFSElem.appendChild( attrElem );
2077  }
2078  node.appendChild( excludeWFSElem );
2079 
2080  //default expressions
2081  QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2082  Q_FOREACH ( const QgsField &field, mFields )
2083  {
2084  QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2085  defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2086  defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueExpression() );
2087  defaultsElem.appendChild( defaultElem );
2088  }
2089  node.appendChild( defaultsElem );
2090 
2091  // constraints
2092  QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2093  Q_FOREACH ( const QgsField &field, mFields )
2094  {
2095  QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2096  constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2097  constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2098  constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2099  constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2100  constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2101  constraintsElem.appendChild( constraintElem );
2102  }
2103  node.appendChild( constraintsElem );
2104 
2105  // constraint expressions
2106  QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2107  Q_FOREACH ( const QgsField &field, mFields )
2108  {
2109  QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2110  constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2111  constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2112  constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2113  constraintExpressionsElem.appendChild( constraintExpressionElem );
2114  }
2115  node.appendChild( constraintExpressionsElem );
2116 
2117  // add attribute actions
2118  mActions->writeXml( node );
2119  mAttributeTableConfig.writeXml( node );
2120  mEditFormConfig.writeXml( node, context );
2121  mConditionalStyles->writeXml( node, doc, context );
2122 
2123  // save expression fields
2124  if ( !mExpressionFieldBuffer )
2125  {
2126  // can happen when saving style on a invalid layer
2128  dummy.writeXml( node, doc );
2129  }
2130  else
2131  mExpressionFieldBuffer->writeXml( node, doc );
2132 
2133  // save readonly state
2134  node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2135 
2136  // save preview expression
2137  QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2138  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2139  prevExpElem.appendChild( prevExpText );
2140  node.appendChild( prevExpElem );
2141 
2142  // save map tip
2143  QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2144  QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2145  mapTipElem.appendChild( mapTipText );
2146  node.toElement().appendChild( mapTipElem );
2147 
2148  return true;
2149 }
2150 
2151 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
2152 {
2153  QDomElement mapLayerNode = node.toElement();
2154 
2155  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2156 
2157  if ( isSpatial() )
2158  {
2159  if ( mRenderer )
2160  {
2161  QDomElement rendererElement = mRenderer->save( doc, context );
2162  node.appendChild( rendererElement );
2163  }
2164 
2165  if ( mLabeling )
2166  {
2167  QDomElement labelingElement = mLabeling->save( doc, context );
2168  node.appendChild( labelingElement );
2169  }
2170 
2171  // save the simplification drawing settings
2172  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2173  mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2174  mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2175  mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2176  mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2177 
2178  //save customproperties
2179  writeCustomProperties( node, doc );
2180 
2181  // add the blend mode field
2182  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2183  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2184  blendModeElem.appendChild( blendModeText );
2185  node.appendChild( blendModeElem );
2186 
2187  // add the feature blend mode field
2188  QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2189  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2190  featureBlendModeElem.appendChild( featureBlendModeText );
2191  node.appendChild( featureBlendModeElem );
2192 
2193  // add the layer opacity
2194  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
2195  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
2196  layerOpacityElem.appendChild( layerOpacityText );
2197  node.appendChild( layerOpacityElem );
2198 
2199  if ( mDiagramRenderer )
2200  {
2201  mDiagramRenderer->writeXml( mapLayerNode, doc, context );
2202  if ( mDiagramLayerSettings )
2203  mDiagramLayerSettings->writeXml( mapLayerNode, doc );
2204  }
2205  }
2206  return true;
2207 }
2208 
2209 bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
2210 {
2211  // get the Name element
2212  QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2213  if ( nameElem.isNull() )
2214  {
2215  errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2216  }
2217 
2218  if ( isSpatial() )
2219  {
2220  QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
2221  if ( !r )
2222  return false;
2223 
2224  setRenderer( r );
2225 
2226  // labeling
2227  readSldLabeling( node );
2228  }
2229  return true;
2230 }
2231 
2232 bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsStringMap &props ) const
2233 {
2234  Q_UNUSED( errorMessage );
2235 
2236  QgsStringMap localProps = QgsStringMap( props );
2237  if ( hasScaleBasedVisibility() )
2238  {
2240  }
2241 
2242  if ( isSpatial() )
2243  {
2244  // store the Name element
2245  QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
2246  nameNode.appendChild( doc.createTextNode( name() ) );
2247  node.appendChild( nameNode );
2248 
2249  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
2250  node.appendChild( userStyleElem );
2251 
2252  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
2253  nameElem.appendChild( doc.createTextNode( name() ) );
2254 
2255  userStyleElem.appendChild( nameElem );
2256 
2257  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
2258  userStyleElem.appendChild( featureTypeStyleElem );
2259 
2260  mRenderer->toSld( doc, featureTypeStyleElem, localProps );
2261  if ( labelsEnabled() )
2262  {
2263  mLabeling->toSld( featureTypeStyleElem, localProps );
2264  }
2265  }
2266  return true;
2267 }
2268 
2269 
2271 {
2272  if ( !mEditBuffer || !mDataProvider )
2273  {
2274  return false;
2275  }
2276 
2277  updateExtents();
2278 
2279  bool result = mEditBuffer->changeGeometry( fid, geom );
2280 
2281  if ( result )
2282  updateExtents();
2283  return result;
2284 }
2285 
2286 
2287 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2288 {
2289  switch ( fields().fieldOrigin( field ) )
2290  {
2291  case QgsFields::OriginJoin:
2292  return mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2293 
2295  case QgsFields::OriginEdit:
2297  {
2298  if ( !mEditBuffer || !mDataProvider )
2299  return false;
2300  else
2301  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2302  }
2303 
2305  return false;
2306  }
2307 
2308  return false;
2309 }
2310 
2312 {
2313  if ( !mEditBuffer || !mDataProvider )
2314  return false;
2315 
2316  return mEditBuffer->addAttribute( field );
2317 }
2318 
2320 {
2321  if ( attIndex < 0 || attIndex >= fields().count() )
2322  return;
2323 
2324  QString name = fields().at( attIndex ).name();
2325  mFields[ attIndex ].setAlias( QString() );
2326  if ( mAttributeAliasMap.contains( name ) )
2327  {
2328  mAttributeAliasMap.remove( name );
2329  updateFields();
2330  mEditFormConfig.setFields( mFields );
2331  emit layerModified();
2332  }
2333 }
2334 
2335 bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
2336 {
2337  if ( index < 0 || index >= fields().count() )
2338  return false;
2339 
2340  switch ( mFields.fieldOrigin( index ) )
2341  {
2343  {
2344  if ( mExpressionFieldBuffer )
2345  {
2346  int oi = mFields.fieldOriginIndex( index );
2347  mExpressionFieldBuffer->renameExpression( oi, newName );
2348  updateFields();
2349  return true;
2350  }
2351  else
2352  {
2353  return false;
2354  }
2355  }
2356 
2358  case QgsFields::OriginEdit:
2359 
2360  if ( !mEditBuffer || !mDataProvider )
2361  return false;
2362 
2363  return mEditBuffer->renameAttribute( index, newName );
2364 
2365  case QgsFields::OriginJoin:
2367  return false;
2368 
2369  }
2370 
2371  return false; // avoid warning
2372 }
2373 
2374 void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
2375 {
2376  if ( attIndex < 0 || attIndex >= fields().count() )
2377  return;
2378 
2379  QString name = fields().at( attIndex ).name();
2380 
2381  mAttributeAliasMap.insert( name, aliasString );
2382  mFields[ attIndex ].setAlias( aliasString );
2383  mEditFormConfig.setFields( mFields );
2384  emit layerModified(); // TODO[MD]: should have a different signal?
2385 }
2386 
2387 QString QgsVectorLayer::attributeAlias( int index ) const
2388 {
2389  if ( index < 0 || index >= fields().count() )
2390  return QString();
2391 
2392  return fields().at( index ).alias();
2393 }
2394 
2395 QString QgsVectorLayer::attributeDisplayName( int index ) const
2396 {
2397  if ( index >= 0 && index < mFields.count() )
2398  return mFields.at( index ).displayName();
2399  else
2400  return QString();
2401 }
2402 
2404 {
2405  QgsStringMap map;
2406  Q_FOREACH ( const QgsField &field, fields() )
2407  {
2408  if ( !field.alias().isEmpty() )
2409  map.insert( field.name(), field.alias() );
2410  }
2411  return map;
2412 }
2413 
2415 {
2416  if ( index < 0 || index >= fields().count() )
2417  return false;
2418 
2419  if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2420  {
2421  removeExpressionField( index );
2422  return true;
2423  }
2424 
2425  if ( !mEditBuffer || !mDataProvider )
2426  return false;
2427 
2428  return mEditBuffer->deleteAttribute( index );
2429 }
2430 
2431 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
2432 {
2433  bool deleted = false;
2434 
2435  // Remove multiple occurrences of same attribute
2436  attrs = attrs.toSet().toList();
2437 
2438  std::sort( attrs.begin(), attrs.end(), std::greater<int>() );
2439 
2440  Q_FOREACH ( int attr, attrs )
2441  {
2442  if ( deleteAttribute( attr ) )
2443  {
2444  deleted = true;
2445  }
2446  }
2447 
2448  return deleted;
2449 }
2450 
2452 {
2453  if ( !mEditBuffer )
2454  return false;
2455 
2456  if ( mJoinBuffer->containsJoins() )
2457  mJoinBuffer->deleteFeature( fid );
2458 
2459  bool res = mEditBuffer->deleteFeature( fid );
2460  if ( res )
2461  {
2462  mSelectedFeatureIds.remove( fid ); // remove it from selection
2463  updateExtents();
2464  }
2465 
2466  return res;
2467 }
2468 
2470 {
2471  if ( !mEditBuffer )
2472  {
2473  QgsDebugMsg( "Cannot delete features (mEditBuffer==NULL)" );
2474  return false;
2475  }
2476 
2477  if ( mJoinBuffer->containsJoins() )
2478  mJoinBuffer->deleteFeatures( fids );
2479 
2480  bool res = mEditBuffer->deleteFeatures( fids );
2481 
2482  if ( res )
2483  {
2484  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2485  updateExtents();
2486  }
2487 
2488  return res;
2489 }
2490 
2492 {
2493  QgsAttributeList pkAttributesList;
2494 
2495  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2496  for ( int i = 0; i < mFields.count(); ++i )
2497  {
2498  if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2499  providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
2500  pkAttributesList << i;
2501  }
2502 
2503  return pkAttributesList;
2504 }
2505 
2507 {
2508  return mDataProvider->featureCount() +
2509  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2510 }
2511 
2513 {
2514  mCommitErrors.clear();
2515 
2516  if ( !mDataProvider )
2517  {
2518  mCommitErrors << tr( "ERROR: no provider" );
2519  return false;
2520  }
2521 
2522  if ( !mEditBuffer )
2523  {
2524  mCommitErrors << tr( "ERROR: layer not editable" );
2525  return false;
2526  }
2527 
2528  emit beforeCommitChanges();
2529 
2530  bool success = mEditBuffer->commitChanges( mCommitErrors );
2531 
2532  if ( success )
2533  {
2534  delete mEditBuffer;
2535  mEditBuffer = nullptr;
2536  undoStack()->clear();
2537  emit editingStopped();
2538  }
2539  else
2540  {
2541  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QStringLiteral( "\n " ) ) ) );
2542  }
2543 
2544  updateFields();
2545  mDataProvider->updateExtents();
2546 
2547  mDataProvider->leaveUpdateMode();
2548 
2549  emit repaintRequested();
2550 
2551  return success;
2552 }
2553 
2554 QStringList QgsVectorLayer::commitErrors() const
2555 {
2556  return mCommitErrors;
2557 }
2558 
2559 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2560 {
2561  if ( !mEditBuffer )
2562  {
2563  return false;
2564  }
2565 
2566  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2567  !mEditBuffer->mAddedFeatures.isEmpty() ||
2568  !mEditBuffer->mChangedGeometries.isEmpty();
2569 
2570  emit beforeRollBack();
2571 
2572  mEditBuffer->rollBack();
2573 
2574  if ( isModified() )
2575  {
2576  // new undo stack roll back method
2577  // old method of calling every undo could cause many canvas refreshes
2578  undoStack()->setIndex( 0 );
2579  }
2580 
2581  updateFields();
2582 
2583  if ( deleteBuffer )
2584  {
2585  delete mEditBuffer;
2586  mEditBuffer = nullptr;
2587  undoStack()->clear();
2588  }
2589  emit editingStopped();
2590 
2591  if ( rollbackExtent )
2592  updateExtents();
2593 
2594  mDataProvider->leaveUpdateMode();
2595 
2596  emit repaintRequested();
2597  return true;
2598 }
2599 
2601 {
2602  return mSelectedFeatureIds.size();
2603 }
2604 
2606 {
2607  return mSelectedFeatureIds;
2608 }
2609 
2611 {
2612  QgsFeatureList features;
2613  QgsFeature f;
2614 
2615  if ( mSelectedFeatureIds.count() <= 8 )
2616  {
2617  // for small amount of selected features, fetch them directly
2618  // because request with FilterFids would go iterate over the whole layer
2619  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2620  {
2621  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2622  features << f;
2623  }
2624  }
2625  else
2626  {
2628 
2629  while ( it.nextFeature( f ) )
2630  {
2631  features.push_back( f );
2632  }
2633  }
2634 
2635  return features;
2636 }
2637 
2639 {
2640  if ( mSelectedFeatureIds.isEmpty() )
2641  return QgsFeatureIterator();
2642 
2645 
2646  if ( mSelectedFeatureIds.count() == 1 )
2647  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2648  else
2649  request.setFilterFids( mSelectedFeatureIds );
2650 
2651  return getFeatures( request );
2652 }
2653 
2655 {
2656  if ( !mEditBuffer || !mDataProvider )
2657  return false;
2658 
2659  bool res = mEditBuffer->addFeatures( features );
2660  updateExtents();
2661 
2662  if ( res && mJoinBuffer->containsJoins() )
2663  res = mJoinBuffer->addFeatures( features );
2664 
2665  return res;
2666 }
2667 
2669 {
2670  QgsDebugMsg( "----- Computing Coordinate System" );
2671 
2672  //
2673  // Get the layers project info and set up the QgsCoordinateTransform
2674  // for this layer
2675  //
2676 
2677  if ( isSpatial() )
2678  {
2679  // get CRS directly from provider
2680  setCrs( mDataProvider->crs() );
2681  }
2682  else
2683  {
2685  }
2686 }
2687 
2688 
2690 {
2691  QgsExpression exp( mDisplayExpression );
2692  if ( exp.isField() )
2693  {
2694  return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
2695  }
2696 
2697  return QString();
2698 }
2699 
2701 {
2702  if ( mDisplayExpression == displayExpression )
2703  return;
2704 
2705  mDisplayExpression = displayExpression;
2706  emit displayExpressionChanged();
2707 }
2708 
2709 QString QgsVectorLayer::displayExpression() const
2710 {
2711  if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
2712  {
2713  return mDisplayExpression;
2714  }
2715  else
2716  {
2717  QString idxName;
2718 
2719  Q_FOREACH ( const QgsField &field, mFields )
2720  {
2721  QString fldName = field.name();
2722 
2723  // Check the fields and keep the first one that matches.
2724  // We assume that the user has organized the data with the
2725  // more "interesting" field names first. As such, name should
2726  // be selected before oldname, othername, etc.
2727  if ( fldName.indexOf( QLatin1String( "name" ), 0, Qt::CaseInsensitive ) > -1 )
2728  {
2729  idxName = fldName;
2730  break;
2731  }
2732  if ( fldName.indexOf( QLatin1String( "descrip" ), 0, Qt::CaseInsensitive ) > -1 )
2733  {
2734  idxName = fldName;
2735  break;
2736  }
2737  if ( fldName.indexOf( QLatin1String( "id" ), 0, Qt::CaseInsensitive ) > -1 )
2738  {
2739  idxName = fldName;
2740  break;
2741  }
2742  }
2743 
2744  if ( !idxName.isNull() )
2745  {
2746  return QgsExpression::quotedColumnRef( idxName );
2747  }
2748  else
2749  {
2750  return QgsExpression::quotedColumnRef( mFields.at( 0 ).name() );
2751  }
2752  }
2753 }
2754 
2756 {
2757  return ( mEditBuffer && mDataProvider );
2758 }
2759 
2761 {
2764 }
2765 
2766 bool QgsVectorLayer::isReadOnly() const
2767 {
2768  return mReadOnly;
2769 }
2770 
2771 bool QgsVectorLayer::setReadOnly( bool readonly )
2772 {
2773  // exit if the layer is in editing mode
2774  if ( readonly && mEditBuffer )
2775  return false;
2776 
2777  mReadOnly = readonly;
2778  emit readOnlyChanged();
2779  return true;
2780 }
2781 
2783 {
2784  emit beforeModifiedCheck();
2785  return mEditBuffer && mEditBuffer->isModified();
2786 }
2787 
2789 {
2790  if ( !isSpatial() )
2791  return;
2792 
2793  if ( r != mRenderer )
2794  {
2795  delete mRenderer;
2796  mRenderer = r;
2797  mSymbolFeatureCounted = false;
2798  mSymbolFeatureCountMap.clear();
2799 
2800  emit rendererChanged();
2801  emit styleChanged();
2802  }
2803 }
2804 
2805 void QgsVectorLayer::beginEditCommand( const QString &text )
2806 {
2807  if ( !mDataProvider )
2808  {
2809  return;
2810  }
2811  if ( mDataProvider->transaction() )
2812  {
2813  QString ignoredError;
2814  mDataProvider->transaction()->createSavepoint( ignoredError );
2815  }
2816  undoStack()->beginMacro( text );
2817  mEditCommandActive = true;
2818  emit editCommandStarted( text );
2819 }
2820 
2822 {
2823  if ( !mDataProvider )
2824  {
2825  return;
2826  }
2827  undoStack()->endMacro();
2828  mEditCommandActive = false;
2829  if ( !mDeletedFids.isEmpty() )
2830  {
2831  emit featuresDeleted( mDeletedFids );
2832  mDeletedFids.clear();
2833  }
2834  emit editCommandEnded();
2835 }
2836 
2838 {
2839  if ( !mDataProvider )
2840  {
2841  return;
2842  }
2843  undoStack()->endMacro();
2844  undoStack()->undo();
2845  mEditCommandActive = false;
2846  mDeletedFids.clear();
2847  emit editCommandDestroyed();
2848 }
2849 
2851 {
2852  return mJoinBuffer->addJoin( joinInfo );
2853 }
2854 
2855 
2856 bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
2857 {
2858  return mJoinBuffer->removeJoin( joinLayerId );
2859 }
2860 
2861 const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
2862 {
2863  return mJoinBuffer->vectorJoins();
2864 }
2865 
2866 int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
2867 {
2868  emit beforeAddingExpressionField( fld.name() );
2869  mExpressionFieldBuffer->addExpression( exp, fld );
2870  updateFields();
2871  int idx = mFields.indexFromName( fld.name() );
2872  emit attributeAdded( idx );
2873  return idx;
2874 }
2875 
2877 {
2878  emit beforeRemovingExpressionField( index );
2879  int oi = mFields.fieldOriginIndex( index );
2880  mExpressionFieldBuffer->removeExpression( oi );
2881  updateFields();
2882  emit attributeDeleted( index );
2883 }
2884 
2885 QString QgsVectorLayer::expressionField( int index ) const
2886 {
2887  int oi = mFields.fieldOriginIndex( index );
2888  if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
2889  return QString();
2890 
2891  return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
2892 }
2893 
2894 void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
2895 {
2896  int oi = mFields.fieldOriginIndex( index );
2897  mExpressionFieldBuffer->updateExpression( oi, exp );
2898 }
2899 
2901 {
2902  if ( !mDataProvider )
2903  return;
2904 
2905  QgsFields oldFields = mFields;
2906 
2907  mFields = mDataProvider->fields();
2908 
2909  // added / removed fields
2910  if ( mEditBuffer )
2911  mEditBuffer->updateFields( mFields );
2912 
2913  // joined fields
2914  if ( mJoinBuffer->containsJoins() )
2915  mJoinBuffer->updateFields( mFields );
2916 
2917  if ( mExpressionFieldBuffer )
2918  mExpressionFieldBuffer->updateFields( mFields );
2919 
2920  // set aliases and default values
2921  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
2922  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
2923  {
2924  int index = mFields.lookupField( aliasIt.key() );
2925  if ( index < 0 )
2926  continue;
2927 
2928  mFields[ index ].setAlias( aliasIt.value() );
2929  }
2930  QMap< QString, QString >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
2931  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
2932  {
2933  int index = mFields.lookupField( defaultIt.key() );
2934  if ( index < 0 )
2935  continue;
2936 
2937  mFields[ index ].setDefaultValueExpression( defaultIt.value() );
2938  }
2939 
2940  QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
2941  for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
2942  {
2943  int index = mFields.lookupField( constraintIt.key() );
2944  if ( index < 0 )
2945  continue;
2946 
2947  QgsFieldConstraints constraints = mFields.at( index ).constraints();
2948 
2949  // always keep provider constraints intact
2950  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
2952  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
2954  if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
2956  mFields[ index ].setConstraints( constraints );
2957  }
2958 
2959  QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
2960  for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
2961  {
2962  int index = mFields.lookupField( constraintExpIt.key() );
2963  if ( index < 0 )
2964  continue;
2965 
2966  QgsFieldConstraints constraints = mFields.at( index ).constraints();
2967 
2968  // always keep provider constraints intact
2970  continue;
2971 
2972  constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
2973  mFields[ index ].setConstraints( constraints );
2974  }
2975 
2976  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
2977  for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
2978  {
2979  int index = mFields.lookupField( constraintStrengthIt.key().first );
2980  if ( index < 0 )
2981  continue;
2982 
2983  QgsFieldConstraints constraints = mFields.at( index ).constraints();
2984 
2985  // always keep provider constraints intact
2987  continue;
2988 
2989  constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
2990  mFields[ index ].setConstraints( constraints );
2991  }
2992 
2993  auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
2994  for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
2995  {
2996  int index = mFields.indexOf( fieldWidgetIterator.key() );
2997  if ( index < 0 )
2998  continue;
2999 
3000  mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
3001  }
3002 
3003  if ( oldFields != mFields )
3004  {
3005  emit updatedFields();
3006  mEditFormConfig.setFields( mFields );
3007  }
3008 }
3009 
3010 
3011 QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
3012 {
3013  if ( index < 0 || index >= mFields.count() )
3014  return QVariant();
3015 
3016  QString expression = mFields.at( index ).defaultValueExpression();
3017  if ( expression.isEmpty() )
3018  return mDataProvider->defaultValue( index );
3019 
3020  QgsExpressionContext *evalContext = context;
3021  std::unique_ptr< QgsExpressionContext > tempContext;
3022  if ( !evalContext )
3023  {
3024  // no context passed, so we create a default one
3026  evalContext = tempContext.get();
3027  }
3028 
3029  if ( feature.isValid() )
3030  {
3032  featScope->setFeature( feature );
3033  featScope->setFields( feature.fields() );
3034  evalContext->appendScope( featScope );
3035  }
3036 
3037  QVariant val;
3038  QgsExpression exp( expression );
3039  exp.prepare( evalContext );
3040  if ( exp.hasEvalError() )
3041  {
3042  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
3043  }
3044  else
3045  {
3046  val = exp.evaluate( evalContext );
3047  }
3048 
3049  if ( feature.isValid() )
3050  {
3051  delete evalContext->popScope();
3052  }
3053 
3054  return val;
3055 }
3056 
3057 void QgsVectorLayer::setDefaultValueExpression( int index, const QString &expression )
3058 {
3059  if ( index < 0 || index >= mFields.count() )
3060  return;
3061 
3062  if ( expression.isEmpty() )
3063  {
3064  mDefaultExpressionMap.remove( mFields.at( index ).name() );
3065  }
3066  else
3067  {
3068  mDefaultExpressionMap.insert( mFields.at( index ).name(), expression );
3069  }
3070  updateFields();
3071 }
3072 
3073 QString QgsVectorLayer::defaultValueExpression( int index ) const
3074 {
3075  if ( index < 0 || index >= mFields.count() )
3076  return QString();
3077  else
3078  return mFields.at( index ).defaultValueExpression();
3079 }
3080 
3081 QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
3082 {
3083  QSet<QVariant> uniqueValues;
3084  if ( !mDataProvider )
3085  {
3086  return uniqueValues;
3087  }
3088 
3089  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3090  switch ( origin )
3091  {
3093  return uniqueValues;
3094 
3095  case QgsFields::OriginProvider: //a provider field
3096  {
3097  uniqueValues = mDataProvider->uniqueValues( index, limit );
3098 
3099  if ( mEditBuffer )
3100  {
3101  QSet<QString> vals;
3102  Q_FOREACH ( const QVariant &v, uniqueValues )
3103  {
3104  vals << v.toString();
3105  }
3106 
3107  QgsFeatureMap added = mEditBuffer->addedFeatures();
3108  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3109  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3110  {
3111  addedIt.next();
3112  QVariant v = addedIt.value().attribute( index );
3113  if ( v.isValid() )
3114  {
3115  QString vs = v.toString();
3116  if ( !vals.contains( vs ) )
3117  {
3118  vals << vs;
3119  uniqueValues << v;
3120  }
3121  }
3122  }
3123 
3124  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3125  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3126  {
3127  it.next();
3128  QVariant v = it.value().value( index );
3129  if ( v.isValid() )
3130  {
3131  QString vs = v.toString();
3132  if ( !vals.contains( vs ) )
3133  {
3134  vals << vs;
3135  uniqueValues << v;
3136  }
3137  }
3138  }
3139  }
3140 
3141  return uniqueValues;
3142  }
3143 
3144  case QgsFields::OriginEdit:
3145  // the layer is editable, but in certain cases it can still be avoided going through all features
3146  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3147  mEditBuffer->mAddedFeatures.isEmpty() &&
3148  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3149  mEditBuffer->mChangedAttributeValues.isEmpty() )
3150  {
3151  uniqueValues = mDataProvider->uniqueValues( index, limit );
3152  return uniqueValues;
3153  }
3154  FALLTHROUGH;
3155  //we need to go through each feature
3156  case QgsFields::OriginJoin:
3158  {
3159  QgsAttributeList attList;
3160  attList << index;
3161 
3163  .setFlags( QgsFeatureRequest::NoGeometry )
3164  .setSubsetOfAttributes( attList ) );
3165 
3166  QgsFeature f;
3167  QVariant currentValue;
3168  QHash<QString, QVariant> val;
3169  while ( fit.nextFeature( f ) )
3170  {
3171  currentValue = f.attribute( index );
3172  val.insert( currentValue.toString(), currentValue );
3173  if ( limit >= 0 && val.size() >= limit )
3174  {
3175  break;
3176  }
3177  }
3178 
3179  return val.values().toSet();
3180  }
3181  }
3182 
3183  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3184  return uniqueValues;
3185 }
3186 
3187 QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
3188 {
3189  QStringList results;
3190  if ( !mDataProvider )
3191  {
3192  return results;
3193  }
3194 
3195  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3196  switch ( origin )
3197  {
3199  return results;
3200 
3201  case QgsFields::OriginProvider: //a provider field
3202  {
3203  results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3204 
3205  if ( mEditBuffer )
3206  {
3207  QgsFeatureMap added = mEditBuffer->addedFeatures();
3208  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3209  while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3210  {
3211  addedIt.next();
3212  QVariant v = addedIt.value().attribute( index );
3213  if ( v.isValid() )
3214  {
3215  QString vs = v.toString();
3216  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3217  {
3218  results << vs;
3219  }
3220  }
3221  }
3222 
3223  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3224  while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
3225  {
3226  it.next();
3227  QVariant v = it.value().value( index );
3228  if ( v.isValid() )
3229  {
3230  QString vs = v.toString();
3231  if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
3232  {
3233  results << vs;
3234  }
3235  }
3236  }
3237  }
3238 
3239  return results;
3240  }
3241 
3242  case QgsFields::OriginEdit:
3243  // the layer is editable, but in certain cases it can still be avoided going through all features
3244  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3245  mEditBuffer->mAddedFeatures.isEmpty() &&
3246  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3247  mEditBuffer->mChangedAttributeValues.isEmpty() )
3248  {
3249  return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
3250  }
3251  FALLTHROUGH;
3252  //we need to go through each feature
3253  case QgsFields::OriginJoin:
3255  {
3256  QgsAttributeList attList;
3257  attList << index;
3258 
3259  QgsFeatureRequest request;
3260  request.setSubsetOfAttributes( attList );
3262  QString fieldName = mFields.at( index ).name();
3263  request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
3264  QgsFeatureIterator fit = getFeatures( request );
3265 
3266  QgsFeature f;
3267  QString currentValue;
3268  while ( fit.nextFeature( f ) )
3269  {
3270  currentValue = f.attribute( index ).toString();
3271  if ( !results.contains( currentValue ) )
3272  results << currentValue;
3273 
3274  if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
3275  {
3276  break;
3277  }
3278  }
3279 
3280  return results;
3281  }
3282  }
3283 
3284  Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
3285  return results;
3286 }
3287 
3288 QVariant QgsVectorLayer::minimumValue( int index ) const
3289 {
3290  if ( !mDataProvider )
3291  {
3292  return QVariant();
3293  }
3294 
3295  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3296 
3297  switch ( origin )
3298  {
3300  return QVariant();
3301 
3302  case QgsFields::OriginProvider: //a provider field
3303  {
3304  QVariant min = mDataProvider->minimumValue( index );
3305  if ( mEditBuffer )
3306  {
3307  QgsFeatureMap added = mEditBuffer->addedFeatures();
3308  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3309  while ( addedIt.hasNext() )
3310  {
3311  addedIt.next();
3312  QVariant v = addedIt.value().attribute( index );
3313  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3314  {
3315  min = v;
3316  }
3317  }
3318 
3319  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3320  while ( it.hasNext() )
3321  {
3322  it.next();
3323  QVariant v = it.value().value( index );
3324  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3325  {
3326  min = v;
3327  }
3328  }
3329  }
3330  return min;
3331  }
3332 
3333  case QgsFields::OriginEdit:
3334  {
3335  // the layer is editable, but in certain cases it can still be avoided going through all features
3336  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3337  mEditBuffer->mAddedFeatures.isEmpty() && !
3338  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3339  mEditBuffer->mChangedAttributeValues.isEmpty() )
3340  {
3341  return mDataProvider->minimumValue( index );
3342  }
3343  }
3344  FALLTHROUGH;
3345  // no choice but to go through all features
3347  case QgsFields::OriginJoin:
3348  {
3349  // we need to go through each feature
3350  QgsAttributeList attList;
3351  attList << index;
3352 
3354  .setFlags( QgsFeatureRequest::NoGeometry )
3355  .setSubsetOfAttributes( attList ) );
3356 
3357  QgsFeature f;
3358  double minimumValue = std::numeric_limits<double>::max();
3359  double currentValue = 0;
3360  while ( fit.nextFeature( f ) )
3361  {
3362  currentValue = f.attribute( index ).toDouble();
3363  if ( currentValue < minimumValue )
3364  {
3365  minimumValue = currentValue;
3366  }
3367  }
3368  return QVariant( minimumValue );
3369  }
3370  }
3371 
3372  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3373  return QVariant();
3374 }
3375 
3376 QVariant QgsVectorLayer::maximumValue( int index ) const
3377 {
3378  if ( !mDataProvider )
3379  {
3380  return QVariant();
3381  }
3382 
3383  QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
3384  switch ( origin )
3385  {
3387  return QVariant();
3388 
3389  case QgsFields::OriginProvider: //a provider field
3390  {
3391  QVariant min = mDataProvider->maximumValue( index );
3392  if ( mEditBuffer )
3393  {
3394  QgsFeatureMap added = mEditBuffer->addedFeatures();
3395  QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
3396  while ( addedIt.hasNext() )
3397  {
3398  addedIt.next();
3399  QVariant v = addedIt.value().attribute( index );
3400  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3401  {
3402  min = v;
3403  }
3404  }
3405 
3406  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3407  while ( it.hasNext() )
3408  {
3409  it.next();
3410  QVariant v = it.value().value( index );
3411  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3412  {
3413  min = v;
3414  }
3415  }
3416  }
3417  return min;
3418  }
3419 
3420  case QgsFields::OriginEdit:
3421  // the layer is editable, but in certain cases it can still be avoided going through all features
3422  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3423  mEditBuffer->mAddedFeatures.isEmpty() &&
3424  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3425  mEditBuffer->mChangedAttributeValues.isEmpty() )
3426  {
3427  return mDataProvider->maximumValue( index );
3428  }
3429 
3430  FALLTHROUGH;
3431  //no choice but to go through each feature
3432  case QgsFields::OriginJoin:
3434  {
3435  QgsAttributeList attList;
3436  attList << index;
3437 
3439  .setFlags( QgsFeatureRequest::NoGeometry )
3440  .setSubsetOfAttributes( attList ) );
3441 
3442  QgsFeature f;
3443  double maximumValue = -std::numeric_limits<double>::max();
3444  double currentValue = 0;
3445  while ( fit.nextFeature( f ) )
3446  {
3447  currentValue = f.attribute( index ).toDouble();
3448  if ( currentValue > maximumValue )
3449  {
3450  maximumValue = currentValue;
3451  }
3452  }
3453  return QVariant( maximumValue );
3454  }
3455  }
3456 
3457  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3458  return QVariant();
3459 }
3460 
3461 QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
3462  const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool *ok ) const
3463 {
3464  if ( ok )
3465  *ok = false;
3466 
3467  if ( !mDataProvider )
3468  {
3469  return QVariant();
3470  }
3471 
3472  // test if we are calculating based on a field
3473  int attrIndex = mFields.lookupField( fieldOrExpression );
3474  if ( attrIndex >= 0 )
3475  {
3476  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
3477  // to the provider itself
3478  QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
3479  if ( origin == QgsFields::OriginProvider )
3480  {
3481  bool providerOk = false;
3482  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk );
3483  if ( providerOk )
3484  {
3485  // provider handled calculation
3486  if ( ok )
3487  *ok = true;
3488  return val;
3489  }
3490  }
3491  }
3492 
3493  // fallback to using aggregate calculator to determine aggregate
3494  QgsAggregateCalculator c( this );
3495  c.setParameters( parameters );
3496  return c.calculate( aggregate, fieldOrExpression, context, ok );
3497 }
3498 
3499 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback ) const
3500 {
3501  QList<QVariant> values;
3502 
3503  std::unique_ptr<QgsExpression> expression;
3504  QgsExpressionContext context;
3505 
3506  int attrNum = mFields.lookupField( fieldOrExpression );
3507 
3508  if ( attrNum == -1 )
3509  {
3510  // try to use expression
3511  expression.reset( new QgsExpression( fieldOrExpression ) );
3513 
3514  if ( expression->hasParserError() || !expression->prepare( &context ) )
3515  {
3516  ok = false;
3517  return values;
3518  }
3519  }
3520 
3521  QgsFeature f;
3522  QSet<QString> lst;
3523  if ( !expression )
3524  lst.insert( fieldOrExpression );
3525  else
3526  lst = expression->referencedColumns();
3527 
3529  .setFlags( ( expression && expression->needsGeometry() ) ?
3532  .setSubsetOfAttributes( lst, fields() );
3533 
3534  QgsFeatureIterator fit;
3535  if ( !selectedOnly )
3536  {
3537  fit = getFeatures( request );
3538  }
3539  else
3540  {
3541  fit = getSelectedFeatures( request );
3542  }
3543 
3544  // create list of non-null attribute values
3545  while ( fit.nextFeature( f ) )
3546  {
3547  if ( expression )
3548  {
3549  context.setFeature( f );
3550  QVariant v = expression->evaluate( &context );
3551  values << v;
3552  }
3553  else
3554  {
3555  values << f.attribute( attrNum );
3556  }
3557  if ( feedback && feedback->isCanceled() )
3558  {
3559  ok = false;
3560  return values;
3561  }
3562  }
3563  ok = true;
3564  return values;
3565 }
3566 
3567 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool &ok, bool selectedOnly, int *nullCount, QgsFeedback *feedback ) const
3568 {
3569  QList<double> values;
3570 
3571  if ( nullCount )
3572  *nullCount = 0;
3573 
3574  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3575  if ( !ok )
3576  return values;
3577 
3578  bool convertOk;
3579  Q_FOREACH ( const QVariant &value, variantValues )
3580  {
3581  double val = value.toDouble( &convertOk );
3582  if ( convertOk )
3583  values << val;
3584  else if ( value.isNull() )
3585  {
3586  if ( nullCount )
3587  *nullCount += 1;
3588  }
3589  if ( feedback && feedback->isCanceled() )
3590  {
3591  ok = false;
3592  return values;
3593  }
3594  }
3595  ok = true;
3596  return values;
3597 }
3598 
3600 {
3601  mFeatureBlendMode = featureBlendMode;
3602  emit featureBlendModeChanged( featureBlendMode );
3603  emit styleChanged();
3604 }
3605 
3606 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3607 {
3608  return mFeatureBlendMode;
3609 }
3610 
3612 {
3613  mLayerOpacity = opacity;
3614  emit opacityChanged( opacity );
3615  emit styleChanged();
3616 }
3617 
3618 double QgsVectorLayer::opacity() const
3619 {
3620  return mLayerOpacity;
3621 }
3622 
3623 
3624 
3625 void QgsVectorLayer::readSldLabeling( const QDomNode &node )
3626 {
3627  setLabeling( nullptr ); // start with no labeling
3628 
3629  QDomElement element = node.toElement();
3630  if ( element.isNull() )
3631  return;
3632 
3633  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
3634  if ( userStyleElem.isNull() )
3635  {
3636  QgsDebugMsg( "Info: UserStyle element not found." );
3637  return;
3638  }
3639 
3640  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
3641  if ( featureTypeStyleElem.isNull() )
3642  {
3643  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3644  return;
3645  }
3646 
3647  // use last rule
3648  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( QStringLiteral( "Rule" ) );
3649  if ( ruleElem.isNull() )
3650  {
3651  QgsDebugMsg( "Info: Rule element not found." );
3652  return;
3653  }
3654 
3655  // use last text symbolizer
3656  QDomElement textSymbolizerElem = ruleElem.lastChildElement( QStringLiteral( "TextSymbolizer" ) );
3657  if ( textSymbolizerElem.isNull() )
3658  {
3659  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3660  return;
3661  }
3662 
3663  QgsPalLayerSettings settings;
3664 
3665  // Label
3666  QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
3667  if ( !labelElem.isNull() )
3668  {
3669  QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
3670  if ( !propertyNameElem.isNull() )
3671  {
3672  // set labeling defaults
3673 
3674  // label attribute
3675  QString labelAttribute = propertyNameElem.text();
3676  settings.fieldName = labelAttribute;
3677  settings.isExpression = false;
3678 
3679  int fieldIndex = mFields.lookupField( labelAttribute );
3680  if ( fieldIndex == -1 )
3681  {
3682  // label attribute is not in columns, check if it is an expression
3683  QgsExpression exp( labelAttribute );
3684  if ( !exp.hasEvalError() )
3685  {
3686  settings.isExpression = true;
3687  }
3688  else
3689  {
3690  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3691  }
3692  }
3693  }
3694  else
3695  {
3696  QgsDebugMsg( "Info: PropertyName element not found." );
3697  return;
3698  }
3699  }
3700  else
3701  {
3702  QgsDebugMsg( "Info: Label element not found." );
3703  return;
3704  }
3705 
3706  QString fontFamily = QStringLiteral( "Sans-Serif" );
3707  int fontPointSize = 10;
3708  int fontWeight = -1;
3709  bool fontItalic = false;
3710  bool fontUnderline = false;
3711 
3712  // Font
3713  QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
3714  if ( !fontElem.isNull() )
3715  {
3716  QString cssName;
3717  QString elemText;
3718  QDomElement cssElem = fontElem.firstChildElement( QStringLiteral( "CssParameter" ) );
3719  while ( !cssElem.isNull() )
3720  {
3721  cssName = cssElem.attribute( QStringLiteral( "name" ), QStringLiteral( "not_found" ) );
3722  if ( cssName != QLatin1String( "not_found" ) )
3723  {
3724  elemText = cssElem.text();
3725  if ( cssName == QLatin1String( "font-family" ) )
3726  {
3727  fontFamily = elemText;
3728  }
3729  else if ( cssName == QLatin1String( "font-style" ) )
3730  {
3731  fontItalic = ( elemText == QLatin1String( "italic" ) ) || ( elemText == QLatin1String( "Italic" ) );
3732  }
3733  else if ( cssName == QLatin1String( "font-size" ) )
3734  {
3735  bool ok;
3736  int fontSize = elemText.toInt( &ok );
3737  if ( ok )
3738  {
3739  fontPointSize = fontSize;
3740  }
3741  }
3742  else if ( cssName == QLatin1String( "font-weight" ) )
3743  {
3744  if ( ( elemText == QLatin1String( "bold" ) ) || ( elemText == QLatin1String( "Bold" ) ) )
3745  fontWeight = QFont::Bold;
3746  }
3747  else if ( cssName == QLatin1String( "font-underline" ) )
3748  {
3749  fontUnderline = ( elemText == QLatin1String( "underline" ) ) || ( elemText == QLatin1String( "Underline" ) );
3750  }
3751  }
3752 
3753  cssElem = cssElem.nextSiblingElement( QStringLiteral( "CssParameter" ) );
3754  }
3755  }
3756 
3757  QgsTextFormat format;
3758  QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
3759  font.setUnderline( fontUnderline );
3760  format.setFont( font );
3761  format.setSize( fontPointSize );
3762 
3763  // Fill
3764  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) ) );
3765  if ( textColor.isValid() )
3766  {
3767  format.setColor( textColor );
3768  }
3769 
3770  QgsTextBufferSettings bufferSettings;
3771 
3772  // Halo
3773  QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
3774  if ( !haloElem.isNull() )
3775  {
3776  bufferSettings.setEnabled( true );
3777  bufferSettings.setSize( 1 );
3778 
3779  QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
3780  if ( !radiusElem.isNull() )
3781  {
3782  bool ok;
3783  double bufferSize = radiusElem.text().toDouble( &ok );
3784  if ( ok )
3785  {
3786  bufferSettings.setSize( bufferSize );
3787  }
3788  }
3789 
3790  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( QStringLiteral( "Fill" ) ) );
3791  if ( bufferColor.isValid() )
3792  {
3793  bufferSettings.setColor( bufferColor );
3794  }
3795  }
3796 
3797  // LabelPlacement
3798  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
3799  if ( !labelPlacementElem.isNull() )
3800  {
3801  // PointPlacement
3802  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
3803  if ( !pointPlacementElem.isNull() )
3804  {
3806 
3807  QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
3808  if ( !displacementElem.isNull() )
3809  {
3810  QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
3811  if ( !displacementXElem.isNull() )
3812  {
3813  bool ok;
3814  double xOffset = displacementXElem.text().toDouble( &ok );
3815  if ( ok )
3816  {
3817  settings.xOffset = xOffset;
3818  }
3819  }
3820  QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
3821  if ( !displacementYElem.isNull() )
3822  {
3823  bool ok;
3824  double yOffset = displacementYElem.text().toDouble( &ok );
3825  if ( ok )
3826  {
3827  settings.yOffset = yOffset;
3828  }
3829  }
3830  }
3831 
3832  QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
3833  if ( !rotationElem.isNull() )
3834  {
3835  bool ok;
3836  double rotation = rotationElem.text().toDouble( &ok );
3837  if ( ok )
3838  {
3839  settings.angleOffset = 360 - rotation;
3840  }
3841  }
3842  }
3843  }
3844 
3845  format.setBuffer( bufferSettings );
3846  settings.setFormat( format );
3847  setLabeling( new QgsVectorLayerSimpleLabeling( settings ) );
3848 }
3849 
3851 {
3852  return mEditFormConfig;
3853 }
3854 
3856 {
3857  if ( mEditFormConfig == editFormConfig )
3858  return;
3859 
3860  mEditFormConfig = editFormConfig;
3861  mEditFormConfig.onRelationsLoaded();
3862  emit editFormConfigChanged();
3863 }
3864 
3865 QString QgsVectorLayer::mapTipTemplate() const
3866 {
3867  return mMapTipTemplate;
3868 }
3869 
3870 void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
3871 {
3872  if ( mMapTipTemplate == mapTip )
3873  return;
3874 
3875  mMapTipTemplate = mapTip;
3876  emit mapTipTemplateChanged();
3877 }
3878 
3880 {
3881  QgsAttributeTableConfig config = mAttributeTableConfig;
3882 
3883  if ( config.isEmpty() )
3884  config.update( fields() );
3885 
3886  return config;
3887 }
3888 
3890 {
3891  if ( mAttributeTableConfig != attributeTableConfig )
3892  {
3893  mAttributeTableConfig = attributeTableConfig;
3894  emit configChanged();
3895  }
3896 }
3897 
3899 {
3901 }
3902 
3904 {
3905  if ( !mDiagramLayerSettings )
3906  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3907  *mDiagramLayerSettings = s;
3908 }
3909 
3911 {
3912  QgsLayerMetadataFormatter htmlFormatter( metadata() );
3913  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
3914 
3915  // identification section
3916  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
3917  myMetadata += htmlFormatter.identificationSectionHtml( );
3918  myMetadata += QLatin1String( "<br><br>\n" );
3919 
3920  // Begin Provider section
3921  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
3922  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
3923 
3924  // original name
3925  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Original" ) + QStringLiteral( "</td><td>" ) + originalName() + QStringLiteral( "</td></tr>\n" );
3926 
3927  // name
3928  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
3929 
3930  // data source
3931  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>" ) + publicSource() + QStringLiteral( "</td></tr>\n" );
3932 
3933  // storage type
3934  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
3935 
3936  // comment
3937  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
3938 
3939  // encoding
3940  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + dataProvider()->encoding() + QStringLiteral( "</td></tr>\n" );
3941 
3942  // geom type
3944  if ( type < 0 || type > QgsWkbTypes::NullGeometry )
3945  {
3946  QgsDebugMsg( "Invalid vector type" );
3947  }
3948  else
3949  {
3950  QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
3952  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
3953  }
3954 
3955  // EPSG
3956  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" ) + crs().authid() + QStringLiteral( " - " );
3957  myMetadata += crs().description() + QStringLiteral( " - " );
3958  if ( crs().isGeographic() )
3959  myMetadata += tr( "Geographic" );
3960  else
3961  myMetadata += tr( "Projected" );
3962  myMetadata += QLatin1String( "</td></tr>\n" );
3963 
3964  // Extent
3965  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
3966 
3967  // unit
3968  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
3969 
3970  // feature count
3971  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Feature count" ) + QStringLiteral( "</td><td>" ) + QString::number( featureCount() ) + QStringLiteral( "</td></tr>\n" );
3972 
3973  // End Provider section
3974  myMetadata += QLatin1String( "</table>\n<br><br>" );
3975 
3976  // extent section
3977  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
3978  myMetadata += htmlFormatter.extentSectionHtml( );
3979  myMetadata += QLatin1String( "<br><br>\n" );
3980 
3981  // Start the Access section
3982  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
3983  myMetadata += htmlFormatter.accessSectionHtml( );
3984  myMetadata += QLatin1String( "<br><br>\n" );
3985 
3986  // Fields section
3987  myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
3988 
3989  // primary key
3990  QgsAttributeList pkAttrList = pkAttributeList();
3991  if ( !pkAttrList.isEmpty() )
3992  {
3993  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
3994  Q_FOREACH ( int idx, pkAttrList )
3995  {
3996  myMetadata += fields().at( idx ).name() + ' ';
3997  }
3998  myMetadata += QLatin1String( "</td></tr>\n" );
3999  }
4000 
4001  const QgsFields &myFields = pendingFields();
4002 
4003  // count fields
4004  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
4005 
4006  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
4007  myMetadata += "<tr><th>" + tr( "Field" ) + "</th><th>" + tr( "Type" ) + "</th><th>" + tr( "Length" ) + "</th><th>" + tr( "Precision" ) + "</th><th>" + tr( "Comment" ) + "</th></tr>\n";
4008 
4009  for ( int i = 0; i < myFields.size(); ++i )
4010  {
4011  QgsField myField = myFields.at( i );
4012  QString rowClass = QLatin1String( "" );
4013  if ( i % 2 )
4014  rowClass = QStringLiteral( "class=\"odd-row\"" );
4015  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";
4016  }
4017 
4018  //close field list
4019  myMetadata += QLatin1String( "</table>\n<br><br>" );
4020 
4021  // Start the contacts section
4022  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
4023  myMetadata += htmlFormatter.contactsSectionHtml( );
4024  myMetadata += QLatin1String( "<br><br>\n" );
4025 
4026  // Start the links section
4027  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
4028  myMetadata += htmlFormatter.linksSectionHtml( );
4029  myMetadata += QLatin1String( "<br><br>\n" );
4030 
4031  // Start the history section
4032  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
4033  myMetadata += htmlFormatter.historySectionHtml( );
4034  myMetadata += QLatin1String( "<br><br>\n" );
4035 
4036  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
4037  return myMetadata;
4038 }
4039 
4040 void QgsVectorLayer::invalidateSymbolCountedFlag()
4041 {
4042  mSymbolFeatureCounted = false;
4043 }
4044 
4045 void QgsVectorLayer::onFeatureCounterCompleted()
4046 {
4047  onSymbolsCounted();
4048  mFeatureCounter = nullptr;
4049 }
4050 
4051 void QgsVectorLayer::onFeatureCounterTerminated()
4052 {
4053  mFeatureCounter = nullptr;
4054 }
4055 
4056 void QgsVectorLayer::onJoinedFieldsChanged()
4057 {
4058  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4059  updateFields();
4060 }
4061 
4062 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4063 {
4064  if ( mEditCommandActive )
4065  mDeletedFids << fid;
4066  else
4067  emit featuresDeleted( QgsFeatureIds() << fid );
4068 
4069  emit featureDeleted( fid );
4070 }
4071 
4072 void QgsVectorLayer::onRelationsLoaded()
4073 {
4074  mEditFormConfig.onRelationsLoaded();
4075 }
4076 
4077 void QgsVectorLayer::onSymbolsCounted()
4078 {
4079  if ( mFeatureCounter )
4080  {
4081  mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
4082  mSymbolFeatureCounted = true;
4084  }
4085 }
4086 
4087 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
4088 {
4089  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4090 }
4091 
4092 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
4093 {
4094  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4095  if ( !myLib )
4096  {
4097  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4098  return -1;
4099  }
4100  listStyles_t *listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
4101 
4102  if ( !listStylesExternalMethod )
4103  {
4104  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "listStyles" ) );
4105  return -1;
4106  }
4107 
4108  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
4109 }
4110 
4111 QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
4112 {
4113  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4114  if ( !myLib )
4115  {
4116  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4117  return QString();
4118  }
4119  getStyleById_t *getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
4120 
4121  if ( !getStyleByIdMethod )
4122  {
4123  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "getStyleById" ) );
4124  return QString();
4125  }
4126 
4127  return getStyleByIdMethod( mDataSource, styleId, msgError );
4128 }
4129 
4130 bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
4131 {
4132  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4133  if ( !myLib )
4134  {
4135  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4136  return false;
4137  }
4138  deleteStyleById_t *deleteStyleByIdMethod = reinterpret_cast< deleteStyleById_t * >( cast_to_fptr( myLib->resolve( "deleteStyleById" ) ) );
4139  if ( !deleteStyleByIdMethod )
4140  {
4141  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "deleteStyleById" ) );
4142  return false;
4143  }
4144  return deleteStyleByIdMethod( mDataSource, styleId, msgError );
4145 }
4146 
4147 
4148 void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
4149  bool useAsDefault, const QString &uiFileContent, QString &msgError )
4150 {
4151 
4152  QString sldStyle, qmlStyle;
4153  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4154  if ( !myLib )
4155  {
4156  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4157  return;
4158  }
4159  saveStyle_t *saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4160 
4161  if ( !saveStyleExternalMethod )
4162  {
4163  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "saveStyle" ) );
4164  return;
4165  }
4166 
4167  QDomDocument qmlDocument, sldDocument;
4168  this->exportNamedStyle( qmlDocument, msgError );
4169  if ( !msgError.isNull() )
4170  {
4171  return;
4172  }
4173  qmlStyle = qmlDocument.toString();
4174 
4175  this->exportSldStyle( sldDocument, msgError );
4176  if ( !msgError.isNull() )
4177  {
4178  return;
4179  }
4180  sldStyle = sldDocument.toString();
4181 
4182  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4183  description, uiFileContent, useAsDefault, msgError );
4184 }
4185 
4186 
4187 
4188 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag )
4189 {
4190  return loadNamedStyle( theURI, resultFlag, false );
4191 }
4192 
4193 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB )
4194 {
4195  QgsDataSourceUri dsUri( theURI );
4196  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
4197  {
4198  std::unique_ptr<QLibrary> myLib( QgsProviderRegistry::instance()->createProviderLibrary( mProviderKey ) );
4199  if ( myLib )
4200  {
4201  loadStyle_t *loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4202  if ( loadStyleExternalMethod )
4203  {
4204  QString qml, errorMsg;
4205  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4206  if ( !qml.isEmpty() )
4207  {
4208  QDomDocument myDocument( QStringLiteral( "qgis" ) );
4209  myDocument.setContent( qml );
4210  resultFlag = importNamedStyle( myDocument, errorMsg );
4211  return QObject::tr( "Loaded from Provider" );
4212  }
4213  }
4214  }
4215  }
4216 
4217  return QgsMapLayer::loadNamedStyle( theURI, resultFlag );
4218 }
4219 
4220 QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
4221 {
4222  if ( mDataProvider )
4223  return mDataProvider->dependencies() + mDependencies;
4224  return mDependencies;
4225 }
4226 
4227 bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
4228 {
4229  QSet<QgsMapLayerDependency> deps;
4230  Q_FOREACH ( const QgsMapLayerDependency &dep, oDeps )
4231  {
4232  if ( dep.origin() == QgsMapLayerDependency::FromUser )
4233  deps << dep;
4234  }
4235  if ( hasDependencyCycle( deps ) )
4236  return false;
4237 
4238  QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
4239 
4240  // disconnect layers that are not present in the list of dependencies anymore
4241  Q_FOREACH ( const QgsMapLayerDependency &dep, mDependencies )
4242  {
4243  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4244  if ( !lyr )
4245  continue;
4246  disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::dataChanged );
4247  disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::dataChanged );
4249  disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::dataChanged );
4251  }
4252 
4253  // assign new dependencies
4254  if ( mDataProvider )
4255  mDependencies = mDataProvider->dependencies() + deps;
4256  else
4257  mDependencies = deps;
4258  emit dependenciesChanged();
4259 
4260  // connect to new layers
4261  Q_FOREACH ( const QgsMapLayerDependency &dep, mDependencies )
4262  {
4263  QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
4264  if ( !lyr )
4265  continue;
4271  }
4272 
4273  // if new layers are present, emit a data change
4274  if ( ! toAdd.isEmpty() )
4275  emit dataChanged();
4276 
4277  return true;
4278 }
4279 
4280 QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
4281 {
4282  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4283  return nullptr;
4284 
4285  QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
4286 
4287  // make sure provider constraints are always present!
4288  if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
4289  {
4290  constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
4291  }
4292 
4293  return constraints;
4294 }
4295 
4296 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
4297 {
4298  QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
4299 
4300  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
4301  return m;
4302 
4303  QString name = mFields.at( fieldIndex ).name();
4304 
4305  QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
4306  for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
4307  {
4308  if ( conIt.key().first == name )
4309  {
4310  m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
4311  }
4312  }
4313 
4314  return m;
4315 }
4316 
4318 {
4319  if ( index < 0 || index >= mFields.count() )
4320  return;
4321 
4322  QString name = mFields.at( index ).name();
4323 
4324  // add constraint to existing constraints
4325  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
4326  constraints |= constraint;
4327  mFieldConstraints.insert( name, constraints );
4328 
4329  mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
4330 
4331  updateFields();
4332 }
4333 
4335 {
4336  if ( index < 0 || index >= mFields.count() )
4337  return;
4338 
4339  QString name = mFields.at( index ).name();
4340 
4341  // remove constraint from existing constraints
4342  QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, nullptr );
4343  constraints &= ~constraint;
4344  mFieldConstraints.insert( name, constraints );
4345 
4346  mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
4347 
4348  updateFields();
4349 }
4350 
4351 QString QgsVectorLayer::constraintExpression( int index ) const
4352 {
4353  if ( index < 0 || index >= mFields.count() )
4354  return QString();
4355 
4356  return mFields.at( index ).constraints().constraintExpression();
4357 }
4358 
4359 QString QgsVectorLayer::constraintDescription( int index ) const
4360 {
4361  if ( index < 0 || index >= mFields.count() )
4362  return QString();
4363 
4364  return mFields.at( index ).constraints().constraintDescription();
4365 }
4366 
4367 void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
4368 {
4369  if ( index < 0 || index >= mFields.count() )
4370  return;
4371 
4372  if ( expression.isEmpty() )
4373  {
4374  mFieldConstraintExpressions.remove( mFields.at( index ).name() );
4375  }
4376  else
4377  {
4378  mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
4379  }
4380  updateFields();
4381 }
4382 
4384 {
4385  if ( index < 0 || index >= mFields.count() )
4386  return;
4387 
4388  if ( setup.isNull() )
4389  mFieldWidgetSetups.remove( mFields.at( index ).name() );
4390  else
4391  mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
4392  updateFields();
4393 }
4394 
4396 {
4397 
4398  if ( index < 0 || index >= mFields.count() )
4399  return QgsEditorWidgetSetup();
4400 
4401  return mFields.at( index ).editorWidgetSetup();
4402 }
4403 
4404 QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
4405 {
4407  if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
4408  {
4409  if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() == true )
4410  {
4411  // try to load from custom properties
4412  QgsPalLayerSettings settings;
4413  settings.readFromLayerCustomProperties( this );
4414  labeling = new QgsVectorLayerSimpleLabeling( settings );
4415  }
4416 
4417  // also clear old-style labeling config
4418  removeCustomProperty( QStringLiteral( "labeling" ) );
4419  Q_FOREACH ( const QString &key, customPropertyKeys() )
4420  {
4421  if ( key.startsWith( QLatin1String( "labeling/" ) ) )
4422  removeCustomProperty( key );
4423  }
4424  }
4425 
4426  return labeling;
4427 }
4428 
4430 {
4431  mReadExtentFromXml = readExtentFromXml;
4432 }
4433 
4435 {
4436  return mReadExtentFromXml;
4437 }
4438 
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
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.
void opacityChanged(double opacity)
Emitted when the layer&#39;s opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
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.
double xOffset
Horizontal offset of label.
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.
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...
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)
QgsVectorLayerFeatureCounter * countSymbolFeatures()
Count features for symbols.
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
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.
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
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
QgsVectorLayer(const QString &path=QString(), const QString &baseName=QString(), const QString &providerLib="ogr", bool loadDefaultStyleFlag=true, bool readExtentFromXml=false)
Constructor - creates a vector layer.
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.
int splitFeatures(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
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.
bool hasParam(const QString &key) const
Test if param exists (generic mode)
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.
double angleOffset
Label rotation, in degrees clockwise.
QString mapTipTemplate() const
The mapTip is a pretty, html representation for feature information.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
QString alias
Definition: qgsfield.h: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.
int addPart(const QList< QgsPointXY > &ring)
Adds a new part polygon to a multipart feature.
QSet< QString > excludeAttributesWfs() const
A set of attributes that are not advertised in WFS requests with QGIS server.
QgsGeometry::OperationResult splitFeatures(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
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.
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 accessSectionHtml() const
Formats the "Access" section according to a metadata object.
bool deleteStyleById_t(const QString &uri, QString styleID, QString &errCause)
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:124
QVariant minimumValue(int index) const override
Returns the minimum value for an attribute column or an invalid variant in case of error...
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.
A class to represent a 2D point.
Definition: qgspointxy.h:42
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.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
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.
double yOffset
Vertical offset of label.
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.
virtual const QgsLayerMetadata & metadata() const
Returns a reference to the layer&#39;s metadata store.
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:92
Type type() const
Return the dependency type.
void selectByIds(const QgsFeatureIds &ids, SelectBehavior behavior=SetSelection)
Select matching features using a list of feature IDs.
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:49
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer...
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:6
QgsEditorWidgetSetup editorWidgetSetup() const
Get the editor widget setup for the field.
Definition: qgsfield.cpp:290
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const override
Calculates a list of unique values contained within an attribute in the layer.
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 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:210
QgsFeatureList selectedFeatures() const
Get a copy of the user-selected features.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp: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:366
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1029
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:142
It has not been specified where the field comes from.
Definition: qgsfields.h:47
Constraint was set at data provider.
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.
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
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...
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:1020
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.
QgsRectangle sourceExtent() const override
Returns the extent of all geometries from the source.
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.
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.
virtual void updateExtents(bool force=false)
Update the extents for the layer.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:66
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
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
void deselect(const QgsFeatureId featureId)
Deselect feature by its ID.
#define FALLTHROUGH
Definition: qgis.h:434
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.
int removeParam(const QString &key)
Remove generic param (generic mode)
QString originalName() const
Returns the original name of the layer.
void select(QgsFeatureId featureId)
Select feature by its ID.
QgsRectangle extent() const override
Returns the extent of the layer.
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:103
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:1063
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 description for this layer as defined in the data provider.
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:123
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 extentSectionHtml() const
Formats the "Extents" section according to a metadata object.
double opacity() const
Returns the opacity for the vector layer, where opacity is a value between 0 (totally transparent) an...
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
This signal is emitted, when features are added to the provider.
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.
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.
QgsGeometry::OperationResult addRing(const QList< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
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 this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
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.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
Reads and writes project states.
Definition: qgsproject.h:79
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.
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.
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
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
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 map scale (i.e.
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:89
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 map scale (i.e.
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1023
#define cast_to_fptr(f)
Definition: qgis.h:136
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, comma separated and translated.
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.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:36
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.
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.
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...
QgsGeometry::OperationResult addPart(const QList< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
const QgsDiagramRenderer * diagramRenderer() const
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
int splitParts(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
bool readExtentFromXml() const
Returns true if the extent is read from the XML document when data source has no metadata, false if it&#39;s the data provider which determines it.
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:111
virtual void reload() override
Synchronises with changes in the datasource.
QString uri(bool expandAuthConfig=true) const
return complete uri
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
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.
virtual void cancel()
Notifies the task that it should terminate.
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:96
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 sourceName() const override
Returns a friendly display name for the source.
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.
QVariant maximumValue(int index) const override
Returns the maximum value for an attribute column or an invalid variant in case of error...
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.
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:54
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:1026
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.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
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.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=0) override
Adds a list of features to the sink.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:379
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.
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written. ...
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
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:101
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
Class for metadata formatter.
Basic implementation of the labeling interface.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
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.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:106
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
True if this label is 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.
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:75
QList< QgsPoint > QgsPointSequence
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.
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
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=0) override
Adds a single feature to the sink.
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 QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
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.
int addRing(const QList< QgsPointXY > &ring, QgsFeatureId *featureId=nullptr)
Adds a ring to polygon/multipolygon features.
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.
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:36
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.
void set(const QgsPointXY &p1, const QgsPointXY &p2)
Sets the rectangle from two QgsPoints.
QString authid() const
Returns the authority identifier for the CRS.
QgsAttributes attributes
Definition: qgsfeature.h:71
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.
Used by QgsVectorLayer::countSymbolFeatures() to provide an interruption checker. ...
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
QgsGeometry::OperationResult splitParts(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:130
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Set flags that affect how features will be fetched.
void setReadExtentFromXml(bool readExtentFromXml)
Flag allowing to indicate if the extent has to be read from the XML document when data source has no ...
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)
QString fieldName
Name of field (or an expression) to use for label text.
Field must have a unique value.
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
void setOpacity(double opacity)
Sets the opacity for the vector layer, where opacity is a value between 0 (totally transparent) and 1...
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as named style in a QDomDocument.