QGIS API Documentation  2.17.0-Master (bf77d09)
qgsvectorlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayer.cpp
3  --------------------
4  begin : Oct 29, 2003
5  copyright : (C) 2003 by Gary E.Sherman
6  email : sherman at mrcc.com
7 
8  This class implements a generic means to display vector layers. The features
9  and attributes are read from the data store using a "data provider" plugin.
10  QgsVectorLayer can be used with any data store for which an appropriate
11  plugin is available.
12 
13 ***************************************************************************/
14 
15 /***************************************************************************
16  * *
17  * This program is free software; you can redistribute it and/or modify *
18  * it under the terms of the GNU General Public License as published by *
19  * the Free Software Foundation; either version 2 of the License, or *
20  * (at your option) any later version. *
21  * *
22  ***************************************************************************/
23 
24 #include <limits>
25 
26 #include <QImage>
27 #include <QPainter>
28 #include <QPainterPath>
29 #include <QPolygonF>
30 #include <QProgressDialog>
31 #include <QSettings>
32 #include <QString>
33 #include <QDomNode>
34 #include <QVector>
35 
36 #include "qgsvectorlayer.h"
37 #include "qgsactionmanager.h"
38 #include "qgis.h" //for globals
39 #include "qgsapplication.h"
40 #include "qgsclipper.h"
41 #include "qgsconditionalstyle.h"
43 #include "qgscoordinatetransform.h"
44 #include "qgscurvev2.h"
45 #include "qgsdatasourceuri.h"
47 #include "qgsfeature.h"
48 #include "qgsfeaturerequest.h"
49 #include "qgsfield.h"
50 #include "qgsgeometrycache.h"
51 #include "qgsgeometry.h"
52 #include "qgslabel.h"
53 #include "qgslegacyhelpers.h"
54 #include "qgslogger.h"
55 #include "qgsmaplayerlegend.h"
56 #include "qgsmaplayerregistry.h"
57 #include "qgsmaptopixel.h"
58 #include "qgsmessagelog.h"
59 #include "qgsogcutils.h"
60 #include "qgspoint.h"
61 #include "qgsproject.h"
62 #include "qgsproviderregistry.h"
63 #include "qgsrectangle.h"
64 #include "qgsrelationmanager.h"
65 #include "qgsrendercontext.h"
66 #include "qgsvectordataprovider.h"
72 #include "qgsvectorlayerlabeling.h"
73 #include "qgsvectorlayerrenderer.h"
75 #include "qgspointv2.h"
76 #include "qgsrendererv2.h"
77 #include "qgssymbolv2.h"
78 #include "qgssymbollayerv2.h"
80 #include "qgsdiagramrendererv2.h"
81 #include "qgsstylev2.h"
83 #include "qgspallabeling.h"
84 #include "qgssimplifymethod.h"
85 #include "qgsexpressioncontext.h"
86 
87 #include "diagram/qgsdiagram.h"
88 
89 #ifdef TESTPROVIDERLIB
90 #include <dlfcn.h>
91 #endif
92 
93 typedef bool saveStyle_t(
94  const QString& uri,
95  const QString& qmlStyle,
96  const QString& sldStyle,
97  const QString& styleName,
98  const QString& styleDescription,
99  const QString& uiFileContent,
100  bool useAsDefault,
101  QString& errCause
102 );
103 
105  const QString& uri,
106  QString& errCause
107 );
108 
109 typedef int listStyles_t(
110  const QString& uri,
111  QStringList &ids,
112  QStringList &names,
113  QStringList &descriptions,
114  QString& errCause
115 );
116 
118  const QString& uri,
119  QString styleID,
120  QString& errCause
121 );
122 
123 QgsVectorLayer::QgsVectorLayer( const QString& vectorLayerPath,
124  const QString& baseName,
125  const QString& providerKey,
126  bool loadDefaultStyleFlag )
127  : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
128  , mDataProvider( nullptr )
129  , mProviderKey( providerKey )
130  , mReadOnly( false )
131  , mEditFormConfig( new QgsEditFormConfig( this ) )
132  , mWkbType( QGis::WKBUnknown )
133  , mRendererV2( nullptr )
134  , mLabel( nullptr )
135  , mLabelOn( false )
136  , mLabeling( new QgsVectorLayerSimpleLabeling )
137  , mLabelFontNotFoundNotified( false )
138  , mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
139  , mLayerTransparency( 0 )
140  , mVertexMarkerOnlyForSelection( false )
141  , mCache( new QgsGeometryCache() )
142  , mEditBuffer( nullptr )
143  , mJoinBuffer( nullptr )
144  , mExpressionFieldBuffer( nullptr )
145  , mDiagramRenderer( nullptr )
146  , mDiagramLayerSettings( nullptr )
147  , mValidExtent( false )
148  , mLazyExtent( true )
149  , mSymbolFeatureCounted( false )
150  , mEditCommandActive( false )
151 
152 {
153  mActions = new QgsActionManager( this );
154  mConditionalStyles = new QgsConditionalLayerStyles();
155 
156  // if we're given a provider type, try to create and bind one to this layer
157  if ( ! mProviderKey.isEmpty() )
158  {
159  setDataSource( vectorLayerPath, baseName, providerKey, loadDefaultStyleFlag );
160  }
161 
162  connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( selectionChanged() ) );
163  connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( repaintRequested() ) );
164 
165  // Default simplify drawing settings
166  QSettings settings;
167  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( settings.value( "/qgis/simplifyDrawingHints", static_cast< int>( mSimplifyMethod.simplifyHints() ) ).toInt() ) );
168  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( settings.value( "/qgis/simplifyAlgorithm", static_cast< int>( mSimplifyMethod.simplifyAlgorithm() ) ).toInt() ) );
169  mSimplifyMethod.setThreshold( settings.value( "/qgis/simplifyDrawingTol", mSimplifyMethod.threshold() ).toFloat() );
170  mSimplifyMethod.setForceLocalOptimization( settings.value( "/qgis/simplifyLocal", mSimplifyMethod.forceLocalOptimization() ).toBool() );
171  mSimplifyMethod.setMaximumScale( settings.value( "/qgis/simplifyMaxScale", mSimplifyMethod.maximumScale() ).toFloat() );
172 } // QgsVectorLayer ctor
173 
174 
175 
177 {
178 
179  emit layerDeleted();
180 
181  mValid = false;
182 
183  delete mDataProvider;
184  delete mEditBuffer;
185  delete mJoinBuffer;
186  delete mExpressionFieldBuffer;
187  delete mCache;
188  delete mLabel; // old deprecated implementation
189  delete mLabeling;
190  delete mDiagramLayerSettings;
191  delete mDiagramRenderer;
192 
193  delete mActions;
194 
195  delete mRendererV2;
196  delete mConditionalStyles;
197 }
198 
200 {
201  if ( mDataProvider )
202  {
203  return mDataProvider->storageType();
204  }
205  return nullptr;
206 }
207 
208 
210 {
211  if ( mDataProvider )
212  {
213  return mDataProvider->capabilitiesString();
214  }
215  return nullptr;
216 }
217 
219 {
220  if ( mDataProvider )
221  {
222  return mDataProvider->dataComment();
223  }
224  return QString();
225 }
226 
227 
229 {
230  return mProviderKey;
231 }
232 
237 {
238  if ( !hasGeometryType() )
239  return;
240 
241  // If fldName is provided, use it as the display field, otherwise
242  // determine the field index for the feature column of the identify
243  // dialog. We look for fields containing "name" first and second for
244  // fields containing "id". If neither are found, the first field
245  // is used as the node.
246  QString idxName = "";
247  QString idxId = "";
248 
249  if ( !fldName.isEmpty() )
250  {
251  mDisplayField = fldName;
252  }
253  else
254  {
255  int fieldsSize = mUpdatedFields.size();
256 
257  Q_FOREACH ( const QgsField& field, mUpdatedFields )
258  {
259  QString fldName = field.name();
260  QgsDebugMsg( "Checking field " + fldName + " of " + QString::number( fieldsSize ) + " total" );
261 
262  // Check the fields and keep the first one that matches.
263  // We assume that the user has organized the data with the
264  // more "interesting" field names first. As such, name should
265  // be selected before oldname, othername, etc.
266  if ( fldName.indexOf( "name", 0, Qt::CaseInsensitive ) > -1 )
267  {
268  if ( idxName.isEmpty() )
269  {
270  idxName = fldName;
271  }
272  }
273  if ( fldName.indexOf( "descrip", 0, Qt::CaseInsensitive ) > -1 )
274  {
275  if ( idxName.isEmpty() )
276  {
277  idxName = fldName;
278  }
279  }
280  if ( fldName.indexOf( "id", 0, Qt::CaseInsensitive ) > -1 )
281  {
282  if ( idxId.isEmpty() )
283  {
284  idxId = fldName;
285  }
286  }
287  }
288 
289  //if there were no fields in the dbf just return - otherwise qgis segfaults!
290  if ( fieldsSize == 0 )
291  return;
292 
293  if ( idxName.length() > 0 )
294  {
295  mDisplayField = idxName;
296  }
297  else
298  {
299  if ( idxId.length() > 0 )
300  {
301  mDisplayField = idxId;
302  }
303  else
304  {
305  mDisplayField = mUpdatedFields.at( 0 ).name();
306  }
307  }
308 
309  }
310 }
311 
312 // NOTE this is a temporary method added by Tim to prevent label clipping
313 // which was occurring when labeller was called in the main draw loop
314 // This method will probably be removed again in the near future!
316 {
317  if ( !hasGeometryType() )
318  return;
319 
320  QgsDebugMsg( "Starting draw of labels: " + id() );
321 
322  if ( mRendererV2 && mLabelOn && mLabel &&
323  mLabel->isInScaleRange( rendererContext.rendererScale() ) )
324  {
325  QgsAttributeList attributes;
326  Q_FOREACH ( const QString& attrName, mRendererV2->usedAttributes() )
327  {
328  int attrNum = fieldNameIndex( attrName );
329  attributes.append( attrNum );
330  }
331  // make sure the renderer is ready for classification ("symbolForFeature")
332  mRendererV2->startRender( rendererContext, fields() );
333 
334  // Add fields required for labels
335  mLabel->addRequiredFields( attributes );
336 
337  QgsDebugMsg( "Selecting features based on view extent" );
338 
339  int featureCount = 0;
340 
341  try
342  {
343  // select the records in the extent. The provider sets a spatial filter
344  // and sets up the selection set for retrieval
346  .setFilterRect( rendererContext.extent() )
347  .setSubsetOfAttributes( attributes ) );
348 
349  QgsFeature fet;
350  while ( fit.nextFeature( fet ) )
351  {
352  if ( mRendererV2->willRenderFeature( fet, rendererContext ) )
353  {
354  bool sel = mSelectedFeatureIds.contains( fet.id() );
355  mLabel->renderLabel( rendererContext, fet, sel, nullptr );
356  }
357  featureCount++;
358  }
359  }
360  catch ( QgsCsException &e )
361  {
362  Q_UNUSED( e );
363  QgsDebugMsg( "Error projecting label locations" );
364  }
365 
366  if ( mRendererV2 )
367  {
368  mRendererV2->stopRender( rendererContext );
369  }
370 
371  QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
372  }
373 }
374 
376 {
377  if ( mDataProvider )
378  {
379  mDataProvider->reloadData();
380  updateFields();
381  }
382 }
383 
385 {
386  return new QgsVectorLayerRenderer( this, rendererContext );
387 }
388 
389 bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
390 {
391  QgsVectorLayerRenderer renderer( this, rendererContext );
392  return renderer.render();
393 }
394 
396 {
398  {
399  p.setPen( QColor( 50, 100, 120, 200 ) );
400  p.setBrush( QColor( 200, 200, 210, 120 ) );
401  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
402  }
403  else if ( type == QgsVectorLayer::Cross )
404  {
405  p.setPen( QColor( 255, 0, 0 ) );
406  p.drawLine( x - m, y + m, x + m, y - m );
407  p.drawLine( x - m, y - m, x + m, y + m );
408  }
409 }
410 
412 {
413  mSelectedFeatureIds.insert( fid );
414 
415  emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
416 }
417 
418 void QgsVectorLayer::select( const QgsFeatureIds& featureIds )
419 {
420  mSelectedFeatureIds.unite( featureIds );
421 
422  emit selectionChanged( featureIds, QgsFeatureIds(), false );
423 }
424 
426 {
427  mSelectedFeatureIds.remove( fid );
428 
429  emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
430 }
431 
432 void QgsVectorLayer::deselect( const QgsFeatureIds& featureIds )
433 {
434  mSelectedFeatureIds.subtract( featureIds );
435 
436  emit selectionChanged( QgsFeatureIds(), featureIds, false );
437 }
438 
439 void QgsVectorLayer::select( QgsRectangle & rect, bool addToSelection )
440 {
441  selectByRect( rect, addToSelection ? AddToSelection : SetSelection );
442 }
443 
445 {
446  // normalize the rectangle
447  rect.normalize();
448 
449  QgsFeatureIds newSelection;
450 
452  .setFilterRect( rect )
454  .setSubsetOfAttributes( QgsAttributeList() ) );
455 
456  QgsFeature feat;
457  while ( features.nextFeature( feat ) )
458  {
459  newSelection << feat.id();
460  }
461  features.close();
462 
463  selectByIds( newSelection, behaviour );
464 }
465 
467 {
468  QgsFeatureIds newSelection;
469 
470  QgsExpressionContext context;
474 
475  if ( behaviour == SetSelection || behaviour == AddToSelection )
476  {
478  .setExpressionContext( context )
481 
482  QgsFeatureIterator features = getFeatures( request );
483 
484  if ( behaviour == AddToSelection )
485  {
486  newSelection = selectedFeaturesIds();
487  }
488  QgsFeature feat;
489  while ( features.nextFeature( feat ) )
490  {
491  newSelection << feat.id();
492  }
493  features.close();
494  }
495  else if ( behaviour == IntersectSelection || behaviour == RemoveFromSelection )
496  {
497  QgsExpression exp( expression );
498  exp.prepare( &context );
499 
500  QgsFeatureIds oldSelection = selectedFeaturesIds();
501  QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
502 
503  //refine request
504  if ( !exp.needsGeometry() )
506  request.setSubsetOfAttributes( exp.referencedColumns(), fields() );
507 
508  QgsFeatureIterator features = getFeatures( request );
509  QgsFeature feat;
510  while ( features.nextFeature( feat ) )
511  {
512  context.setFeature( feat );
513  bool matches = exp.evaluate( &context ).toBool();
514 
515  if ( matches && behaviour == IntersectSelection )
516  {
517  newSelection << feat.id();
518  }
519  else if ( !matches && behaviour == RemoveFromSelection )
520  {
521  newSelection << feat.id();
522  }
523  }
524  }
525 
526  selectByIds( newSelection );
527 }
528 
530 {
531  QgsFeatureIds newSelection;
532 
533  switch ( behaviour )
534  {
535  case SetSelection:
536  newSelection = ids;
537  break;
538 
539  case AddToSelection:
540  newSelection = mSelectedFeatureIds + ids;
541  break;
542 
543  case RemoveFromSelection:
544  newSelection = mSelectedFeatureIds - ids;
545  break;
546 
547  case IntersectSelection:
548  newSelection = mSelectedFeatureIds.intersect( ids );
549  break;
550  }
551 
552  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
553  mSelectedFeatureIds = newSelection;
554 
555  emit selectionChanged( newSelection, deselectedFeatures, true );
556 }
557 
559 {
560  QgsFeatureIds intersectingIds = selectIds & deselectIds;
561  if ( !intersectingIds.isEmpty() )
562  {
563  QgsDebugMsg( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." );
564  }
565 
566  mSelectedFeatureIds -= deselectIds;
567  mSelectedFeatureIds += selectIds;
568 
569  emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
570 }
571 
573 {
575  ids.subtract( mSelectedFeatureIds );
576  selectByIds( ids );
577 }
578 
580 {
582 }
583 
585 {
587  .setFlags( QgsFeatureRequest::NoGeometry )
588  .setSubsetOfAttributes( QgsAttributeList() ) );
589 
590  QgsFeatureIds ids;
591 
592  QgsFeature fet;
593  while ( fit.nextFeature( fet ) )
594  {
595  ids << fet.id();
596  }
597 
598  return ids;
599 }
600 
602 {
603  // normalize the rectangle
604  rect.normalize();
605 
607  .setFilterRect( rect )
609  .setSubsetOfAttributes( QgsAttributeList() ) );
610 
611  QgsFeatureIds selectIds;
612  QgsFeatureIds deselectIds;
613 
614  QgsFeature fet;
615  while ( fit.nextFeature( fet ) )
616  {
617  if ( mSelectedFeatureIds.contains( fet.id() ) )
618  {
619  deselectIds << fet.id();
620  }
621  else
622  {
623  selectIds << fet.id();
624  }
625  }
626 
627  modifySelection( selectIds, deselectIds );
628 }
629 
631 {
632  if ( mSelectedFeatureIds.isEmpty() )
633  return;
634 
636 }
637 
639 {
640  return mDataProvider;
641 }
642 
644 {
645  return mDataProvider;
646 }
647 
649 {
650  if ( mValid && mDataProvider && mDataProvider->encoding() != encoding )
651  {
652  mDataProvider->setEncoding( encoding );
653  updateFields();
654  }
655 }
656 
658 {
659  delete mDiagramRenderer;
660  mDiagramRenderer = r;
661  emit rendererChanged();
662  emit styleChanged();
663 }
664 
666 {
667  if ( mValid && mDataProvider )
668  {
669  QGis::WkbType type = mDataProvider->geometryType();
670  return static_cast< QGis::GeometryType >( QgsWKBTypes::geometryType( static_cast< QgsWKBTypes::Type >( type ) ) );
671  }
672  else
673  {
674  QgsDebugMsg( "invalid layer or pointer to mDataProvider is null" );
675  }
676 
677  // We shouldn't get here, and if we have, other things are likely to
678  // go wrong. Code that uses the type() return value should be
679  // rewritten to cope with a value of QGis::Unknown. To make this
680  // need known, the following message is printed every time we get
681  // here.
682  QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
683 
684  return QGis::UnknownGeometry;
685 }
686 
688 {
690  return t != QGis::NoGeometry && t != QGis::UnknownGeometry;
691 }
692 
694 {
695  return mWkbType;
696 }
697 
699 {
700  if ( !mValid || mSelectedFeatureIds.isEmpty() ) //no selected features
701  {
702  return QgsRectangle( 0, 0, 0, 0 );
703  }
704 
705  QgsRectangle r, retval;
706  retval.setMinimal();
707 
708  QgsFeature fet;
709  if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
710  {
712  .setFilterFids( mSelectedFeatureIds )
713  .setSubsetOfAttributes( QgsAttributeList() ) );
714 
715  while ( fit.nextFeature( fet ) )
716  {
717  if ( !fet.constGeometry() || fet.constGeometry()->isEmpty() )
718  continue;
719  r = fet.constGeometry()->boundingBox();
720  retval.combineExtentWith( r );
721  }
722  }
723  else
724  {
726  .setSubsetOfAttributes( QgsAttributeList() ) );
727 
728  while ( fit.nextFeature( fet ) )
729  {
730  if ( mSelectedFeatureIds.contains( fet.id() ) )
731  {
732  if ( fet.constGeometry() )
733  {
734  r = fet.constGeometry()->boundingBox();
735  retval.combineExtentWith( r );
736  }
737  }
738  }
739  }
740 
741  if ( retval.width() == 0.0 || retval.height() == 0.0 )
742  {
743  // If all of the features are at the one point, buffer the
744  // rectangle a bit. If they are all at zero, do something a bit
745  // more crude.
746 
747  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
748  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
749  {
750  retval.set( -1.0, -1.0, 1.0, 1.0 );
751  }
752  }
753 
754  return retval;
755 }
756 
758 {
759  if ( !mLabeling )
760  return false;
761 
762  // for simple labeling the mode can be "no labels" - so we need to check
763  // in properties whether we are really enabled or not
764  if ( mLabeling->type() == "simple" )
765  return customProperty( "labeling/enabled", QVariant( false ) ).toBool();
766 
767  // for other labeling implementations we always assume that labeling is enabled
768  return true;
769 }
770 
772 {
773  if ( !mDiagramRenderer || !mDiagramLayerSettings )
774  return false;
775 
776  QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
777  if ( !settingList.isEmpty() )
778  {
779  return settingList.at( 0 ).enabled;
780  }
781  return false;
782 }
783 
785 {
786  if ( !mSymbolFeatureCounted )
787  return -1;
788 
789  return mSymbolFeatureCountMap.value( symbol );
790 }
791 
797 {
798  public:
799 
802  : mDialog( dialog )
803  {
804  }
805 
806  virtual bool mustStop() const
807  {
808  if ( mDialog->isVisible() )
809  {
810  // So that we get a chance of hitting the Abort button
811 #ifdef Q_OS_LINUX
812  // For some reason on Windows hasPendingEvents() always return true,
813  // but one iteration is actually enough on Windows to get good interactivity
814  // whereas on Linux we must allow for far more iterations.
815  // For safety limit the number of iterations
816  int nIters = 0;
817  while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
818 #endif
819  {
821  }
822  return mDialog->wasCanceled();
823  }
824  return false;
825  }
826 
827  private:
828  QProgressDialog* mDialog;
829 };
830 
831 bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
832 {
833  if ( mSymbolFeatureCounted )
834  return true;
835 
836  mSymbolFeatureCountMap.clear();
837 
838  if ( !mValid )
839  {
840  QgsDebugMsg( "invoked with invalid layer" );
841  return false;
842  }
843  if ( !mDataProvider )
844  {
845  QgsDebugMsg( "invoked with null mDataProvider" );
846  return false;
847  }
848  if ( !mRendererV2 )
849  {
850  QgsDebugMsg( "invoked with null mRendererV2" );
851  return false;
852  }
853 
854  QgsLegendSymbolList symbolList = mRendererV2->legendSymbolItems();
855  QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
856 
857  for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
858  {
859  mSymbolFeatureCountMap.insert( symbolIt->second, 0 );
860  }
861 
862  long nFeatures = featureCount();
863 
864  QWidget* mainWindow = nullptr;
865  Q_FOREACH ( QWidget* widget, qApp->topLevelWidgets() )
866  {
867  if ( widget->objectName() == "QgisApp" )
868  {
869  mainWindow = widget;
870  break;
871  }
872  }
873 
874  QProgressDialog progressDialog( tr( "Updating feature count for layer %1" ).arg( name() ), tr( "Abort" ), 0, nFeatures, mainWindow );
875  progressDialog.setWindowTitle( tr( "QGIS" ) );
876  progressDialog.setWindowModality( Qt::WindowModal );
877  if ( showProgress )
878  {
879  // Properly initialize to 0 as recommended in doc so that the evaluation
880  // of the total time properly works
881  progressDialog.setValue( 0 );
882  }
883  int featuresCounted = 0;
884 
885  QgsFeatureRequest request;
886  if ( !mRendererV2->filterNeedsGeometry() )
888  request.setSubsetOfAttributes( mRendererV2->usedAttributes(), mUpdatedFields );
889  QgsFeatureIterator fit = getFeatures( request );
890  QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures interruptionCheck( &progressDialog );
891  if ( showProgress )
892  {
893  fit.setInterruptionChecker( &interruptionCheck );
894  }
895 
896  // Renderer (rule based) may depend on context scale, with scale is ignored if 0
897  QgsRenderContext renderContext;
898  renderContext.setRendererScale( 0 );
902 
903  mRendererV2->startRender( renderContext, fields() );
904 
905  QgsFeature f;
906  QTime time;
907  time.start();
908  while ( fit.nextFeature( f ) )
909  {
910  renderContext.expressionContext().setFeature( f );
911  QgsSymbolV2List featureSymbolList = mRendererV2->originalSymbolsForFeature( f, renderContext );
912  for ( QgsSymbolV2List::iterator symbolIt = featureSymbolList.begin(); symbolIt != featureSymbolList.end(); ++symbolIt )
913  {
914  mSymbolFeatureCountMap[*symbolIt] += 1;
915  }
916  ++featuresCounted;
917 
918  if ( showProgress )
919  {
920  // Refresh progress every 50 features or second
921  if (( featuresCounted % 50 == 0 ) || time.elapsed() > 1000 )
922  {
923  time.restart();
924  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
925  {
926  progressDialog.setMaximum( 0 );
927  }
928  progressDialog.setValue( featuresCounted );
929  }
930  // So that we get a chance of hitting the Abort button
931 #ifdef Q_OS_LINUX
932  // For some reason on Windows hasPendingEvents() always return true,
933  // but one iteration is actually enough on Windows to get good interactivity
934  // whereas on Linux we must allow for far more iterations.
935  // For safety limit the number of iterations
936  int nIters = 0;
937  while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
938 #endif
939  {
941  }
942  if ( progressDialog.wasCanceled() )
943  {
944  mSymbolFeatureCountMap.clear();
945  mRendererV2->stopRender( renderContext );
946  return false;
947  }
948  }
949  }
950  mRendererV2->stopRender( renderContext );
951  progressDialog.setValue( nFeatures );
952  mSymbolFeatureCounted = true;
953  return true;
954 }
955 
957 {
958  mValidExtent = false;
959 }
960 
962 {
964  mValidExtent = true;
965 }
966 
968 {
969  QgsRectangle rect;
970  rect.setMinimal();
971 
972  if ( !hasGeometryType() )
973  return rect;
974 
975  if ( !mValidExtent && mLazyExtent && mDataProvider )
976  {
977  // get the extent
978  QgsRectangle mbr = mDataProvider->extent();
979 
980  // show the extent
981  QgsDebugMsg( "Extent of layer: " + mbr.toString() );
982  // store the extent
983  setExtent( mbr );
984 
985  mLazyExtent = false;
986  }
987 
988  if ( mValidExtent )
989  return QgsMapLayer::extent();
990 
991  if ( !mValid || !mDataProvider )
992  {
993  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
994  return rect;
995  }
996 
997  if ( !mEditBuffer ||
998  ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() ) ||
999  QgsDataSourceURI( mDataProvider->dataSourceUri() ).useEstimatedMetadata() )
1000  {
1001  mDataProvider->updateExtents();
1002 
1003  // get the extent of the layer from the provider
1004  // but only when there are some features already
1005  if ( mDataProvider->featureCount() != 0 )
1006  {
1007  QgsRectangle r = mDataProvider->extent();
1008  rect.combineExtentWith( r );
1009  }
1010 
1011  if ( mEditBuffer )
1012  {
1013  for ( QgsFeatureMap::const_iterator it = mEditBuffer->mAddedFeatures.constBegin(); it != mEditBuffer->mAddedFeatures.constEnd(); ++it )
1014  {
1015  if ( it->constGeometry() )
1016  {
1017  QgsRectangle r = it->constGeometry()->boundingBox();
1018  rect.combineExtentWith( r );
1019  }
1020  }
1021  }
1022  }
1023  else
1024  {
1026  .setSubsetOfAttributes( QgsAttributeList() ) );
1027 
1028  QgsFeature fet;
1029  while ( fit.nextFeature( fet ) )
1030  {
1031  if ( fet.constGeometry() && fet.constGeometry()->type() != QGis::UnknownGeometry )
1032  {
1033  QgsRectangle bb = fet.constGeometry()->boundingBox();
1034  rect.combineExtentWith( bb );
1035  }
1036  }
1037  }
1038 
1039  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
1040  {
1041  // special case when there are no features in provider nor any added
1042  rect = QgsRectangle(); // use rectangle with zero coordinates
1043  }
1044 
1045  setExtent( rect );
1046 
1047  // Send this (hopefully) up the chain to the map canvas
1048  emit recalculateExtents();
1049 
1050  return rect;
1051 }
1052 
1054 {
1055  if ( !mValid || !mDataProvider )
1056  {
1057  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
1058  return nullptr;
1059  }
1060  return mDataProvider->subsetString();
1061 }
1062 
1064 {
1065  if ( !mValid || !mDataProvider )
1066  {
1067  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
1068  return false;
1069  }
1070 
1071  bool res = mDataProvider->setSubsetString( subset );
1072 
1073  // get the updated data source string from the provider
1074  mDataSource = mDataProvider->dataSourceUri();
1075  updateExtents();
1076  updateFields();
1077 
1078  if ( res )
1079  emit repaintRequested();
1080 
1081  return res;
1082 }
1083 
1085 {
1086  if ( mValid && mDataProvider && !mEditBuffer && ( hasGeometryType() && geometryType() != QGis::Point ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
1087  {
1088  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
1089 
1090  // check maximum scale at which generalisation should be carried out
1091  if ( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale )
1092  return false;
1093 
1094  return true;
1095  }
1096  return false;
1097 }
1098 
1100 {
1101  return mConditionalStyles;
1102 }
1103 
1105 {
1106  if ( !mValid || !mDataProvider )
1107  return QgsFeatureIterator();
1108 
1109  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
1110 }
1111 
1112 
1113 bool QgsVectorLayer::addFeature( QgsFeature& feature, bool alsoUpdateExtent )
1114 {
1115  Q_UNUSED( alsoUpdateExtent ); // TODO[MD]
1116  if ( !mValid || !mEditBuffer || !mDataProvider )
1117  return false;
1118 
1119  bool success = mEditBuffer->addFeature( feature );
1120 
1121  if ( success )
1122  updateExtents();
1123 
1124  return success;
1125 }
1126 
1128 {
1129  QgsFeatureRequest req;
1130  req.setFilterFid( f.id() );
1131  if ( !f.constGeometry() )
1133  if ( f.attributes().isEmpty() )
1135 
1136  QgsFeature current;
1137  if ( !getFeatures( req ).nextFeature( current ) )
1138  {
1139  QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( f.id() ) );
1140  return false;
1141  }
1142 
1143  if ( f.constGeometry() && current.constGeometry() && f.constGeometry() != current.constGeometry() && !f.constGeometry()->isGeosEqual( *current.constGeometry() ) )
1144  {
1145  if ( !changeGeometry( f.id(), f.geometry() ) )
1146  {
1147  QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( f.id() ) );
1148  return false;
1149  }
1150  }
1151 
1152  QgsAttributes fa = f.attributes();
1153  QgsAttributes ca = current.attributes();
1154 
1155  for ( int attr = 0; attr < fa.count(); ++attr )
1156  {
1157  if ( fa.at( attr ) != ca.at( attr ) )
1158  {
1159  if ( !changeAttributeValue( f.id(), attr, fa.at( attr ), ca.at( attr ) ) )
1160  {
1161  QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( f.id() ) );
1162  return false;
1163  }
1164  }
1165  }
1166 
1167  return true;
1168 }
1169 
1170 
1171 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1172 {
1173  if ( !mValid || !mEditBuffer || !mDataProvider )
1174  return false;
1175 
1176  QgsVectorLayerEditUtils utils( this );
1177  bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
1178  if ( result )
1179  updateExtents();
1180  return result;
1181 }
1182 
1183 
1184 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1185 {
1186  if ( !mValid || !mEditBuffer || !mDataProvider )
1187  return false;
1188 
1189  QgsVectorLayerEditUtils utils( this );
1190  bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
1191 
1192  if ( result )
1193  updateExtents();
1194  return result;
1195 }
1196 
1197 bool QgsVectorLayer::moveVertex( const QgsPointV2& p, QgsFeatureId atFeatureId, int atVertex )
1198 {
1199  if ( !mValid || !mEditBuffer || !mDataProvider )
1200  return false;
1201 
1202  QgsVectorLayerEditUtils utils( this );
1203  bool result = utils.moveVertex( p, atFeatureId, atVertex );
1204 
1205  if ( result )
1206  updateExtents();
1207  return result;
1208 }
1209 
1210 bool QgsVectorLayer::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
1211 {
1212  QgsVectorLayer::EditResult res = deleteVertexV2( atFeatureId, atVertex );
1213  bool result = ( res == QgsVectorLayer::Success || res == QgsVectorLayer::EmptyGeometry );
1214 
1215  if ( result )
1216  updateExtents();
1217  return result;
1218 }
1219 
1221 {
1222  if ( !mValid || !mEditBuffer || !mDataProvider )
1224 
1225  QgsVectorLayerEditUtils utils( this );
1226  EditResult result = utils.deleteVertexV2( featureId, vertex );
1227 
1228  if ( result == Success )
1229  updateExtents();
1230  return result;
1231 }
1232 
1233 
1235 {
1236  if ( !mValid || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1237  {
1238  return false;
1239  }
1240 
1241  if ( !isEditable() )
1242  {
1243  return false;
1244  }
1245 
1246  int deleted = 0;
1247  int count = mSelectedFeatureIds.size();
1248  // Make a copy since deleteFeature modifies mSelectedFeatureIds
1249  QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1250  Q_FOREACH ( QgsFeatureId fid, selectedFeatures )
1251  {
1252  deleted += deleteFeature( fid ); // removes from selection
1253  }
1254 
1255  triggerRepaint();
1256  updateExtents();
1257 
1258  if ( deletedCount )
1259  {
1260  *deletedCount = deleted;
1261  }
1262 
1263  return deleted == count;
1264 }
1265 
1267 {
1268  if ( !mValid || !mEditBuffer || !mDataProvider )
1269  return 6;
1270 
1271  QgsVectorLayerEditUtils utils( this );
1272  int result = 5;
1273 
1274  //first try with selected features
1275  if ( !mSelectedFeatureIds.isEmpty() )
1276  {
1277  result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1278  }
1279 
1280  if ( result != 0 )
1281  {
1282  //try with all intersecting features
1283  result = utils.addRing( ring, QgsFeatureIds(), featureId );
1284  }
1285 
1286  return result;
1287 }
1288 
1290 {
1291  if ( !mValid || !mEditBuffer || !mDataProvider )
1292  {
1293  delete ring;
1294  return 6;
1295  }
1296 
1297  if ( !ring )
1298  {
1299  return 1;
1300  }
1301 
1302  if ( !ring->isClosed() )
1303  {
1304  delete ring;
1305  return 2;
1306  }
1307 
1308  QgsVectorLayerEditUtils utils( this );
1309  int result = 5;
1310 
1311  //first try with selected features
1312  if ( !mSelectedFeatureIds.isEmpty() )
1313  {
1314  result = utils.addRing( static_cast< QgsCurveV2* >( ring->clone() ), mSelectedFeatureIds, featureId );
1315  }
1316 
1317  if ( result != 0 )
1318  {
1319  //try with all intersecting features
1320  result = utils.addRing( static_cast< QgsCurveV2* >( ring->clone() ), QgsFeatureIds(), featureId );
1321  }
1322 
1323  delete ring;
1324  return result;
1325 }
1326 
1328 {
1329  if ( !mValid || !mEditBuffer || !mDataProvider )
1330  return 7;
1331 
1332  //number of selected features must be 1
1333 
1334  if ( mSelectedFeatureIds.size() < 1 )
1335  {
1336  QgsDebugMsg( "Number of selected features <1" );
1337  return 4;
1338  }
1339  else if ( mSelectedFeatureIds.size() > 1 )
1340  {
1341  QgsDebugMsg( "Number of selected features >1" );
1342  return 5;
1343  }
1344 
1345  QgsVectorLayerEditUtils utils( this );
1346  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1347 
1348  if ( result == 0 )
1349  updateExtents();
1350  return result;
1351 }
1352 
1354 {
1355  if ( !mValid || !mEditBuffer || !mDataProvider )
1356  return 7;
1357 
1358  //number of selected features must be 1
1359 
1360  if ( mSelectedFeatureIds.size() < 1 )
1361  {
1362  QgsDebugMsg( "Number of selected features <1" );
1363  return 4;
1364  }
1365  else if ( mSelectedFeatureIds.size() > 1 )
1366  {
1367  QgsDebugMsg( "Number of selected features >1" );
1368  return 5;
1369  }
1370 
1371  QgsVectorLayerEditUtils utils( this );
1372  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1373 
1374  if ( result == 0 )
1375  updateExtents();
1376  return result;
1377 }
1378 
1380 {
1381  if ( !mValid || !mEditBuffer || !mDataProvider )
1382  return 7;
1383 
1384  //number of selected features must be 1
1385 
1386  if ( mSelectedFeatureIds.size() < 1 )
1387  {
1388  QgsDebugMsg( "Number of selected features <1" );
1389  return 4;
1390  }
1391  else if ( mSelectedFeatureIds.size() > 1 )
1392  {
1393  QgsDebugMsg( "Number of selected features >1" );
1394  return 5;
1395  }
1396 
1397  QgsVectorLayerEditUtils utils( this );
1398  int result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1399 
1400  if ( result == 0 )
1401  updateExtents();
1402  return result;
1403 }
1404 
1405 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1406 {
1407  if ( !mValid || !mEditBuffer || !mDataProvider )
1408  return -1;
1409 
1410  QgsVectorLayerEditUtils utils( this );
1411  int result = utils.translateFeature( featureId, dx, dy );
1412 
1413  if ( result == 0 )
1414  updateExtents();
1415  return result;
1416 }
1417 
1418 int QgsVectorLayer::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1419 {
1420  if ( !mValid || !mEditBuffer || !mDataProvider )
1421  return -1;
1422 
1423  QgsVectorLayerEditUtils utils( this );
1424  return utils.splitParts( splitLine, topologicalEditing );
1425 }
1426 
1427 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1428 {
1429  if ( !mValid || !mEditBuffer || !mDataProvider )
1430  return -1;
1431 
1432  QgsVectorLayerEditUtils utils( this );
1433  return utils.splitFeatures( splitLine, topologicalEditing );
1434 }
1435 
1437 {
1438  if ( !hasGeometryType() )
1439  return 1;
1440 
1441  int returnValue = 0;
1442 
1443  //first test if geom really has type polygon or multipolygon
1444  if ( geom->type() != QGis::Polygon )
1445  {
1446  return 1;
1447  }
1448 
1449  //get bounding box of geom
1450  QgsRectangle geomBBox = geom->boundingBox();
1451 
1452  //get list of features that intersect this bounding box
1454  .setFilterRect( geomBBox )
1456  .setSubsetOfAttributes( QgsAttributeList() ) );
1457 
1458  QgsFeature f;
1459  while ( fit.nextFeature( f ) )
1460  {
1461  if ( ignoreFeatures.contains( f.id() ) )
1462  {
1463  continue;
1464  }
1465 
1466  //call geometry->makeDifference for each feature
1467  const QgsGeometry *currentGeom = f.constGeometry();
1468  if ( currentGeom )
1469  {
1470  if ( geom->makeDifference( currentGeom ) != 0 )
1471  {
1472  returnValue = 2;
1473  }
1474  }
1475  }
1476 
1477  return returnValue;
1478 }
1479 
1481 {
1482  if ( !mValid || !mEditBuffer || !mDataProvider )
1483  return -1;
1484 
1485  QgsVectorLayerEditUtils utils( this );
1486  return utils.addTopologicalPoints( geom );
1487 }
1488 
1490 {
1491  if ( !mValid || !mEditBuffer || !mDataProvider )
1492  return -1;
1493 
1494  QgsVectorLayerEditUtils utils( this );
1495  return utils.addTopologicalPoints( p );
1496 }
1497 
1499 {
1500  return mLabel;
1501 }
1502 
1504 {
1505  return mLabel;
1506 }
1507 
1509 {
1510  mLabelOn = on;
1511 }
1512 
1514 {
1515  return mLabelOn;
1516 }
1517 
1519 {
1520  if ( mLabeling == labeling )
1521  return;
1522 
1523  delete mLabeling;
1524  mLabeling = labeling;
1525 }
1526 
1528 {
1529  if ( !mValid || !mDataProvider )
1530  {
1531  return false;
1532  }
1533 
1534  // allow editing if provider supports any of the capabilities
1535  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1536  {
1537  return false;
1538  }
1539 
1540  if ( mReadOnly )
1541  {
1542  return false;
1543  }
1544 
1545  if ( mEditBuffer )
1546  {
1547  // editing already underway
1548  return false;
1549  }
1550 
1551  emit beforeEditingStarted();
1552 
1553  mDataProvider->enterUpdateMode();
1554 
1555  if ( mDataProvider->transaction() )
1556  {
1557  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1558  }
1559  else
1560  {
1561  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1562  }
1563  // forward signals
1564  connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( invalidateSymbolCountedFlag() ) );
1565  connect( mEditBuffer, SIGNAL( layerModified() ), this, SIGNAL( layerModified() ) ); // TODO[MD]: necessary?
1566  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1567  connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( featureAdded( QgsFeatureId ) ) );
1568  connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
1569  connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
1570  connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
1571  connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), this, SIGNAL( attributeAdded( int ) ) );
1572  connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), this, SIGNAL( attributeDeleted( int ) ) );
1573 
1574  connect( mEditBuffer, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ),
1575  this, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ) );
1576 
1577  connect( mEditBuffer, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ),
1578  this, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ) );
1579 
1580  connect( mEditBuffer, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ), this, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ) );
1581  connect( mEditBuffer, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ), this, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ) );
1582 
1583  connect( mEditBuffer, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ),
1584  this, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ) );
1585 
1586  connect( mEditBuffer, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ),
1587  this, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ) );
1588 
1589  updateFields();
1590 
1591  emit editingStarted();
1592 
1593  return true;
1594 }
1595 
1596 bool QgsVectorLayer::readXml( const QDomNode& layer_node )
1597 {
1598  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
1599 
1600  //process provider key
1601  QDomNode pkeyNode = layer_node.namedItem( "provider" );
1602 
1603  if ( pkeyNode.isNull() )
1604  {
1605  mProviderKey = "";
1606  }
1607  else
1608  {
1609  QDomElement pkeyElt = pkeyNode.toElement();
1610  mProviderKey = pkeyElt.text();
1611  }
1612 
1613  // determine type of vector layer
1614  if ( !mProviderKey.isNull() )
1615  {
1616  // if the provider string isn't empty, then we successfully
1617  // got the stored provider
1618  }
1619  else if ( mDataSource.contains( "dbname=" ) )
1620  {
1621  mProviderKey = "postgres";
1622  }
1623  else
1624  {
1625  mProviderKey = "ogr";
1626  }
1627 
1628  if ( !setDataProvider( mProviderKey ) )
1629  {
1630  return false;
1631  }
1632 
1633  QDomElement mapLayerNode = layer_node.toElement();
1634  if ( mapLayerNode.attribute( "readOnly", "0" ).toInt() == 1 )
1635  mReadOnly = true;
1636 
1637  QDomElement pkeyElem = pkeyNode.toElement();
1638  if ( !pkeyElem.isNull() )
1639  {
1640  QString encodingString = pkeyElem.attribute( "encoding" );
1641  if ( !encodingString.isEmpty() )
1642  {
1643  mDataProvider->setEncoding( encodingString );
1644  }
1645  }
1646 
1647  //load vector joins
1648  if ( !mJoinBuffer )
1649  {
1650  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1651  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1652  }
1653  mJoinBuffer->readXml( layer_node );
1654 
1655  if ( !mExpressionFieldBuffer )
1656  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1657  mExpressionFieldBuffer->readXml( layer_node );
1658 
1659  updateFields();
1660  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1661 
1662  QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );
1663 
1664  if ( prevExpNode.isNull() )
1665  {
1666  mDisplayExpression = "";
1667  }
1668  else
1669  {
1670  QDomElement prevExpElem = prevExpNode.toElement();
1671  mDisplayExpression = prevExpElem.text();
1672  }
1673 
1674  QString errorMsg;
1675  if ( !readSymbology( layer_node, errorMsg ) )
1676  {
1677  return false;
1678  }
1679 
1680  readStyleManager( layer_node );
1681 
1682 
1684 
1685  return mValid; // should be true if read successfully
1686 
1687 } // void QgsVectorLayer::readXml
1688 
1689 
1690 void QgsVectorLayer::setDataSource( const QString& dataSource, const QString& baseName, const QString& provider, bool loadDefaultStyleFlag )
1691 {
1692  QGis::GeometryType oldGeomType = mValid && mDataProvider ? geometryType() : QGis::UnknownGeometry;
1693 
1694  mDataSource = dataSource;
1695  mLayerName = capitaliseLayerName( baseName );
1696  setName( mLayerName );
1697  setDataProvider( provider );
1698 
1699  if ( !mValid )
1700  return;
1701 
1702  // Always set crs
1704 
1705  // reset style if loading default style, style is missing, or geometry type has changed
1706  if ( !rendererV2() || !legend() || oldGeomType != geometryType() || loadDefaultStyleFlag )
1707  {
1708  // check if there is a default style / propertysheet defined
1709  // for this layer and if so apply it
1710  bool defaultLoadedFlag = false;
1711  if ( loadDefaultStyleFlag )
1712  {
1713  loadDefaultStyle( defaultLoadedFlag );
1714  }
1715 
1716  // if the default style failed to load or was disabled use some very basic defaults
1717  if ( !defaultLoadedFlag && hasGeometryType() )
1718  {
1719  // add single symbol renderer
1721  }
1722 
1724  }
1725 
1726  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1727  emit repaintRequested();
1728 }
1729 
1730 
1731 bool QgsVectorLayer::setDataProvider( QString const & provider )
1732 {
1733  mProviderKey = provider; // XXX is this necessary? Usually already set
1734  // XXX when execution gets here.
1735 
1736  //XXX - This was a dynamic cast but that kills the Windows
1737  // version big-time with an abnormal termination error
1738  delete mDataProvider;
1739  mDataProvider = ( QgsVectorDataProvider* )( QgsProviderRegistry::instance()->provider( provider, mDataSource ) );
1740  if ( !mDataProvider )
1741  {
1742  QgsDebugMsg( " unable to get data provider" );
1743  return false;
1744  }
1745 
1746  connect( mDataProvider, SIGNAL( raiseError( QString ) ), this, SIGNAL( raiseError( QString ) ) );
1747 
1748  QgsDebugMsg( "Instantiated the data provider plugin" );
1749 
1750  mValid = mDataProvider->isValid();
1751  if ( !mValid )
1752  {
1753  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1754  return false;
1755  }
1756 
1757  // TODO: Check if the provider has the capability to send fullExtentCalculated
1758  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
1759 
1760  // get and store the feature type
1761  mWkbType = mDataProvider->geometryType();
1762 
1763  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1764  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1765  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1766  updateFields();
1767 
1768  // look at the fields in the layer and set the primary
1769  // display field using some real fuzzy logic
1770  setDisplayField();
1771 
1772  if ( mProviderKey == "postgres" )
1773  {
1774  QgsDebugMsg( "Beautifying layer name " + name() );
1775 
1776  // adjust the display name for postgres layers
1777  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1778  if ( reg.indexIn( name() ) >= 0 )
1779  {
1780  QStringList stuff = reg.capturedTexts();
1781  QString lName = stuff[1];
1782 
1784 
1786  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1787  ;
1788 
1789  if ( it != layers.constEnd() && stuff.size() > 2 )
1790  {
1791  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1792  }
1793 
1794  if ( !lName.isEmpty() )
1795  setName( lName );
1796  }
1797 
1798  QgsDebugMsg( "Beautified layer name " + name() );
1799 
1800  // deal with unnecessary schema qualification to make v.in.ogr happy
1801  mDataSource = mDataProvider->dataSourceUri();
1802  }
1803  else if ( mProviderKey == "osm" )
1804  {
1805  // make sure that the "observer" has been removed from URI to avoid crashes
1806  mDataSource = mDataProvider->dataSourceUri();
1807  }
1808  else if ( provider == "ogr" )
1809  {
1810  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1811  mDataSource = mDataProvider->dataSourceUri();
1812  if ( mDataSource.right( 10 ) == "|layerid=0" )
1813  mDataSource.chop( 10 );
1814  }
1815 
1816  // label
1817  mLabel = new QgsLabel( mDataProvider->fields() );
1818  mLabelOn = false;
1819 
1820  connect( mDataProvider, SIGNAL( dataChanged() ), this, SIGNAL( dataChanged() ) );
1821  connect( mDataProvider, SIGNAL( dataChanged() ), this, SLOT( removeSelection() ) );
1822 
1823  return true;
1824 } // QgsVectorLayer:: setDataProvider
1825 
1826 
1827 
1828 
1829 /* virtual */
1831  QDomDocument & document )
1832 {
1833  // first get the layer element so that we can append the type attribute
1834 
1835  QDomElement mapLayerNode = layer_node.toElement();
1836 
1837  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1838  {
1839  QgsDebugMsg( "can't find <maplayer>" );
1840  return false;
1841  }
1842 
1843  mapLayerNode.setAttribute( "type", "vector" );
1844 
1845  // set the geometry type
1846  mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
1847 
1848  // add provider node
1849  if ( mDataProvider )
1850  {
1851  QDomElement provider = document.createElement( "provider" );
1852  provider.setAttribute( "encoding", mDataProvider->encoding() );
1853  QDomText providerText = document.createTextNode( providerType() );
1854  provider.appendChild( providerText );
1855  layer_node.appendChild( provider );
1856  }
1857 
1858  // save readonly state
1859  mapLayerNode.setAttribute( "readOnly", mReadOnly );
1860 
1861  // save preview expression
1862  QDomElement prevExpElem = document.createElement( "previewExpression" );
1863  QDomText prevExpText = document.createTextNode( mDisplayExpression );
1864  prevExpElem.appendChild( prevExpText );
1865  layer_node.appendChild( prevExpElem );
1866 
1867  //save joins
1868  mJoinBuffer->writeXml( layer_node, document );
1869 
1870  // dependencies
1871  QDomElement dependenciesElement = document.createElement( "layerDependencies" );
1872  Q_FOREACH ( QString layerId, layerDependencies() )
1873  {
1874  QDomElement depElem = document.createElement( "layer" );
1875  depElem.setAttribute( "id", layerId );
1876  dependenciesElement.appendChild( depElem );
1877  }
1878  layer_node.appendChild( dependenciesElement );
1879 
1880  // save expression fields
1881  mExpressionFieldBuffer->writeXml( layer_node, document );
1882 
1883  writeStyleManager( layer_node, document );
1884 
1885  // renderer specific settings
1886  QString errorMsg;
1887  return writeSymbology( layer_node, document, errorMsg );
1888 } // bool QgsVectorLayer::writeXml
1889 
1890 
1891 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
1892 {
1893  readStyle( node, errorMessage );
1894 
1895  // process the attribute actions
1896  mActions->readXML( node );
1897 
1898  mEditFormConfig->readXml( node );
1899 
1900  QDomNode annotationFormNode = node.namedItem( "annotationform" );
1901  if ( !annotationFormNode.isNull() )
1902  {
1903  QDomElement e = annotationFormNode.toElement();
1904  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1905  }
1906 
1907  mAttributeAliasMap.clear();
1908  QDomNode aliasesNode = node.namedItem( "aliases" );
1909  if ( !aliasesNode.isNull() )
1910  {
1911  QDomElement aliasElem;
1912 
1913  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
1914  for ( int i = 0; i < aliasNodeList.size(); ++i )
1915  {
1916  aliasElem = aliasNodeList.at( i ).toElement();
1917 
1918  QString field;
1919  if ( aliasElem.hasAttribute( "field" ) )
1920  {
1921  field = aliasElem.attribute( "field" );
1922  }
1923  else
1924  {
1925  int index = aliasElem.attribute( "index" ).toInt();
1926 
1927  if ( index >= 0 && index < fields().count() )
1928  field = fields().at( index ).name();
1929  }
1930 
1931  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
1932  }
1933  }
1934 
1935  //Attributes excluded from WMS and WFS
1936  mExcludeAttributesWMS.clear();
1937  QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
1938  if ( !excludeWMSNode.isNull() )
1939  {
1940  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
1941  for ( int i = 0; i < attributeNodeList.size(); ++i )
1942  {
1943  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1944  }
1945  }
1946 
1947  mExcludeAttributesWFS.clear();
1948  QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
1949  if ( !excludeWFSNode.isNull() )
1950  {
1951  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
1952  for ( int i = 0; i < attributeNodeList.size(); ++i )
1953  {
1954  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1955  }
1956  }
1957 
1958  mEditFormConfig->readXml( node );
1959 
1960  mAttributeTableConfig.readXml( node );
1961 
1962  mConditionalStyles->readXml( node );
1963 
1964  return true;
1965 }
1966 
1967 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage )
1968 {
1969  emit readCustomSymbology( node.toElement(), errorMessage );
1970 
1971  if ( hasGeometryType() )
1972  {
1973  // try renderer v2 first
1974  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1975  if ( !rendererElement.isNull() )
1976  {
1977  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
1978  if ( !r )
1979  return false;
1980 
1981  setRendererV2( r );
1982  }
1983  else
1984  {
1986  if ( !r )
1988 
1989  setRendererV2( r );
1990  }
1991 
1992  QDomElement labelingElement = node.firstChildElement( "labeling" );
1993  if ( !labelingElement.isNull() )
1994  {
1997  }
1998 
1999  // get and set the display field if it exists.
2000  QDomNode displayFieldNode = node.namedItem( "displayfield" );
2001  if ( !displayFieldNode.isNull() )
2002  {
2003  QDomElement e = displayFieldNode.toElement();
2004  setDisplayField( e.text() );
2005  }
2006 
2007  // get and set the blend mode if it exists
2008  QDomNode blendModeNode = node.namedItem( "blendMode" );
2009  if ( !blendModeNode.isNull() )
2010  {
2011  QDomElement e = blendModeNode.toElement();
2012  setBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
2013  }
2014 
2015  // get and set the feature blend mode if it exists
2016  QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
2017  if ( !featureBlendModeNode.isNull() )
2018  {
2019  QDomElement e = featureBlendModeNode.toElement();
2020  setFeatureBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
2021  }
2022 
2023  // get and set the layer transparency if it exists
2024  QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
2025  if ( !layerTransparencyNode.isNull() )
2026  {
2027  QDomElement e = layerTransparencyNode.toElement();
2028  setLayerTransparency( e.text().toInt() );
2029  }
2030 
2031  // use scale dependent visibility flag
2032  QDomElement e = node.toElement();
2033  if ( mLabel )
2034  {
2035  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
2036  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
2037  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
2038  }
2039 
2040  // get the simplification drawing settings
2041  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( "simplifyDrawingHints", "1" ).toInt() ) );
2042  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( "simplifyAlgorithm", "0" ).toInt() ) );
2043  mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
2044  mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
2045  mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
2046 
2047  //also restore custom properties (for labeling-ng)
2048  readCustomProperties( node, "labeling" );
2049 
2050  // Test if labeling is on or off
2051  QDomNode labelnode = node.namedItem( "label" );
2052  QDomElement element = labelnode.toElement();
2053  int hasLabelsEnabled = element.text().toInt();
2055  if ( hasLabelsEnabled < 1 )
2056  {
2057  enableLabels( false );
2058  }
2059  else
2060  {
2061  enableLabels( true );
2062  }
2064 
2065  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
2066 
2067  if ( !labelattributesnode.isNull() && mLabel )
2068  {
2069  QgsDebugMsg( "calling readXML" );
2070  mLabel->readXML( labelattributesnode );
2071  }
2072 
2073  //diagram renderer and diagram layer settings
2074  delete mDiagramRenderer;
2075  mDiagramRenderer = nullptr;
2076  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
2077  if ( !singleCatDiagramElem.isNull() )
2078  {
2079  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2080  mDiagramRenderer->readXML( singleCatDiagramElem, this );
2081  }
2082  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
2083  if ( !linearDiagramElem.isNull() )
2084  {
2085  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2086  mDiagramRenderer->readXML( linearDiagramElem, this );
2087  }
2088 
2089  if ( mDiagramRenderer )
2090  {
2091  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
2092  if ( !diagramSettingsElem.isNull() )
2093  {
2094  delete mDiagramLayerSettings;
2095  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2096  mDiagramLayerSettings->readXML( diagramSettingsElem, this );
2097  }
2098  }
2099  }
2100  return true;
2101 }
2102 
2103 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2104 {
2105  ( void )writeStyle( node, doc, errorMessage );
2106 
2107  // FIXME
2108  // edittypes are written to the layerNode
2109  // by slot QgsEditorWidgetRegistry::writeMapLayer()
2110  // triggered by signal QgsProject::writeMapLayer()
2111  // still other editing settings are written here,
2112  // although they are not part of symbology either
2113 
2114  QDomElement afField = doc.createElement( "annotationform" );
2115  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
2116  afField.appendChild( afText );
2117  node.appendChild( afField );
2118 
2119  //attribute aliases
2120  if ( !mAttributeAliasMap.isEmpty() )
2121  {
2122  QDomElement aliasElem = doc.createElement( "aliases" );
2123  QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
2124  for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
2125  {
2126  int idx = fieldNameIndex( a_it.key() );
2127  if ( idx < 0 )
2128  continue;
2129 
2130  QDomElement aliasEntryElem = doc.createElement( "alias" );
2131  aliasEntryElem.setAttribute( "field", a_it.key() );
2132  aliasEntryElem.setAttribute( "index", idx );
2133  aliasEntryElem.setAttribute( "name", a_it.value() );
2134  aliasElem.appendChild( aliasEntryElem );
2135  }
2136  node.appendChild( aliasElem );
2137  }
2138 
2139  //exclude attributes WMS
2140  QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
2141  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2142  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2143  {
2144  QDomElement attrElem = doc.createElement( "attribute" );
2145  QDomText attrText = doc.createTextNode( *attWMSIt );
2146  attrElem.appendChild( attrText );
2147  excludeWMSElem.appendChild( attrElem );
2148  }
2149  node.appendChild( excludeWMSElem );
2150 
2151  //exclude attributes WFS
2152  QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
2153  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2154  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2155  {
2156  QDomElement attrElem = doc.createElement( "attribute" );
2157  QDomText attrText = doc.createTextNode( *attWFSIt );
2158  attrElem.appendChild( attrText );
2159  excludeWFSElem.appendChild( attrElem );
2160  }
2161  node.appendChild( excludeWFSElem );
2162 
2163  // add attribute actions
2164  mActions->writeXML( node, doc );
2165  mAttributeTableConfig.writeXml( node );
2166  mEditFormConfig->writeXml( node );
2167  mConditionalStyles->writeXml( node, doc );
2168 
2169  return true;
2170 }
2171 
2172 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage ) const
2173 {
2174  QDomElement mapLayerNode = node.toElement();
2175 
2176  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2177 
2178  if ( hasGeometryType() )
2179  {
2180  QDomElement rendererElement = mRendererV2->save( doc );
2181  node.appendChild( rendererElement );
2182 
2183  if ( mLabeling )
2184  {
2185  QDomElement labelingElement = mLabeling->save( doc );
2186  node.appendChild( labelingElement );
2187  }
2188 
2189  // use scale dependent visibility flag
2190  if ( mLabel )
2191  {
2192  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
2193  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
2194  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
2195  }
2196 
2197  // save the simplification drawing settings
2198  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
2199  mapLayerNode.setAttribute( "simplifyAlgorithm", QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2200  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
2201  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2202  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
2203 
2204  //save customproperties (for labeling ng)
2205  writeCustomProperties( node, doc );
2206 
2207  // add the blend mode field
2208  QDomElement blendModeElem = doc.createElement( "blendMode" );
2210  blendModeElem.appendChild( blendModeText );
2211  node.appendChild( blendModeElem );
2212 
2213  // add the feature blend mode field
2214  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
2216  featureBlendModeElem.appendChild( featureBlendModeText );
2217  node.appendChild( featureBlendModeElem );
2218 
2219  // add the layer transparency
2220  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
2221  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
2222  layerTransparencyElem.appendChild( layerTransparencyText );
2223  node.appendChild( layerTransparencyElem );
2224 
2225  // add the display field
2226  QDomElement dField = doc.createElement( "displayfield" );
2227  QDomText dFieldText = doc.createTextNode( displayField() );
2228  dField.appendChild( dFieldText );
2229  node.appendChild( dField );
2230 
2231  // add label node
2232  QDomElement labelElem = doc.createElement( "label" );
2233  QDomText labelText = doc.createTextNode( "" );
2234 
2236  if ( hasLabelsEnabled() )
2237  {
2238  labelText.setData( "1" );
2239  }
2240  else
2241  {
2242  labelText.setData( "0" );
2243  }
2245  labelElem.appendChild( labelText );
2246 
2247  node.appendChild( labelElem );
2248 
2249  // Now we get to do all that all over again for QgsLabel
2250 
2251  if ( mLabel )
2252  {
2253  QString fieldname = mLabel->labelField( QgsLabel::Text );
2254  if ( fieldname != "" )
2255  {
2256  dField = doc.createElement( "labelfield" );
2257  dFieldText = doc.createTextNode( fieldname );
2258  dField.appendChild( dFieldText );
2259  node.appendChild( dField );
2260  }
2261 
2262  mLabel->writeXML( node, doc );
2263  }
2264 
2265  if ( mDiagramRenderer )
2266  {
2267  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
2268  if ( mDiagramLayerSettings )
2269  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
2270  }
2271  }
2272  return true;
2273 }
2274 
2275 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2276 {
2277  // get the Name element
2278  QDomElement nameElem = node.firstChildElement( "Name" );
2279  if ( nameElem.isNull() )
2280  {
2281  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
2282  }
2283 
2284  if ( hasGeometryType() )
2285  {
2286  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
2287  if ( !r )
2288  return false;
2289 
2290  setRendererV2( r );
2291 
2292  // labeling
2293  readSldLabeling( node );
2294  }
2295  return true;
2296 }
2297 
2298 
2299 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2300 {
2301  Q_UNUSED( errorMessage );
2302 
2303  // store the Name element
2304  QDomElement nameNode = doc.createElement( "se:Name" );
2305  nameNode.appendChild( doc.createTextNode( name() ) );
2306  node.appendChild( nameNode );
2307 
2308  if ( hasGeometryType() )
2309  {
2310  node.appendChild( mRendererV2->writeSld( doc, name() ) );
2311  }
2312  return true;
2313 }
2314 
2315 
2317 {
2318  if ( !mEditBuffer || !mDataProvider )
2319  {
2320  return false;
2321  }
2322 
2323  updateExtents();
2324 
2325  bool result = mEditBuffer->changeGeometry( fid, geom );
2326 
2327  if ( result )
2328  updateExtents();
2329  return result;
2330 }
2331 
2332 
2333 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant& value, bool emitSignal )
2334 {
2335  Q_UNUSED( emitSignal );
2336  return changeAttributeValue( fid, field, value );
2337 }
2338 
2339 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2340 {
2341  if ( !mEditBuffer || !mDataProvider )
2342  return false;
2343 
2344  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2345 }
2346 
2348 {
2349  if ( !mEditBuffer || !mDataProvider )
2350  return false;
2351 
2352  return mEditBuffer->addAttribute( field );
2353 }
2354 
2356 {
2357  if ( attIndex < 0 || attIndex >= fields().count() )
2358  return;
2359 
2360  QString name = fields().at( attIndex ).name();
2361  if ( mAttributeAliasMap.contains( name ) )
2362  {
2363  mAttributeAliasMap.remove( name );
2364  emit layerModified();
2365  }
2366 }
2367 
2368 bool QgsVectorLayer::renameAttribute( int attIndex, const QString& newName )
2369 {
2370  if ( !mEditBuffer || !mDataProvider )
2371  return false;
2372 
2373  return mEditBuffer->renameAttribute( attIndex, newName );
2374 }
2375 
2376 void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString )
2377 {
2378  if ( attIndex < 0 || attIndex >= fields().count() )
2379  return;
2380 
2381  QString name = fields().at( attIndex ).name();
2382 
2383  mAttributeAliasMap.insert( name, aliasString );
2384  emit layerModified(); // TODO[MD]: should have a different signal?
2385 }
2386 
2387 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2388 {
2389  if ( attributeIndex < 0 || attributeIndex >= fields().count() )
2390  return QString();
2391 
2392  QString name = fields().at( attributeIndex ).name();
2393 
2394  return mAttributeAliasMap.value( name, QString() );
2395 }
2396 
2398 {
2399  QString displayName = attributeAlias( attributeIndex );
2400  if ( displayName.isEmpty() )
2401  {
2402  if ( attributeIndex >= 0 && attributeIndex < mUpdatedFields.count() )
2403  {
2404  displayName = mUpdatedFields.at( attributeIndex ).name();
2405  }
2406  }
2407  return displayName;
2408 }
2409 
2411 {
2412  if ( index < 0 || index >= fields().count() )
2413  return false;
2414 
2415  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2416  {
2417  removeExpressionField( index );
2418  return true;
2419  }
2420 
2421  if ( !mEditBuffer || !mDataProvider )
2422  return false;
2423 
2424  return mEditBuffer->deleteAttribute( index );
2425 }
2426 
2428 {
2429  bool deleted = false;
2430 
2431  // Remove multiple occurrences of same attribute
2432  attrs = attrs.toSet().toList();
2433 
2434  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2435 
2436  Q_FOREACH ( int attr, attrs )
2437  {
2438  if ( deleteAttribute( attr ) )
2439  {
2440  deleted = true;
2441  }
2442  }
2443 
2444  return deleted;
2445 }
2446 
2448 {
2449  if ( !mEditBuffer )
2450  return false;
2451 
2452  bool res = mEditBuffer->deleteFeature( fid );
2453  if ( res )
2454  {
2455  mSelectedFeatureIds.remove( fid ); // remove it from selection
2456  updateExtents();
2457  }
2458 
2459  return res;
2460 }
2461 
2463 {
2464  if ( !mEditBuffer )
2465  return false;
2466 
2467  bool res = mEditBuffer->deleteFeatures( fids );
2468 
2469  if ( res )
2470  {
2471  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2472  updateExtents();
2473  }
2474 
2475  return res;
2476 }
2477 
2479 {
2480  QgsAttributeList pkAttributesList;
2481 
2482  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2483  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2484  {
2485  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2486  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2487  pkAttributesList << i;
2488  }
2489 
2490  return pkAttributesList;
2491 }
2492 
2494 {
2495  return mDataProvider->featureCount() +
2496  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2497 }
2498 
2500 {
2501  mCommitErrors.clear();
2502 
2503  if ( !mDataProvider )
2504  {
2505  mCommitErrors << tr( "ERROR: no provider" );
2506  return false;
2507  }
2508 
2509  if ( !mEditBuffer )
2510  {
2511  mCommitErrors << tr( "ERROR: layer not editable" );
2512  return false;
2513  }
2514 
2515  emit beforeCommitChanges();
2516 
2517  bool success = mEditBuffer->commitChanges( mCommitErrors );
2518 
2519  if ( success )
2520  {
2521  delete mEditBuffer;
2522  mEditBuffer = nullptr;
2523  undoStack()->clear();
2524  emit editingStopped();
2525  }
2526  else
2527  {
2528  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2529  }
2530 
2531  if ( mCache )
2532  {
2533  mCache->deleteCachedGeometries();
2534  }
2535 
2536  updateFields();
2537  mDataProvider->updateExtents();
2538 
2539  mDataProvider->leaveUpdateMode();
2540 
2541  emit repaintRequested();
2542 
2543  return success;
2544 }
2545 
2547 {
2548  return mCommitErrors;
2549 }
2550 
2551 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2552 {
2553  if ( !mEditBuffer )
2554  {
2555  return false;
2556  }
2557 
2558  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2559  !mEditBuffer->mAddedFeatures.isEmpty() ||
2560  !mEditBuffer->mChangedGeometries.isEmpty();
2561 
2562  emit beforeRollBack();
2563 
2564  mEditBuffer->rollBack();
2565 
2566  if ( isModified() )
2567  {
2568  // new undo stack roll back method
2569  // old method of calling every undo could cause many canvas refreshes
2570  undoStack()->setIndex( 0 );
2571  }
2572 
2573  updateFields();
2574 
2575  if ( deleteBuffer )
2576  {
2577  delete mEditBuffer;
2578  mEditBuffer = nullptr;
2579  undoStack()->clear();
2580  }
2581  emit editingStopped();
2582 
2583  if ( mCache )
2584  {
2585  mCache->deleteCachedGeometries();
2586  }
2587 
2588  if ( rollbackExtent )
2589  updateExtents();
2590 
2591  mDataProvider->leaveUpdateMode();
2592 
2593  emit repaintRequested();
2594  return true;
2595 }
2596 
2598 {
2599  selectByIds( ids, SetSelection );
2600 }
2601 
2603 {
2604  return mSelectedFeatureIds.size();
2605 }
2606 
2608 {
2609  return mSelectedFeatureIds;
2610 }
2611 
2613 {
2614  QgsFeatureList features;
2615  QgsFeature f;
2616 
2617  if ( mSelectedFeatureIds.count() <= 8 )
2618  {
2619  // for small amount of selected features, fetch them directly
2620  // because request with FilterFids would go iterate over the whole layer
2621  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2622  {
2623  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2624  features << f;
2625  }
2626  }
2627  else
2628  {
2630 
2631  while ( it.nextFeature( f ) )
2632  {
2633  features.push_back( f );
2634  }
2635  }
2636 
2637  return features;
2638 }
2639 
2641 {
2642  if ( mSelectedFeatureIds.isEmpty() )
2643  return QgsFeatureIterator();
2644 
2645  if ( geometryType() == QGis::NoGeometry )
2647 
2648  if ( mSelectedFeatureIds.count() == 1 )
2649  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2650  else
2651  request.setFilterFids( mSelectedFeatureIds );
2652 
2653  return getFeatures( request );
2654 }
2655 
2656 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2657 {
2658  if ( !mEditBuffer || !mDataProvider )
2659  return false;
2660 
2661  bool res = mEditBuffer->addFeatures( features );
2662 
2663  if ( makeSelected )
2664  {
2665  QgsFeatureIds ids;
2666 
2667  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2668  ids << iter->id();
2669 
2670  selectByIds( ids );
2671  }
2672 
2673  updateExtents();
2674 
2675  return res;
2676 }
2677 
2678 
2679 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2680 {
2681  if ( !hasGeometryType() )
2682  return false;
2683 
2685  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2686 
2687  if ( result != 0 )
2688  {
2689  return false;
2690  }
2691 
2692  if ( snapResults.size() < 1 )
2693  {
2694  return false;
2695  }
2696 
2698  point.setX( snap_it.value().snappedVertex.x() );
2699  point.setY( snap_it.value().snappedVertex.y() );
2700  return true;
2701 }
2702 
2703 
2704 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2705  QMultiMap<double, QgsSnappingResult>& snappingResults,
2706  QgsSnapper::SnappingType snap_to )
2707 {
2708  if ( !hasGeometryType() )
2709  return 1;
2710 
2711  if ( snappingTolerance <= 0 || !mDataProvider )
2712  {
2713  return 1;
2714  }
2715 
2716  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2717  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2718  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2719 
2720  int n = 0;
2721  QgsFeature f;
2722 
2723  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2724  {
2725  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2726  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2727  {
2728  QgsGeometry* g = &( it.value() );
2729  if ( g->boundingBox().intersects( searchRect ) )
2730  {
2731  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2732  ++n;
2733  }
2734  }
2735  }
2736  else
2737  {
2738  // snapping outside cached area
2739 
2741  .setFilterRect( searchRect )
2743  .setSubsetOfAttributes( QgsAttributeList() ) );
2744 
2745  while ( fit.nextFeature( f ) )
2746  {
2747  snapToGeometry( startPoint, f.id(), f.constGeometry(), sqrSnappingTolerance, snappingResults, snap_to );
2748  ++n;
2749  }
2750  }
2751 
2752  return n == 0 ? 2 : 0;
2753 }
2754 
2755 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2756  QgsFeatureId featureId,
2757  const QgsGeometry* geom,
2758  double sqrSnappingTolerance,
2759  QMultiMap<double, QgsSnappingResult>& snappingResults,
2760  QgsSnapper::SnappingType snap_to ) const
2761 {
2762  if ( !geom )
2763  {
2764  return;
2765  }
2766 
2767  int atVertex, beforeVertex, afterVertex;
2768  double sqrDistVertexSnap, sqrDistSegmentSnap;
2769  QgsPoint snappedPoint;
2770  QgsSnappingResult snappingResultVertex;
2771  QgsSnappingResult snappingResultSegment;
2772 
2773  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2774  {
2775  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2776  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2777  {
2778  snappingResultVertex.snappedVertex = snappedPoint;
2779  snappingResultVertex.snappedVertexNr = atVertex;
2780  snappingResultVertex.beforeVertexNr = beforeVertex;
2781  if ( beforeVertex != -1 ) // make sure the vertex is valid
2782  {
2783  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2784  }
2785  snappingResultVertex.afterVertexNr = afterVertex;
2786  if ( afterVertex != -1 ) // make sure the vertex is valid
2787  {
2788  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2789  }
2790  snappingResultVertex.snappedAtGeometry = featureId;
2791  snappingResultVertex.layer = this;
2792  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2793  return;
2794  }
2795  }
2796  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2797  {
2798  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2799  {
2800  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, nullptr, crs().geographicFlag() ? 1e-12 : 1e-8 );
2801 
2802  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2803  {
2804  snappingResultSegment.snappedVertex = snappedPoint;
2805  snappingResultSegment.snappedVertexNr = -1;
2806  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2807  snappingResultSegment.afterVertexNr = afterVertex;
2808  snappingResultSegment.snappedAtGeometry = featureId;
2809  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2810  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2811  snappingResultSegment.layer = this;
2812  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2813  }
2814  }
2815  }
2816 }
2817 
2819 {
2820  QgsVectorLayerEditUtils utils( this );
2821  return utils.insertSegmentVerticesForSnap( snapResults );
2822 }
2823 
2824 
2826 {
2827  QgsDebugMsg( "----- Computing Coordinate System" );
2828 
2829  //
2830  // Get the layers project info and set up the QgsCoordinateTransform
2831  // for this layer
2832  //
2833 
2834  if ( hasGeometryType() )
2835  {
2836  // get CRS directly from provider
2837  setCrs( mDataProvider->crs() );
2838  }
2839  else
2840  {
2842  }
2843 }
2844 
2845 
2847 {
2848  return mDisplayField;
2849 }
2850 
2852 {
2853  mDisplayExpression = displayExpression;
2854 }
2855 
2857 {
2858  return mDisplayExpression;
2859 }
2860 
2862 {
2863  return ( mEditBuffer && mDataProvider );
2864 }
2865 
2867 {
2868  return geometryType() != QGis::NoGeometry;
2869 }
2870 
2872 {
2873  return mReadOnly;
2874 }
2875 
2876 bool QgsVectorLayer::setReadOnly( bool readonly )
2877 {
2878  // exit if the layer is in editing mode
2879  if ( readonly && mEditBuffer )
2880  return false;
2881 
2882  mReadOnly = readonly;
2883  return true;
2884 }
2885 
2887 {
2888  emit beforeModifiedCheck();
2889  return mEditBuffer && mEditBuffer->isModified();
2890 }
2891 
2893 {
2894  if ( idx < 0 || idx >= mUpdatedFields.count() )
2895  return Hidden;
2896 
2898  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
2900 }
2901 
2903 {
2904  if ( idx < 0 || idx >= mUpdatedFields.count() )
2905  return;
2906 
2908 
2910  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
2911 
2912  setEditorWidgetV2( idx, widgetType );
2913  setEditorWidgetV2Config( idx, cfg );
2915 }
2916 
2918 {
2919  mAnnotationForm = ui;
2920 }
2921 
2923 {
2925  return editorWidgetV2Config( idx );
2927 }
2928 
2930 {
2932  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2933  return RangeData(
2934  cfg.value( "Min" ),
2935  cfg.value( "Max" ),
2936  cfg.value( "Step" )
2937  );
2939 }
2940 
2942 {
2944  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
2946 }
2947 
2949 {
2951  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2952  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
2954 }
2955 
2957 {
2958  if ( !hasGeometryType() )
2959  return;
2960 
2961  if ( r != mRendererV2 )
2962  {
2963  delete mRendererV2;
2964  mRendererV2 = r;
2965  mSymbolFeatureCounted = false;
2966  mSymbolFeatureCountMap.clear();
2967 
2968  emit rendererChanged();
2969  emit styleChanged();
2970  }
2971 }
2972 
2974 {
2975  if ( !mDataProvider )
2976  {
2977  return;
2978  }
2979  if ( !mDataProvider->transaction() )
2980  {
2981  undoStack()->beginMacro( text );
2982  mEditCommandActive = true;
2983  emit editCommandStarted( text );
2984  }
2985 }
2986 
2988 {
2989  if ( !mDataProvider )
2990  {
2991  return;
2992  }
2993  if ( !mDataProvider->transaction() )
2994  {
2995  undoStack()->endMacro();
2996  mEditCommandActive = false;
2997  if ( !mDeletedFids.isEmpty() )
2998  {
2999  emit featuresDeleted( mDeletedFids );
3000  mDeletedFids.clear();
3001  }
3002  emit editCommandEnded();
3003  }
3004 }
3005 
3007 {
3008  if ( !mDataProvider )
3009  {
3010  return;
3011  }
3012  if ( !mDataProvider->transaction() )
3013  {
3014  undoStack()->endMacro();
3015  undoStack()->undo();
3016  mEditCommandActive = false;
3017  mDeletedFids.clear();
3018  emit editCommandDestroyed();
3019  }
3020 }
3021 
3022 
3023 void QgsVectorLayer::setCheckedState( int idx, const QString& checked, const QString& unchecked )
3024 {
3027  cfg["CheckedState"] = checked;
3028  cfg["UncheckedState"] = unchecked;
3029  setEditorWidgetV2Config( idx, cfg );
3031 }
3032 
3033 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
3034 {
3035  return fields().fieldNameIndex( fieldName );
3036 }
3037 
3039 {
3040  return mJoinBuffer && mJoinBuffer->addJoin( joinInfo );
3041 }
3042 
3044 {
3045  removeJoin( theLayerId );
3046 }
3047 
3048 bool QgsVectorLayer::removeJoin( const QString& joinLayerId )
3049 {
3050  bool res = false;
3051  if ( mJoinBuffer )
3052  {
3053  res = mJoinBuffer->removeJoin( joinLayerId );
3054  }
3055  return res;
3056 }
3057 
3059 {
3060  if ( mJoinBuffer )
3061  return mJoinBuffer->vectorJoins();
3062  else
3063  return QList< QgsVectorJoinInfo >();
3064 }
3065 
3067 {
3068  emit beforeAddingExpressionField( fld.name() );
3069  mExpressionFieldBuffer->addExpression( exp, fld );
3070  updateFields();
3071  int idx = mUpdatedFields.indexFromName( fld.name() );
3072  emit attributeAdded( idx );
3073  return idx;
3074 }
3075 
3077 {
3078  emit beforeRemovingExpressionField( index );
3079  int oi = mUpdatedFields.fieldOriginIndex( index );
3080  mExpressionFieldBuffer->removeExpression( oi );
3081  updateFields();
3082  emit attributeDeleted( index );
3083 }
3084 
3086 {
3087  int oi = mUpdatedFields.fieldOriginIndex( index );
3088  return mExpressionFieldBuffer->expressions().value( oi ).expression;
3089 }
3090 
3092 {
3093  int oi = mUpdatedFields.fieldOriginIndex( index );
3094  mExpressionFieldBuffer->updateExpression( oi, exp );
3095 }
3096 
3098 {
3099  if ( !mDataProvider )
3100  return;
3101 
3102  QgsFields oldFields = mUpdatedFields;
3103 
3104  mUpdatedFields = mDataProvider->fields();
3105 
3106  // added / removed fields
3107  if ( mEditBuffer )
3108  mEditBuffer->updateFields( mUpdatedFields );
3109 
3110  // joined fields
3111  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
3112  mJoinBuffer->updateFields( mUpdatedFields );
3113 
3114  if ( mExpressionFieldBuffer )
3115  mExpressionFieldBuffer->updateFields( mUpdatedFields );
3116 
3117  if ( oldFields != mUpdatedFields )
3118  {
3119  emit updatedFields();
3120  mEditFormConfig->setFields( mUpdatedFields );
3121  }
3122 }
3123 
3124 
3126 {
3127  if ( mJoinBuffer->containsJoins() )
3128  {
3129  mJoinBuffer->createJoinCaches();
3130  }
3131 }
3132 
3134 {
3135  uniqueValues.clear();
3136  if ( !mDataProvider )
3137  {
3138  return;
3139  }
3140 
3141  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3142  switch ( origin )
3143  {
3145  return;
3146 
3147  case QgsFields::OriginProvider: //a provider field
3148  {
3149  mDataProvider->uniqueValues( index, uniqueValues, limit );
3150 
3151  if ( mEditBuffer )
3152  {
3153  QSet<QString> vals;
3154  Q_FOREACH ( const QVariant& v, uniqueValues )
3155  {
3156  vals << v.toString();
3157  }
3158 
3159  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3160  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3161  {
3162  it.next();
3163  QVariant v = it.value().value( index );
3164  if ( v.isValid() )
3165  {
3166  QString vs = v.toString();
3167  if ( !vals.contains( vs ) )
3168  {
3169  vals << vs;
3170  uniqueValues << v;
3171  }
3172  }
3173  }
3174  }
3175 
3176  return;
3177  }
3178 
3179  case QgsFields::OriginEdit:
3180  // the layer is editable, but in certain cases it can still be avoided going through all features
3181  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3182  mEditBuffer->mAddedFeatures.isEmpty() &&
3183  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3184  mEditBuffer->mChangedAttributeValues.isEmpty() )
3185  {
3186  mDataProvider->uniqueValues( index, uniqueValues, limit );
3187  return;
3188  }
3189  FALLTHROUGH;
3190  //we need to go through each feature
3191  case QgsFields::OriginJoin:
3193  {
3194  QgsAttributeList attList;
3195  attList << index;
3196 
3198  .setFlags( QgsFeatureRequest::NoGeometry )
3199  .setSubsetOfAttributes( attList ) );
3200 
3201  QgsFeature f;
3202  QVariant currentValue;
3204  while ( fit.nextFeature( f ) )
3205  {
3206  currentValue = f.attribute( index );
3207  val.insert( currentValue.toString(), currentValue );
3208  if ( limit >= 0 && val.size() >= limit )
3209  {
3210  break;
3211  }
3212  }
3213 
3214  uniqueValues = val.values();
3215  return;
3216  }
3217  }
3218 
3219  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3220 }
3221 
3223 {
3224  if ( !mDataProvider )
3225  {
3226  return QVariant();
3227  }
3228 
3229  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3230 
3231  switch ( origin )
3232  {
3234  return QVariant();
3235 
3236  case QgsFields::OriginProvider: //a provider field
3237  return mDataProvider->minimumValue( index );
3238 
3239  case QgsFields::OriginEdit:
3240  {
3241  // the layer is editable, but in certain cases it can still be avoided going through all features
3242  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3243  mEditBuffer->mAddedFeatures.isEmpty() && !
3244  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3245  mEditBuffer->mChangedAttributeValues.isEmpty() )
3246  {
3247  return mDataProvider->minimumValue( index );
3248  }
3249  }
3250  FALLTHROUGH;
3251  // no choice but to go through all features
3253  case QgsFields::OriginJoin:
3254  {
3255  // we need to go through each feature
3256  QgsAttributeList attList;
3257  attList << index;
3258 
3260  .setFlags( QgsFeatureRequest::NoGeometry )
3261  .setSubsetOfAttributes( attList ) );
3262 
3263  QgsFeature f;
3265  double currentValue = 0;
3266  while ( fit.nextFeature( f ) )
3267  {
3268  currentValue = f.attribute( index ).toDouble();
3269  if ( currentValue < minimumValue )
3270  {
3271  minimumValue = currentValue;
3272  }
3273  }
3274  return QVariant( minimumValue );
3275  }
3276  }
3277 
3278  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3279  return QVariant();
3280 }
3281 
3283 {
3284  if ( !mDataProvider )
3285  {
3286  return QVariant();
3287  }
3288 
3289  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3290  switch ( origin )
3291  {
3293  return QVariant();
3294 
3295  case QgsFields::OriginProvider: //a provider field
3296  return mDataProvider->maximumValue( index );
3297 
3298  case QgsFields::OriginEdit:
3299  // the layer is editable, but in certain cases it can still be avoided going through all features
3300  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3301  mEditBuffer->mAddedFeatures.isEmpty() &&
3302  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3303  mEditBuffer->mChangedAttributeValues.isEmpty() )
3304  {
3305  return mDataProvider->maximumValue( index );
3306  }
3307 
3308  FALLTHROUGH;
3309  //no choice but to go through each feature
3310  case QgsFields::OriginJoin:
3312  {
3313  QgsAttributeList attList;
3314  attList << index;
3315 
3317  .setFlags( QgsFeatureRequest::NoGeometry )
3318  .setSubsetOfAttributes( attList ) );
3319 
3320  QgsFeature f;
3322  double currentValue = 0;
3323  while ( fit.nextFeature( f ) )
3324  {
3325  currentValue = f.attribute( index ).toDouble();
3326  if ( currentValue > maximumValue )
3327  {
3328  maximumValue = currentValue;
3329  }
3330  }
3331  return QVariant( maximumValue );
3332  }
3333  }
3334 
3335  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3336  return QVariant();
3337 }
3338 
3340  const QgsAggregateCalculator::AggregateParameters& parameters, QgsExpressionContext* context, bool* ok )
3341 {
3342  if ( ok )
3343  *ok = false;
3344 
3345  if ( !mDataProvider )
3346  {
3347  return QVariant();
3348  }
3349 
3350  // test if we are calculating based on a field
3351  int attrIndex = mUpdatedFields.fieldNameIndex( fieldOrExpression );
3352  if ( attrIndex >= 0 )
3353  {
3354  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
3355  // to the provider itself
3356  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( attrIndex );
3357  if ( origin == QgsFields::OriginProvider )
3358  {
3359  bool providerOk = false;
3360  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk );
3361  if ( providerOk )
3362  {
3363  // provider handled calculation
3364  if ( ok )
3365  *ok = true;
3366  return val;
3367  }
3368  }
3369  }
3370 
3371  // fallback to using aggregate calculator to determine aggregate
3372  QgsAggregateCalculator c( this );
3373  c.setParameters( parameters );
3374  return c.calculate( aggregate, fieldOrExpression, context, ok );
3375 }
3376 
3377 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly )
3378 {
3379  QList<QVariant> values;
3380 
3381  QScopedPointer<QgsExpression> expression;
3382  QgsExpressionContext context;
3383 
3384  int attrNum = fieldNameIndex( fieldOrExpression );
3385 
3386  if ( attrNum == -1 )
3387  {
3388  // try to use expression
3389  expression.reset( new QgsExpression( fieldOrExpression ) );
3393 
3394  if ( expression->hasParserError() || !expression->prepare( &context ) )
3395  {
3396  ok = false;
3397  return values;
3398  }
3399  }
3400 
3401  QgsFeature f;
3402  QStringList lst;
3403  if ( expression.isNull() )
3404  lst.append( fieldOrExpression );
3405  else
3406  lst = expression->referencedColumns();
3407 
3409  .setFlags(( expression && expression->needsGeometry() ) ?
3412  .setSubsetOfAttributes( lst, fields() );
3413 
3414  QgsFeatureIterator fit;
3415  if ( !selectedOnly )
3416  {
3417  fit = getFeatures( request );
3418  }
3419  else
3420  {
3421  fit = selectedFeaturesIterator( request );
3422  }
3423 
3424  // create list of non-null attribute values
3425  while ( fit.nextFeature( f ) )
3426  {
3427  if ( expression )
3428  {
3429  context.setFeature( f );
3430  QVariant v = expression->evaluate( &context );
3431  values << v;
3432  }
3433  else
3434  {
3435  values << f.attribute( attrNum );
3436  }
3437  }
3438  ok = true;
3439  return values;
3440 }
3441 
3442 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly, int* nullCount )
3443 {
3444  QList<double> values;
3445 
3446  if ( nullCount )
3447  *nullCount = 0;
3448 
3449  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3450  if ( !ok )
3451  return values;
3452 
3453  bool convertOk;
3454  Q_FOREACH ( const QVariant& value, variantValues )
3455  {
3456  double val = value.toDouble( &convertOk );
3457  if ( convertOk )
3458  values << val;
3459  else if ( value.isNull() )
3460  {
3461  if ( nullCount )
3462  *nullCount += 1;
3463  }
3464  }
3465  ok = true;
3466  return values;
3467 }
3468 
3469 
3472 {
3473  mFeatureBlendMode = featureBlendMode;
3474  emit featureBlendModeChanged( featureBlendMode );
3475  emit styleChanged();
3476 }
3477 
3479 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3480 {
3481  return mFeatureBlendMode;
3482 }
3483 
3486 {
3487  mLayerTransparency = layerTransparency;
3488  emit layerTransparencyChanged( layerTransparency );
3489  emit styleChanged();
3490 }
3491 
3494 {
3495  return mLayerTransparency;
3496 }
3497 
3498 
3499 
3500 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3501 {
3502  QDomElement element = node.toElement();
3503  if ( element.isNull() )
3504  return;
3505 
3506  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3507  if ( userStyleElem.isNull() )
3508  {
3509  QgsDebugMsg( "Info: UserStyle element not found." );
3510  return;
3511  }
3512 
3513  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3514  if ( featureTypeStyleElem.isNull() )
3515  {
3516  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3517  return;
3518  }
3519 
3520  // use last rule
3521  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3522  if ( ruleElem.isNull() )
3523  {
3524  QgsDebugMsg( "Info: Rule element not found." );
3525  return;
3526  }
3527 
3528  // use last text symbolizer
3529  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3530  if ( textSymbolizerElem.isNull() )
3531  {
3532  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3533  return;
3534  }
3535 
3536  // Label
3537  setCustomProperty( "labeling/enabled", false );
3538  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3539  if ( !labelElem.isNull() )
3540  {
3541  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3542  if ( !propertyNameElem.isNull() )
3543  {
3544  // enable labeling
3545  setCustomProperty( "labeling", "pal" );
3546  setCustomProperty( "labeling/enabled", true );
3547 
3548  // set labeling defaults
3549  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3550  setCustomProperty( "labeling/fontItalic", false );
3551  setCustomProperty( "labeling/fontSize", 10 );
3552  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3553  setCustomProperty( "labeling/fontBold", false );
3554  setCustomProperty( "labeling/fontUnderline", false );
3555  setCustomProperty( "labeling/textColorR", 0 );
3556  setCustomProperty( "labeling/textColorG", 0 );
3557  setCustomProperty( "labeling/textColorB", 0 );
3558  setCustomProperty( "labeling/textTransp", 0 );
3559  setCustomProperty( "labeling/bufferDraw", false );
3560  setCustomProperty( "labeling/bufferSize", 1 );
3561  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3562  setCustomProperty( "labeling/bufferColorR", 255 );
3563  setCustomProperty( "labeling/bufferColorG", 255 );
3564  setCustomProperty( "labeling/bufferColorB", 255 );
3565  setCustomProperty( "labeling/bufferTransp", 0 );
3566  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3567  setCustomProperty( "labeling/xOffset", 0 );
3568  setCustomProperty( "labeling/yOffset", 0 );
3569  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3570  setCustomProperty( "labeling/angleOffset", 0 );
3571 
3572  // label attribute
3573  QString labelAttribute = propertyNameElem.text();
3574  setCustomProperty( "labeling/fieldName", labelAttribute );
3575  setCustomProperty( "labeling/isExpression", false );
3576 
3577  int fieldIndex = fieldNameIndex( labelAttribute );
3578  if ( fieldIndex == -1 )
3579  {
3580  // label attribute is not in columns, check if it is an expression
3581  QgsExpression exp( labelAttribute );
3582  if ( !exp.hasEvalError() )
3583  {
3584  setCustomProperty( "labeling/isExpression", true );
3585  }
3586  else
3587  {
3588  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3589  }
3590  }
3591  }
3592  else
3593  {
3594  QgsDebugMsg( "Info: PropertyName element not found." );
3595  return;
3596  }
3597  }
3598  else
3599  {
3600  QgsDebugMsg( "Info: Label element not found." );
3601  return;
3602  }
3603 
3604  // Font
3605  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3606  if ( !fontElem.isNull() )
3607  {
3608  QString cssName;
3609  QString elemText;
3610  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3611  while ( !cssElem.isNull() )
3612  {
3613  cssName = cssElem.attribute( "name", "not_found" );
3614  if ( cssName != "not_found" )
3615  {
3616  elemText = cssElem.text();
3617  if ( cssName == "font-family" )
3618  {
3619  setCustomProperty( "labeling/fontFamily", elemText );
3620  }
3621  else if ( cssName == "font-style" )
3622  {
3623  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3624  }
3625  else if ( cssName == "font-size" )
3626  {
3627  bool ok;
3628  int fontSize = elemText.toInt( &ok );
3629  if ( ok )
3630  {
3631  setCustomProperty( "labeling/fontSize", fontSize );
3632  }
3633  }
3634  else if ( cssName == "font-weight" )
3635  {
3636  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3637  }
3638  else if ( cssName == "font-underline" )
3639  {
3640  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3641  }
3642  }
3643 
3644  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3645  }
3646  }
3647 
3648  // Fill
3649  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3650  if ( textColor.isValid() )
3651  {
3652  setCustomProperty( "labeling/textColorR", textColor.red() );
3653  setCustomProperty( "labeling/textColorG", textColor.green() );
3654  setCustomProperty( "labeling/textColorB", textColor.blue() );
3655  setCustomProperty( "labeling/textTransp", 100 - static_cast< int >( 100 * textColor.alphaF() ) );
3656  }
3657 
3658  // Halo
3659  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3660  if ( !haloElem.isNull() )
3661  {
3662  setCustomProperty( "labeling/bufferDraw", true );
3663  setCustomProperty( "labeling/bufferSize", 1 );
3664 
3665  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3666  if ( !radiusElem.isNull() )
3667  {
3668  bool ok;
3669  double bufferSize = radiusElem.text().toDouble( &ok );
3670  if ( ok )
3671  {
3672  setCustomProperty( "labeling/bufferSize", bufferSize );
3673  }
3674  }
3675 
3676  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3677  if ( bufferColor.isValid() )
3678  {
3679  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3680  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3681  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3682  setCustomProperty( "labeling/bufferTransp", 100 - static_cast< int >( 100 * bufferColor.alphaF() ) );
3683  }
3684  }
3685 
3686  // LabelPlacement
3687  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3688  if ( !labelPlacementElem.isNull() )
3689  {
3690  // PointPlacement
3691  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3692  if ( !pointPlacementElem.isNull() )
3693  {
3694  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3695 
3696  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3697  if ( !displacementElem.isNull() )
3698  {
3699  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3700  if ( !displacementXElem.isNull() )
3701  {
3702  bool ok;
3703  double xOffset = displacementXElem.text().toDouble( &ok );
3704  if ( ok )
3705  {
3706  setCustomProperty( "labeling/xOffset", xOffset );
3707  }
3708  }
3709  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3710  if ( !displacementYElem.isNull() )
3711  {
3712  bool ok;
3713  double yOffset = displacementYElem.text().toDouble( &ok );
3714  if ( ok )
3715  {
3716  setCustomProperty( "labeling/yOffset", yOffset );
3717  }
3718  }
3719  }
3720 
3721  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
3722  if ( !rotationElem.isNull() )
3723  {
3724  bool ok;
3725  double rotation = rotationElem.text().toDouble( &ok );
3726  if ( ok )
3727  {
3728  setCustomProperty( "labeling/angleOffset", rotation );
3729  }
3730  }
3731  }
3732  }
3733 }
3734 
3736 {
3737  QgsAttributeTableConfig config = mAttributeTableConfig;
3738 
3739  if ( config.isEmpty() )
3740  config.update( fields() );
3741 
3742  return config;
3743 }
3744 
3746 {
3747  if ( mAttributeTableConfig != attributeTableConfig )
3748  {
3749  mAttributeTableConfig = attributeTableConfig;
3750  emit configChanged();
3751  }
3752 }
3753 
3755 {
3756  if ( !mDiagramLayerSettings )
3757  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3758  *mDiagramLayerSettings = s;
3759 }
3760 
3762 {
3763  QString myMetadata = "<html><body>";
3764 
3765  //-------------
3766 
3767  myMetadata += "<p class=\"subheaderglossy\">";
3768  myMetadata += tr( "General" );
3769  myMetadata += "</p>\n";
3770 
3771  // data comment
3772  if ( !( dataComment().isEmpty() ) )
3773  {
3774  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
3775  myMetadata += "<p>";
3776  myMetadata += dataComment();
3777  myMetadata += "</p>\n";
3778  }
3779 
3780  //storage type
3781  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
3782  myMetadata += "<p>";
3783  myMetadata += storageType();
3784  myMetadata += "</p>\n";
3785 
3786  if ( dataProvider() )
3787  {
3788  //provider description
3789  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
3790  myMetadata += "<p>";
3791  myMetadata += dataProvider()->description().replace( '\n', "<br>" );
3792  myMetadata += "</p>\n";
3793  }
3794 
3795  // data source
3796  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
3797  myMetadata += "<p>";
3798  myMetadata += publicSource();
3799  myMetadata += "</p>\n";
3800 
3801  //geom type
3802 
3804 
3805  if ( type < 0 || type > QGis::NoGeometry )
3806  {
3807  QgsDebugMsg( "Invalid vector type" );
3808  }
3809  else
3810  {
3811  QString typeString( QGis::vectorGeometryType( geometryType() ) );
3812  QString wkbTypeString = QgsWKBTypes::displayString( QGis::fromOldWkbType( mWkbType ) );
3813 
3814  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
3815  myMetadata += QString( "<p>%1 (WKB type: \"%2\")</p>\n" ).arg( typeString, wkbTypeString );
3816  }
3817 
3818  QgsAttributeList pkAttrList = pkAttributeList();
3819  if ( !pkAttrList.isEmpty() )
3820  {
3821  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
3822  myMetadata += "<p>";
3823  Q_FOREACH ( int idx, pkAttrList )
3824  {
3825  myMetadata += fields().at( idx ).name() + ' ';
3826  }
3827  myMetadata += "</p>\n";
3828  }
3829 
3830 
3831  //feature count
3832  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
3833  myMetadata += "<p>";
3834  myMetadata += QString::number( featureCount() );
3835  myMetadata += "</p>\n";
3836  //capabilities
3837  myMetadata += "<p class=\"glossy\">" + tr( "Capabilities of this layer" ) + "</p>\n";
3838  myMetadata += "<p>";
3839  myMetadata += capabilitiesString();
3840  myMetadata += "</p>\n";
3841 
3842  //-------------
3843 
3844  QgsRectangle myExtent = extent();
3845  myMetadata += "<p class=\"subheaderglossy\">";
3846  myMetadata += tr( "Extents" );
3847  myMetadata += "</p>\n";
3848 
3849  //extents in layer cs TODO...maybe make a little nested table to improve layout...
3850  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
3851  myMetadata += "<p>";
3852  // Try to be a bit clever over what number format we use for the
3853  // extents. Some people don't like it using scientific notation when the
3854  // numbers get large, but for small numbers this is the more practical
3855  // option (so we can't force the format to 'f' for all values).
3856  // The scheme:
3857  // - for all numbers with more than 5 digits, force non-scientific notation
3858  // and 2 digits after the decimal point.
3859  // - for all smaller numbers let the OS decide which format to use (it will
3860  // generally use non-scientific unless the number gets much less than 1).
3861 
3862  if ( !myExtent.isEmpty() )
3863  {
3864  QString xMin, yMin, xMax, yMax;
3865  double changeoverValue = 99999; // The 'largest' 5 digit number
3866  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
3867  {
3868  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
3869  }
3870  else
3871  {
3872  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
3873  }
3874  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
3875  {
3876  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
3877  }
3878  else
3879  {
3880  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
3881  }
3882  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
3883  {
3884  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
3885  }
3886  else
3887  {
3888  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
3889  }
3890  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
3891  {
3892  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
3893  }
3894  else
3895  {
3896  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
3897  }
3898 
3899  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3900  .arg( xMin, yMin, xMax, yMax );
3901  }
3902  else
3903  {
3904  myMetadata += tr( "unknown extent" );
3905  }
3906 
3907  myMetadata += "</p>\n";
3908 
3909  //extents in project cs
3910 
3911  try
3912  {
3913 #if 0
3914  // TODO: currently disabled, will revisit later [MD]
3915  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
3916  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3917  myMetadata += "<p>";
3918  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3919  .arg( myProjectedExtent.xMinimum() )
3920  .arg( myProjectedExtent.yMinimum() )
3921  .arg( myProjectedExtent.xMaximum() )
3922  .arg( myProjectedExtent.yMaximum() );
3923  myMetadata += "</p>\n";
3924 #endif
3925 
3926  //
3927  // Display layer spatial ref system
3928  //
3929  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
3930  myMetadata += "<p>";
3931  myMetadata += crs().toProj4().replace( '"', " \"" );
3932  myMetadata += "</p>\n";
3933 
3934  //
3935  // Display project (output) spatial ref system
3936  //
3937 #if 0
3938  // TODO: disabled for now, will revisit later [MD]
3939  //myMetadata += "<tr><td bgcolor=\"gray\">";
3940  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
3941  myMetadata += "<p>";
3942  myMetadata += coordinateTransform->destCRS().toProj4().replace( '"', " \"" );
3943  myMetadata += "</p>\n";
3944 #endif
3945  }
3946  catch ( QgsCsException &cse )
3947  {
3948  Q_UNUSED( cse );
3949  QgsDebugMsg( cse.what() );
3950 
3951  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3952  myMetadata += "<p>";
3953  myMetadata += tr( "(Invalid transformation of layer extents)" );
3954  myMetadata += "</p>\n";
3955 
3956  }
3957 
3958 #if 0
3959  //
3960  // Add the info about each field in the attribute table
3961  //
3962  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
3963  myMetadata += "<p>";
3964 
3965  // Start a nested table in this trow
3966  myMetadata += "<table width=\"100%\">";
3967  myMetadata += "<tr><th>";
3968  myMetadata += tr( "Field" );
3969  myMetadata += "</th>";
3970  myMetadata += "<th>";
3971  myMetadata += tr( "Type" );
3972  myMetadata += "</th>";
3973  myMetadata += "<th>";
3974  myMetadata += tr( "Length" );
3975  myMetadata += "</th>";
3976  myMetadata += "<th>";
3977  myMetadata += tr( "Precision" );
3978  myMetadata += "</th>";
3979  myMetadata += "<th>";
3980  myMetadata += tr( "Comment" );
3981  myMetadata += "</th>";
3982 
3983  //get info for each field by looping through them
3984  const QgsFields& myFields = pendingFields();
3985  for ( int i = 0, n = myFields.size(); i < n; ++i )
3986  {
3987  const QgsField& myField = fields[i];
3988 
3989  myMetadata += "<tr><td>";
3990  myMetadata += myField.name();
3991  myMetadata += "</td>";
3992  myMetadata += "<td>";
3993  myMetadata += myField.typeName();
3994  myMetadata += "</td>";
3995  myMetadata += "<td>";
3996  myMetadata += QString( "%1" ).arg( myField.length() );
3997  myMetadata += "</td>";
3998  myMetadata += "<td>";
3999  myMetadata += QString( "%1" ).arg( myField.precision() );
4000  myMetadata += "</td>";
4001  myMetadata += "<td>";
4002  myMetadata += QString( "%1" ).arg( myField.comment() );
4003  myMetadata += "</td></tr>";
4004  }
4005 
4006  //close field list
4007  myMetadata += "</table>"; //end of nested table
4008 #endif
4009 
4010  myMetadata += "</body></html>";
4011  return myMetadata;
4012 }
4013 
4015 {
4016  mSymbolFeatureCounted = false;
4017 }
4018 
4019 void QgsVectorLayer::onJoinedFieldsChanged()
4020 {
4021  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4022  updateFields();
4023 }
4024 
4025 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4026 {
4027  if ( mEditCommandActive )
4028  mDeletedFids << fid;
4029  else
4030  emit featuresDeleted( QgsFeatureIds() << fid );
4031 
4032  emit featureDeleted( fid );
4033 }
4034 
4036 {
4037  if ( mEditFormConfig->widgetType( idx ) == "ValueRelation" )
4038  {
4039  QgsEditorWidgetConfig cfg = mEditFormConfig->widgetConfig( idx );
4040 
4041  return ValueRelationData( cfg.value( "Layer" ).toString(),
4042  cfg.value( "Key" ).toString(),
4043  cfg.value( "Value" ).toString(),
4044  cfg.value( "AllowNull" ).toBool(),
4045  cfg.value( "OrderByValue" ).toBool(),
4046  cfg.value( "AllowMulti" ).toBool(),
4047  cfg.value( "FilterExpression" ).toString()
4048  );
4049  }
4050  else
4051  {
4052  return ValueRelationData();
4053  }
4054 }
4055 
4057 {
4058  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4059 }
4060 
4062 {
4063  QDomElement elem = doc.createElement( "attributeEditorContainer" );
4064  elem.setAttribute( "name", mName );
4065  elem.setAttribute( "columnCount", mColumnCount );
4066  elem.setAttribute( "groupBox", mIsGroupBox ? 1 : 0 );
4067 
4068  Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
4069  {
4070  elem.appendChild( child->toDomElement( doc ) );
4071  }
4072  return elem;
4073 }
4074 
4076 {
4077  mChildren.append( widget );
4078 }
4079 
4081 {
4082  mName = name;
4083 }
4084 
4086 {
4088 
4089  Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
4090  {
4091  if ( elem->type() == type )
4092  {
4093  results.append( elem );
4094  }
4095 
4096  if ( elem->type() == AeTypeContainer )
4097  {
4098  QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
4099  if ( cont )
4100  results += cont->findElements( type );
4101  }
4102  }
4103 
4104  return results;
4105 }
4106 
4108 {
4109  QDomElement elem = doc.createElement( "attributeEditorField" );
4110  elem.setAttribute( "name", mName );
4111  elem.setAttribute( "index", mIdx );
4112  return elem;
4113 }
4114 
4116 {
4118  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4119  if ( !myLib )
4120  {
4121  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4122  return -1;
4123  }
4124  listStyles_t* listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
4125 
4126  if ( !listStylesExternalMethod )
4127  {
4128  delete myLib;
4129  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "listStyles" );
4130  return -1;
4131  }
4132 
4133  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
4134 }
4135 
4137 {
4139  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4140  if ( !myLib )
4141  {
4142  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4143  return QObject::tr( "" );
4144  }
4145  getStyleById_t* getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
4146 
4147  if ( !getStyleByIdMethod )
4148  {
4149  delete myLib;
4150  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "getStyleById" );
4151  return QObject::tr( "" );
4152  }
4153 
4154  return getStyleByIdMethod( mDataSource, styleId, msgError );
4155 }
4156 
4157 
4158 void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& description,
4159  bool useAsDefault, const QString& uiFileContent, QString &msgError )
4160 {
4161 
4162  QString sldStyle, qmlStyle;
4164  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4165  if ( !myLib )
4166  {
4167  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4168  return;
4169  }
4170  saveStyle_t* saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4171 
4172  if ( !saveStyleExternalMethod )
4173  {
4174  delete myLib;
4175  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "saveStyle" );
4176  return;
4177  }
4178 
4179  QDomDocument qmlDocument, sldDocument;
4180  this->exportNamedStyle( qmlDocument, msgError );
4181  if ( !msgError.isNull() )
4182  {
4183  return;
4184  }
4185  qmlStyle = qmlDocument.toString();
4186 
4187  this->exportSldStyle( sldDocument, msgError );
4188  if ( !msgError.isNull() )
4189  {
4190  return;
4191  }
4192  sldStyle = sldDocument.toString();
4193 
4194  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4195  description, uiFileContent, useAsDefault, msgError );
4196 }
4197 
4198 
4199 
4200 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
4201 {
4202  return loadNamedStyle( theURI, theResultFlag, false );
4203 }
4204 
4205 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
4206 {
4207  QgsDataSourceURI dsUri( theURI );
4208  if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
4209  {
4211  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4212  if ( myLib )
4213  {
4214  loadStyle_t* loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4215  if ( loadStyleExternalMethod )
4216  {
4217  QString qml, errorMsg;
4218  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4219  if ( !qml.isEmpty() )
4220  {
4222  theResultFlag = applyNamedStyle( qml, errorMsg );
4224  return QObject::tr( "Loaded from Provider" );
4225  }
4226  }
4227  }
4228  }
4229 
4230  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
4231 }
4232 
4233 bool QgsVectorLayer::applyNamedStyle( const QString& namedStyle, QString& errorMsg )
4234 {
4235  QDomDocument myDocument( "qgis" );
4236  myDocument.setContent( namedStyle );
4237 
4238  return importNamedStyle( myDocument, errorMsg );
4239 }
4240 
4241 
4243 {
4244  QDomElement elem = doc.createElement( "attributeEditorRelation" );
4245  elem.setAttribute( "name", mName );
4246  elem.setAttribute( "relation", mRelation.id() );
4247  return elem;
4248 }
4249 
4251 {
4252  mRelation = relationManager->relation( mRelationId );
4253  return mRelation.isValid();
4254 }
4255 
4257 {
4258  if ( mDataProvider )
4259  {
4260  return mDataProvider->layerDependencies();
4261  }
4262  return QSet<QString>();
4263 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
Q_DECL_DEPRECATED bool deleteVertex(QgsFeatureId atFeatureId, int atVertex)
Deletes a vertex from a feature.
QObject * child(const char *objName, const char *inheritsClass, bool recursiveSearch) const
void setExtent(const QgsRectangle &rect) override
Set the extent.
bool draw(QgsRenderContext &rendererContext) override
Draws the layer.
virtual QString subsetString()
Get the string (typically sql) used to define a subset of the layer.
virtual Q_DECL_DEPRECATED bool applyNamedStyle(const QString &namedStyle, QString &errorMsg)
Will load a named style from a provided QML string.
Class for parsing and evaluation of expressions (formerly called "search strings").
void updateFields()
Assembles mUpdatedFields considering provider fields, joined fields and added fields.
Q_DECL_DEPRECATED int removePolygonIntersections(QgsGeometry *geom, const QgsFeatureIds &ignoreFeatures=QgsFeatureIds())
Changes the specified geometry such that it has no intersections with other polygon (or multipolygon)...
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
bool isValid() const
Returns the validity of this relation.
void featuresDeleted(const QgsFeatureIds &fids)
Emitted when features have been deleted.
void selectAll()
Select all the features.
QDomNodeList elementsByTagName(const QString &tagname) const
QString database() const
Returns the database.
bool intersects(const QgsRectangle &rect) const
returns true when rectangle intersects with other rectangle
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
#define RENDERER_TAG_NAME
Definition: qgsrendererv2.h:49
static unsigned index
bool addJoin(const QgsVectorJoinInfo &joinInfo)
Joins another vector layer to this layer.
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
bool init(QgsRelationManager *relManager)
Initializes the relation from the id.
const QList< QgsVectorJoinInfo > vectorJoins() const
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
bool isEmpty() const
test if rectangle is empty.
iterator insert(const Key &key, const T &value)
int insertSegmentVerticesForSnap(const QList< QgsSnappingResult > &snapResults)
Inserts vertices to the snapped segments.
void update(const QgsFields &fields)
Update the configuration with the given fields.
bool readSymbology(const QDomNode &node, QString &errorMessage) override
Read the symbology for the current layer from the Dom node supplied.
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:201
float threshold() const
Gets the simplification threshold of the vector layer managed.
QgsFeatureList selectedFeatures()
Get a copy of the user-selected features.
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:97
void setName(const QString &name)
Change the name of this container.
virtual bool writeXml(QDomNode &layer_node, QDomDocument &doc) override
Write vector layer specific state to project file Dom node.
QStringList referencedColumns() const
Get list of columns referenced by the expression.
This is an abstract base class for any elements of a drag and drop form.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
virtual bool mustStop() const
return true if the iterator must stop as soon as possible
GeometryType
Definition: qgis.h:115
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith="")
Read custom properties from project file.
qreal alphaF() const
QString name() const
Get the display name of the layer.
void selectByRect(QgsRectangle &rect, SelectBehaviour behaviour=SetSelection)
Select features found within the search rectangle (in layer&#39;s coordinates)
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
QDomNode appendChild(const QDomNode &newChild)
void beforeRollBack()
Is emitted, before changes are rolled back.
void setSimplifyAlgorithm(const SimplifyAlgorithm &simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
bool readStyle(const QDomNode &node, QString &errorMessage) override
Read the style for the current layer from the Dom node supplied.
Use exact geometry intersection (slower) instead of bounding boxes.
static QgsFeatureRendererV2 * loadSld(const QDomNode &node, QGis::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
void setMaximum(int maximum)
void push_back(const T &value)
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
QVariant maximumValue(int index)
Returns maximum value for an attribute column or invalid variant in case of error.
Modify current selection to include only select features which match.
Renders the diagrams for all features with the same settings.
QString capabilitiesString() const
Returns the above in friendly format.
Q_DECL_DEPRECATED const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
QString attribute(const QString &name, const QString &defValue) const
bool hasPendingEvents()
void setWindowModality(Qt::WindowModality windowModality)
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:202
int addTopologicalPoints(const QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
void beginMacro(const QString &text)
void layerTransparencyChanged(int layerTransparency)
Signal emitted when setLayerTransparency() is called.
QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures(QProgressDialog *dialog)
Constructor.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:439
QgsFields fields() const
Returns the list of fields of this layer.
void clear()
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
QString toString(int indent) const
int fieldNameIndex(const QString &fieldName) const
Look up field&#39;s index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:534
double rendererScale() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
friend class QgsVectorLayerFeatureSource
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported...
double closestSegmentWithContext(const QgsPoint &point, QgsPoint &minDistPoint, int &afterVertex, double *leftOf=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
void 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.
void setRendererV2(QgsFeatureRendererV2 *r)
Set renderer which will be invoked to represent this layer.
int size() const
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
bool startEditing()
Make layer editable.
const_iterator constBegin() const
void setRendererScale(double scale)
const T & at(int i) const
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
VertexMarkerType
Editing vertex markers.
void removeExpressionField(int index)
Remove an expression field.
void setFeatureBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering each feature.
Q_DECL_DEPRECATED void select(QgsRectangle &rect, bool addToSelection)
Select features found within the search rectangle (in layer&#39;s coordinates)
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:515
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:104
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
int makeDifference(const QgsGeometry *other)
Changes this geometry such that it does not intersect the other geometry.
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
static QgsMapRenderer::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
Q_DECL_DEPRECATED QString dateFormat(int idx)
Access date format.
SimplifyHint
Simplification flags for fast rendering of features.
Utility class for calculating aggregates for a field (or expression) over the features from a vector ...
bool deleteAttributes(QList< int > attrs)
Deletes a list of attribute fields (but does not commit it)
void setLabeling(QgsAbstractVectorLayerLabeling *labeling)
Set labeling configuration.
void readCustomSymbology(const QDomElement &element, QString &errorMessage)
Signal emitted whenever the symbology (QML-file) for this layer is being read.
QDomElement nextSiblingElement(const QString &tagName) const
QgsConditionalLayerStyles * conditionalStyles() const
Return the conditional styles that are set for this layer.
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it)
int insertSegmentVerticesForSnap(const QList< QgsSnappingResult > &snapResults)
Inserts vertices to the snapped segments.
Q_DECL_DEPRECATED QMap< QString, QVariant > valueMap(int idx)
Access value map.
T value() const
void configChanged()
Emitted whenever the configuration is changed.
Container of fields for a vector layer.
Definition: qgsfield.h:193
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setDiagramRenderer(QgsDiagramRendererV2 *r)
Sets diagram rendering object (takes ownership)
void setLayerTransparency(int layerTransparency)
Set the transparency for the vector layer.
QSet< T > & subtract(const QSet< T > &other)
ValueRelationData valueRelation(int idx)
Access value relation widget data.
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer...
virtual QSet< QString > layerDependencies() const
Get the list of layer ids on which this layer depends.
static const char * vectorGeometryType(GeometryType type)
description strings for geometry types
Definition: qgis.cpp:441
WkbType
Used for symbology operations.
Definition: qgis.h:61
const QgsRectangle & extent() const
QSet< T > toSet() const
void remAttributeAlias(int attIndex)
Removes an alias (a display name) for attributes to display in dialogs.
QList< double > getDoubleValues(const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr)
Fetches all double values from a specified field name or expression.
QString comment() const
Returns the field comment.
Definition: qgsfield.cpp:109
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:40
Set selection, removing any existing selection.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
virtual QList< QString > usedAttributes()=0
Returns a set of attributes required for this renderer.
void selectByIds(const QgsFeatureIds &ids, SelectBehaviour behaviour=SetSelection)
Select matching features using a list of feature IDs.
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:200
Edit operation resulted in an empty geometry.
QString expressionField(int index)
Returns the expressoin used for a given expression field.
int addPart(const QList< QgsPoint > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QString & remove(int position, int n)
QList< QgsRelation > referencingRelations(int idx)
Get relations, where the foreign key is on this layer.
bool addFeature(QgsFeature &feature, bool alsoUpdateExtent=true)
Adds a feature.
void drawLine(const QLineF &line)
static const int EditingCapabilities
Bitmask of all provider&#39;s editing capabilities.
virtual ~QgsVectorLayer()
Destructor.
virtual QgsCurveV2 * clone() const override=0
Clones the geometry by performing a deep copy.
Q_DECL_DEPRECATED void setCheckedState(int idx, const QString &checked, const QString &notChecked)
Set string representing &#39;true&#39; for a checkbox.
const QString displayExpression()
Get the preview expression, used to create a human readable preview string.
void beforeCommitChanges()
Is emitted, before changes are commited to the data provider.
virtual Q_DECL_DEPRECATED bool isReadOnly() const override
Returns true if the provider is in read-only mode.
void chop(int n)
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
This signal is emitted, when features are deleted from the provider.
double toDouble(bool *ok) const
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.
QVariant minimumValue(int index)
Returns minimum value for an attribute column or invalid variant in case of error.
void selectByExpression(const QString &expression, SelectBehaviour behaviour=SetSelection)
Select matching features using an expression.
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Insert a new vertex before the given vertex number, in the given ring, item (first number is index 0)...
void setSimplifyHints(const SimplifyHints &simplifyHints)
Sets the simplification hints of the vector layer managed.
virtual Q_DECL_DEPRECATED bool willRenderFeature(QgsFeature &feat)
Returns whether the renderer will render a feature or not.
QString tr(const char *sourceText, const char *disambiguation, int n)
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
QString readPath(QString filename) const
Turn filename read from the project file to an absolute path.
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written. ...
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:773
void invertSelection()
Select not selected features and deselect selected ones.
void setParameters(const AggregateParameters &parameters)
Sets all aggregate parameters from a parameter bundle.
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
it has not been specified where the field comes from
Definition: qgsfield.h:199
int splitFeatures(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
int size() const
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
Needs to be called when a new render cycle is started.
bool isNull() const
virtual void updateExtents()
Update the extents for the layer.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
void removeSelection()
Clear selection.
Manages joined fields for a vector layer.
void reset(T *other)
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
virtual void stopRender(QgsRenderContext &context)=0
Needs to be called when a render cycle has finished to clean up.
void clear()
static QString capitaliseLayerName(const QString &name)
A convenience function to (un)capitalise the layer name.
Interface that can be optionaly attached to an iterator so its nextFeature() implementaton can check ...
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
QDomElement toElement() const
virtual QDomElement toDomElement(QDomDocument &doc) const override
Will serialize this containers information into a QDomElement for saving it in an XML file...
Q_DECL_DEPRECATED void setEditorWidgetV2(int attrIdx, const QString &widgetType)
Set the editor widget type for a field.
void setData(const QString &v)
int indexIn(const QString &str, int offset, CaretMode caretMode) const
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.
static QgsWKBTypes::Type fromOldWkbType(QGis::WkbType type)
Converts from old (pre 2.10) WKB type (OGR) to new WKB type.
Definition: qgis.cpp:106
SnappingType
Snap to vertex, to segment or both.
Definition: qgssnapper.h:67
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QString encoding() const
Get encoding which is used for accessing data.
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Return new instance of QgsMapLayerRenderer that will be used for rendering of given context...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
void setValue(int progress)
QgsFields pendingFields() const
Returns the list of fields of this layer.
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Update the data source of the layer.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
int elapsed() const
virtual QDomElement toDomElement(QDomDocument &doc) const override
Will serialize this elements information into a QDomElement for saving it in an XML file...
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QString number(int n, int base)
int count(const T &value) const
QVariantMap QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
void append(const T &value)
void setIndex(int idx)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:94
void deselect(const QgsFeatureId featureId)
Deselect feature by its ID.
void layerDeleted()
TODO QGIS3: remove in favor of QObject::destroyed.
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
QString & insert(int position, QChar ch)
#define FALLTHROUGH
Definition: qgis.h:539
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
QgsRectangle extent() override
Return the extent of the layer.
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any).
bool rollBack(bool deleteBuffer=true)
Stop editing and discard the edits.
QString text() const
int toInt(bool *ok) const
bool isNull() const
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
const QgsAbstractVectorLayerLabeling * labeling() const
Access to labeling configuration.
QgsDataProvider * provider(const QString &providerKey, const QString &dataSource)
Create an instance of the provider.
bool hasAttribute(const QString &name) const
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
QString capabilitiesString() const
Capabilities for this layer in a friendly format.
QgsRelation relation(const QString &id) const
Get access to a relation by its id.
The attribute value should not be shown in the attribute form.
void featureBlendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when setFeatureBlendMode() is called.
virtual QString dataComment() const
Return a short comment for the data that this provider is providing access to (e.g.
Represents the result of a snapping operation.
Definition: qgssnapper.h:36
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
int red() const
void setPen(const QColor &color)
QStringList capturedTexts() const
void drawEllipse(const QRectF &rectangle)
void setAttribute(const QString &name, const QString &value)
int addTopologicalPoints(const QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
Q_DECL_DEPRECATED EditType editType(int idx)
Get edit type.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists).
int snapWithContext(const QgsPoint &startPoint, double snappingTolerance, QMultiMap< double, QgsSnappingResult > &snappingResults, QgsSnapper::SnappingType snap_to)
Snaps to segment or vertex within given tolerance.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:84
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage) const override
Write just the style information for the layer into the document.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
int toInt(bool *ok, int base) const
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
This signal is emitted, when features are added to the provider.
QString nodeName() const
int addPart(const QList< QgsPoint > &ring)
Adds a new part polygon to a multipart feature.
bool isEmpty() const
const_iterator constEnd() const
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.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
QgsPoint closestVertex(const QgsPoint &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0)...
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
Arranges candidates in a circle around a point (or centroid of a polygon).
void triggerRepaint()
Will advice the map canvas (and any other interested party) that this layer requires to be repainted...
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
virtual bool isSpatial() const override
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
QList< int > QgsAttributeList
AttributeEditorType type() const
The type of this element.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
void setBrush(const QBrush &brush)
void setDisplayField(const QString &fldName="")
Set the primary display field to be used in the identify results dialog.
int restart()
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
Storage and management of actions associated with a layer.
const T & value() const
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:74
QMap< Key, T >::iterator insert(const Key &key, const T &value)
const QString displayField() const
Returns the primary display field name used in the identify results dialog.
const_iterator constEnd() const
bool isEmpty() const
Returns true if the configuration is empty, ie it contains no columns.
bool setReadOnly(bool readonly=true)
Make layer read-only (editing disabled) or not.
bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
Change feature&#39;s geometry.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
int afterVertexNr
The index of the vertex after snappedVertex or -1 if no such vertex.
Definition: qgssnapper.h:52
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:44
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.
iterator end()
static QgsFeatureRendererV2 * defaultRenderer(QGis::GeometryType geomType)
return a new renderer - used by default in vector layers
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
void rendererChanged()
Signal emitted when renderer is changed.
virtual QGis::WkbType geometryType() const =0
Get feature type.
QString attributeAlias(int attributeIndex) const
Returns the alias of an attribute name or a null string if there is no alias.
Fast access to features using their ID.
QgsFeatureId snappedAtGeometry
Index of the snapped geometry.
Definition: qgssnapper.h:54
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:767
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
QList< QVariant > getValues(const QString &fieldOrExpression, bool &ok, bool selectedOnly=false)
Fetches all values from a specified field name or expression.
static QPainter::CompositionMode getCompositionMode(BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
void geometryChanged(QgsFeatureId fid, QgsGeometry &geometry)
Is emitted whenever a geometry change is done in the edit buffer.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:385
void raiseError(const QString &msg)
Signals an error related to this vector layer.
void editingStarted()
Is emitted, when editing on this layer has started.
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all registered layers by layer ID.
void setName(const QString &name)
Set the display name of the layer.
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
bool addFeatures(QgsFeatureList features, bool makeSelected=true)
Insert a copy of the given features into the layer (but does not commit it)
A class to represent a point.
Definition: qgspoint.h:117
iterator begin()
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &value, bool emitSignal)
Changes an attribute value (but does not commit it)
void addAttributeAlias(int attIndex, const QString &aliasString)
Sets an alias (a display name) for attributes to display in dialogs.
Q_DECL_DEPRECATED void setEditorWidgetV2Config(int attrIdx, const QgsEditorWidgetConfig &config)
Set the editor widget config for a field.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
This signal is emitted, when attribute value changes are saved to the provider.
QString right(int n) const
const QStringList & commitErrors()
QDomText createTextNode(const QString &value)
int green() const
void invalidateSymbolCountedFlag()
iterator end()
QByteArray toLocal8Bit() const
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, eg both MultiPolygon and CurvePolygon would have a PolygonG...
Definition: qgswkbtypes.h:584
QgsPoint beforeVertex
The layer coordinates of the vertex before snappedVertex.
Definition: qgssnapper.h:44
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported...
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
QgsPoint afterVertex
The layer coordinates of the vertex after snappedVertex.
Definition: qgssnapper.h:49
QDomNode namedItem(const QString &name) const
bool contains(QChar ch, Qt::CaseSensitivity cs) const
void editCommandDestroyed()
Signal emitted, whan an edit command is destroyed.
void setX(double x)
Sets the x value of the point.
Definition: qgspoint.h:162
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.
QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters &parameters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr)
Calculates an aggregated value from the layer&#39;s features.
void setY(double y)
Sets the y value of the point.
Definition: qgspoint.h:170
virtual void reload() override
Synchronises with changes in the datasource.
bool contains(const T &value) const
bool countSymbolFeatures(bool showProgress=true)
Count features for symbols.
A class to render labels.
Definition: qgslabel.h:51
static QgsMapLayerLegend * defaultVectorLegend(QgsVectorLayer *vl)
Create new legend implementation for vector layer.
A registry / canonical manager of data providers.
void setProviderEncoding(const QString &encoding)
Sets the textencoding of the data provider.
QgsExpressionContext & expressionContext()
Gets the expression context.
virtual QString loadNamedStyle(const QString &theURI, bool &theResultFlag, bool loadFromLocalDb)
Load a named style from file/local db/datasource db.
QgsGeometry * geometry()
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:76
Implementation of threaded rendering for vector layers.
const_iterator constBegin() const
bool isInScaleRange(double scale) const
Return true if the label is visible at the given scale.
Definition: qgslabel.cpp:1418
Stores the settings for rendering of all diagrams for a layer.
bool renameAttribute(int attIndex, const QString &newName)
Renames an attribute field (but does not commit it).
bool contains(const T &value) const
int layerTransparency() const
Returns the current transparency for the vector layer.
QgsMapLayerLegend * legend() const
Can be null.
bool isNull() const
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QgsAttributeList pkAttributeList() const
Returns list of attributes making up the primary key.
QgsFeatureIterator selectedFeaturesIterator(QgsFeatureRequest request=QgsFeatureRequest())
Get an iterator of the selected features.
QLibrary * providerLibrary(const QString &providerKey) const
int snappedVertexNr
The vertex index of snappedVertex or -1 if no such vertex number (e.g.
Definition: qgssnapper.h:42
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:516
const Key key(const T &value) const
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
bool snapPoint(QgsPoint &point, double tolerance)
Snaps a point to the closest vertex if there is one within the snapping tolerance.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
void addRequiredFields(QgsAttributeList &fields) const
add vector of required fields to existing list of fields
Definition: qgslabel.cpp:459
Q_DECL_DEPRECATED void setEditType(int idx, EditType edit)
Set edit type.
bool isNull() const
EditResult deleteVertexV2(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as named style in a QDomDocument.
bool updateFeature(QgsFeature &f)
Updates an existing feature.
SelectBehaviour
Selection behaviour.
void selectionChanged()
This signal is emitted when selection was changed.
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)...
virtual bool render() override
Do the rendering (based on data stored in the class)
QString providerType() const
Return the provider type for this layer.
QString & replace(int position, int n, QChar after)
Add selection to current selection.
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=nullptr)
render label
Definition: qgslabel.cpp:72
int blue() const
QString what() const
Definition: qgsexception.h:36
const T & at(int i) const
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QVariant value(const QString &key, const QVariant &defaultValue) const
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
long featureCount() const
Returns feature count including changes which have not yet been committed If you need only the count ...
Q_DECL_DEPRECATED QSize widgetSize(int idx)
Access widget size for photo and webview widget.
void beforeAddingExpressionField(const QString &fieldName)
Will be emitted, when an expression field is going to be added to this vector layer.
int addRing(const QList< QgsPoint > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
Contains information about the context of a rendering operation.
Buffers information about expression fields for a vector layer.
QString getStyleById_t(const QString &uri, QString styleID, QString &errCause)
void save(QTextStream &str, int indent) const
virtual QDomElement toDomElement(QDomDocument &doc) const =0
Is reimplemented in classes inheriting from this to serialize it.
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
QString loadStyle_t(const QString &uri, QString &errCause)
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
QgsVectorLayer(const QString &path=QString::null, const QString &baseName=QString::null, const QString &providerLib=QString::null, bool loadDefaultStyleFlag=true)
Constructor - creates a vector layer.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
bool remove(const T &value)
void setAnnotationForm(const QString &ui)
Set annotation form for layer.
QSet< T > & unite(const QSet< T > &other)
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:770
virtual QString loadDefaultStyle(bool &theResultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void * resolve(const char *symbol)
static Q_DECL_DEPRECATED const QString convertEditType(QgsVectorLayer::EditType editType, QgsEditorWidgetConfig &cfg, QgsVectorLayer *vl, const QString &name, const QDomElement &editTypeElement=QDomElement())
QSet< T > & intersect(const QSet< T > &other)
QgsVectorLayer::EditResult deleteVertexV2(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
Q_DECL_DEPRECATED const QgsEditorWidgetConfig editorWidgetV2Config(int fieldIdx) const
Get the configuration for the editor widget used to represent the field at the given index...
Q_DECL_DEPRECATED void setSelectedFeatures(const QgsFeatureIds &ids)
Change selection to the new set of features.
void endMacro()
bool isEmpty() const
QVariant calculate(Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr) const
Calculates the value of an aggregate.
This class manages a set of relations between layers.
static QgsFeatureRendererV2 * load(QDomElement &symbologyElem)
create a renderer from XML element
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurvev2.cpp:27
virtual void reloadData()
Reloads the data from the source.
void beforeModifiedCheck() const
Is emitted, when layer is checked for modifications.
bool deleteSelectedFeatures(int *deletedCount=nullptr)
Deletes the selected features.
Q_DECL_DEPRECATED RangeData range(int idx)
Access range widget config data.
Edit operation was successful.
static QgsAbstractVectorLayerLabeling * create(const QDomElement &element)
Try to create instance of an implementation based on the XML data.
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 repaintRequested()
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
This signal is emitted, when attributes are added to the provider.
const QChar at(int position) const
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
void setWindowTitle(const QString &)
QDomElement firstChildElement(const QString &tagName) const
QgsPoint snappedVertex
The coordinates of the snapping result.
Definition: qgssnapper.h:39
QDomElement lastChildElement(const QString &tagName) const
Class for storing a coordinate reference system (CRS)
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:99
friend class QgsVectorLayerEditBuffer
int count(const T &value) const
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
QgsLabel * label()
Get the label rendering properties associated with this layer.
int size() const
Return number of items.
Definition: qgsfield.cpp:370
virtual QString description() const =0
Return description.
Q_DECL_DEPRECATED bool hasLabelsEnabled() const
Label is on.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
QList< T > values() const
QList< T > mid(int pos, int length) const
This is a container for attribute editors, used to group them visually in the attribute form if it is...
void recalculateExtents()
This is used to send a request that any mapcanvas using this layer update its extents.
int length() const
virtual QDomElement toDomElement(QDomDocument &doc) const override
Will serialize this elements information into a QDomElement for saving it in an XML file...
virtual bool setSubsetString(const QString &subset)
Set the string (typically sql) used to define a subset of the layer.
bool toBool() const
char * data()
virtual QString getStyleFromDatabase(const QString &styleId, QString &msgError)
Will return the named style corresponding to style id provided.
bool isEmpty() const
bool readSld(const QDomNode &node, QString &errorMessage) override
Basic implementation of the labeling interface.
void undo()
qint64 QgsFeatureId
Definition: qgsfeature.h:31
void dataChanged()
Data of layer changed.
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
Base class for utility classes that encapsulate information necessary for rendering of map layers...
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
bool isValid() const
Remove from current selection.
void start()
virtual QString loadNamedStyle(const QString &theURI, bool &theResultFlag)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
double toDouble(bool *ok) const
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage) const override
Write the symbology for the layer into the docment provided.
virtual void addChildElement(QgsAttributeEditorElement *element)
Add a child element to this container.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
void checkJoinLayerRemove(const QString &theLayerId)
Check if there is a join with a layer that will be removed.
void(*)() cast_to_fptr(void *p)
Definition: qgis.h:272
virtual QString type() const =0
Unique type string of the labeling configuration implementation.
QString dataComment() const
Returns a comment for the data in the layer.
Edit failed due to invalid layer.
Custom exception class for Coordinate Reference System related exceptions.
QUndoStack * undoStack()
Return pointer to layer&#39;s undo stack.
QString metadata() override
Obtain Metadata for this layer.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
int size() const
QgsVectorDataProvider * dataProvider()
Returns the data provider.
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
const_iterator constEnd() const
void normalize()
Normalize the rectangle so it has non-negative width/height.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
This is a container for configuration of the attribute table.
const_iterator constBegin() const
void setCoordinateSystem()
Setup the coordinate system transformation for the layer.
This is the base class for vector data providers.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
static QString displayString(Type type)
Returns a display string type for a WKB type, eg the geometry name used in WKT geometry representatio...
Definition: qgswkbtypes.cpp:48
Abstract base class for curved geometry type.
Definition: qgscurvev2.h:32
Geometry is not required. It may still be returned if e.g. required for a filter condition.
virtual bool readXml(const QDomNode &layer_node) override
Reads vector layer specific state from project file Dom node.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
int addRing(const QList< QgsPoint > &ring, QgsFeatureId *featureId=nullptr)
Adds a ring to polygon/multipolygon features.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
This signal is emitted, when geometry changes are saved to the provider.