QGIS API Documentation  2.17.0-Master (973e4b0)
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  if ( mRendererV2 )
2181  {
2182  QDomElement rendererElement = mRendererV2->save( doc );
2183  node.appendChild( rendererElement );
2184  }
2185 
2186  if ( mLabeling )
2187  {
2188  QDomElement labelingElement = mLabeling->save( doc );
2189  node.appendChild( labelingElement );
2190  }
2191 
2192  // use scale dependent visibility flag
2193  if ( mLabel )
2194  {
2195  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
2196  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
2197  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
2198  }
2199 
2200  // save the simplification drawing settings
2201  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
2202  mapLayerNode.setAttribute( "simplifyAlgorithm", QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2203  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
2204  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2205  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
2206 
2207  //save customproperties (for labeling ng)
2208  writeCustomProperties( node, doc );
2209 
2210  // add the blend mode field
2211  QDomElement blendModeElem = doc.createElement( "blendMode" );
2213  blendModeElem.appendChild( blendModeText );
2214  node.appendChild( blendModeElem );
2215 
2216  // add the feature blend mode field
2217  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
2219  featureBlendModeElem.appendChild( featureBlendModeText );
2220  node.appendChild( featureBlendModeElem );
2221 
2222  // add the layer transparency
2223  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
2224  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
2225  layerTransparencyElem.appendChild( layerTransparencyText );
2226  node.appendChild( layerTransparencyElem );
2227 
2228  // add the display field
2229  QDomElement dField = doc.createElement( "displayfield" );
2230  QDomText dFieldText = doc.createTextNode( displayField() );
2231  dField.appendChild( dFieldText );
2232  node.appendChild( dField );
2233 
2234  // add label node
2235  QDomElement labelElem = doc.createElement( "label" );
2236  QDomText labelText = doc.createTextNode( "" );
2237 
2239  if ( hasLabelsEnabled() )
2240  {
2241  labelText.setData( "1" );
2242  }
2243  else
2244  {
2245  labelText.setData( "0" );
2246  }
2248  labelElem.appendChild( labelText );
2249 
2250  node.appendChild( labelElem );
2251 
2252  // Now we get to do all that all over again for QgsLabel
2253 
2254  if ( mLabel )
2255  {
2256  QString fieldname = mLabel->labelField( QgsLabel::Text );
2257  if ( fieldname != "" )
2258  {
2259  dField = doc.createElement( "labelfield" );
2260  dFieldText = doc.createTextNode( fieldname );
2261  dField.appendChild( dFieldText );
2262  node.appendChild( dField );
2263  }
2264 
2265  mLabel->writeXML( node, doc );
2266  }
2267 
2268  if ( mDiagramRenderer )
2269  {
2270  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
2271  if ( mDiagramLayerSettings )
2272  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
2273  }
2274  }
2275  return true;
2276 }
2277 
2278 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2279 {
2280  // get the Name element
2281  QDomElement nameElem = node.firstChildElement( "Name" );
2282  if ( nameElem.isNull() )
2283  {
2284  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
2285  }
2286 
2287  if ( hasGeometryType() )
2288  {
2289  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
2290  if ( !r )
2291  return false;
2292 
2293  setRendererV2( r );
2294 
2295  // labeling
2296  readSldLabeling( node );
2297  }
2298  return true;
2299 }
2300 
2301 
2302 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2303 {
2304  Q_UNUSED( errorMessage );
2305 
2306  // store the Name element
2307  QDomElement nameNode = doc.createElement( "se:Name" );
2308  nameNode.appendChild( doc.createTextNode( name() ) );
2309  node.appendChild( nameNode );
2310 
2311  if ( hasGeometryType() )
2312  {
2313  node.appendChild( mRendererV2->writeSld( doc, name() ) );
2314  }
2315  return true;
2316 }
2317 
2318 
2320 {
2321  if ( !mEditBuffer || !mDataProvider )
2322  {
2323  return false;
2324  }
2325 
2326  updateExtents();
2327 
2328  bool result = mEditBuffer->changeGeometry( fid, geom );
2329 
2330  if ( result )
2331  updateExtents();
2332  return result;
2333 }
2334 
2335 
2336 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant& value, bool emitSignal )
2337 {
2338  Q_UNUSED( emitSignal );
2339  return changeAttributeValue( fid, field, value );
2340 }
2341 
2342 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2343 {
2344  if ( !mEditBuffer || !mDataProvider )
2345  return false;
2346 
2347  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2348 }
2349 
2351 {
2352  if ( !mEditBuffer || !mDataProvider )
2353  return false;
2354 
2355  return mEditBuffer->addAttribute( field );
2356 }
2357 
2359 {
2360  if ( attIndex < 0 || attIndex >= fields().count() )
2361  return;
2362 
2363  QString name = fields().at( attIndex ).name();
2364  if ( mAttributeAliasMap.contains( name ) )
2365  {
2366  mAttributeAliasMap.remove( name );
2367  emit layerModified();
2368  }
2369 }
2370 
2371 bool QgsVectorLayer::renameAttribute( int attIndex, const QString& newName )
2372 {
2373  if ( !mEditBuffer || !mDataProvider )
2374  return false;
2375 
2376  return mEditBuffer->renameAttribute( attIndex, newName );
2377 }
2378 
2379 void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString )
2380 {
2381  if ( attIndex < 0 || attIndex >= fields().count() )
2382  return;
2383 
2384  QString name = fields().at( attIndex ).name();
2385 
2386  mAttributeAliasMap.insert( name, aliasString );
2387  emit layerModified(); // TODO[MD]: should have a different signal?
2388 }
2389 
2390 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2391 {
2392  if ( attributeIndex < 0 || attributeIndex >= fields().count() )
2393  return QString();
2394 
2395  QString name = fields().at( attributeIndex ).name();
2396 
2397  return mAttributeAliasMap.value( name, QString() );
2398 }
2399 
2401 {
2402  QString displayName = attributeAlias( attributeIndex );
2403  if ( displayName.isEmpty() )
2404  {
2405  if ( attributeIndex >= 0 && attributeIndex < mUpdatedFields.count() )
2406  {
2407  displayName = mUpdatedFields.at( attributeIndex ).name();
2408  }
2409  }
2410  return displayName;
2411 }
2412 
2414 {
2415  if ( index < 0 || index >= fields().count() )
2416  return false;
2417 
2418  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2419  {
2420  removeExpressionField( index );
2421  return true;
2422  }
2423 
2424  if ( !mEditBuffer || !mDataProvider )
2425  return false;
2426 
2427  return mEditBuffer->deleteAttribute( index );
2428 }
2429 
2431 {
2432  bool deleted = false;
2433 
2434  // Remove multiple occurrences of same attribute
2435  attrs = attrs.toSet().toList();
2436 
2437  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2438 
2439  Q_FOREACH ( int attr, attrs )
2440  {
2441  if ( deleteAttribute( attr ) )
2442  {
2443  deleted = true;
2444  }
2445  }
2446 
2447  return deleted;
2448 }
2449 
2451 {
2452  if ( !mEditBuffer )
2453  return false;
2454 
2455  bool res = mEditBuffer->deleteFeature( fid );
2456  if ( res )
2457  {
2458  mSelectedFeatureIds.remove( fid ); // remove it from selection
2459  updateExtents();
2460  }
2461 
2462  return res;
2463 }
2464 
2466 {
2467  if ( !mEditBuffer )
2468  return false;
2469 
2470  bool res = mEditBuffer->deleteFeatures( fids );
2471 
2472  if ( res )
2473  {
2474  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2475  updateExtents();
2476  }
2477 
2478  return res;
2479 }
2480 
2482 {
2483  QgsAttributeList pkAttributesList;
2484 
2485  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2486  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2487  {
2488  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2489  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2490  pkAttributesList << i;
2491  }
2492 
2493  return pkAttributesList;
2494 }
2495 
2497 {
2498  return mDataProvider->featureCount() +
2499  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2500 }
2501 
2503 {
2504  mCommitErrors.clear();
2505 
2506  if ( !mDataProvider )
2507  {
2508  mCommitErrors << tr( "ERROR: no provider" );
2509  return false;
2510  }
2511 
2512  if ( !mEditBuffer )
2513  {
2514  mCommitErrors << tr( "ERROR: layer not editable" );
2515  return false;
2516  }
2517 
2518  emit beforeCommitChanges();
2519 
2520  bool success = mEditBuffer->commitChanges( mCommitErrors );
2521 
2522  if ( success )
2523  {
2524  delete mEditBuffer;
2525  mEditBuffer = nullptr;
2526  undoStack()->clear();
2527  emit editingStopped();
2528  }
2529  else
2530  {
2531  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2532  }
2533 
2534  if ( mCache )
2535  {
2536  mCache->deleteCachedGeometries();
2537  }
2538 
2539  updateFields();
2540  mDataProvider->updateExtents();
2541 
2542  mDataProvider->leaveUpdateMode();
2543 
2544  emit repaintRequested();
2545 
2546  return success;
2547 }
2548 
2550 {
2551  return mCommitErrors;
2552 }
2553 
2554 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2555 {
2556  if ( !mEditBuffer )
2557  {
2558  return false;
2559  }
2560 
2561  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2562  !mEditBuffer->mAddedFeatures.isEmpty() ||
2563  !mEditBuffer->mChangedGeometries.isEmpty();
2564 
2565  emit beforeRollBack();
2566 
2567  mEditBuffer->rollBack();
2568 
2569  if ( isModified() )
2570  {
2571  // new undo stack roll back method
2572  // old method of calling every undo could cause many canvas refreshes
2573  undoStack()->setIndex( 0 );
2574  }
2575 
2576  updateFields();
2577 
2578  if ( deleteBuffer )
2579  {
2580  delete mEditBuffer;
2581  mEditBuffer = nullptr;
2582  undoStack()->clear();
2583  }
2584  emit editingStopped();
2585 
2586  if ( mCache )
2587  {
2588  mCache->deleteCachedGeometries();
2589  }
2590 
2591  if ( rollbackExtent )
2592  updateExtents();
2593 
2594  mDataProvider->leaveUpdateMode();
2595 
2596  emit repaintRequested();
2597  return true;
2598 }
2599 
2601 {
2602  selectByIds( ids, SetSelection );
2603 }
2604 
2606 {
2607  return mSelectedFeatureIds.size();
2608 }
2609 
2611 {
2612  return mSelectedFeatureIds;
2613 }
2614 
2616 {
2617  QgsFeatureList features;
2618  QgsFeature f;
2619 
2620  if ( mSelectedFeatureIds.count() <= 8 )
2621  {
2622  // for small amount of selected features, fetch them directly
2623  // because request with FilterFids would go iterate over the whole layer
2624  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2625  {
2626  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2627  features << f;
2628  }
2629  }
2630  else
2631  {
2633 
2634  while ( it.nextFeature( f ) )
2635  {
2636  features.push_back( f );
2637  }
2638  }
2639 
2640  return features;
2641 }
2642 
2644 {
2645  if ( mSelectedFeatureIds.isEmpty() )
2646  return QgsFeatureIterator();
2647 
2648  if ( geometryType() == QGis::NoGeometry )
2650 
2651  if ( mSelectedFeatureIds.count() == 1 )
2652  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2653  else
2654  request.setFilterFids( mSelectedFeatureIds );
2655 
2656  return getFeatures( request );
2657 }
2658 
2659 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2660 {
2661  if ( !mEditBuffer || !mDataProvider )
2662  return false;
2663 
2664  bool res = mEditBuffer->addFeatures( features );
2665 
2666  if ( makeSelected )
2667  {
2668  QgsFeatureIds ids;
2669 
2670  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2671  ids << iter->id();
2672 
2673  selectByIds( ids );
2674  }
2675 
2676  updateExtents();
2677 
2678  return res;
2679 }
2680 
2681 
2682 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2683 {
2684  if ( !hasGeometryType() )
2685  return false;
2686 
2688  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2689 
2690  if ( result != 0 )
2691  {
2692  return false;
2693  }
2694 
2695  if ( snapResults.size() < 1 )
2696  {
2697  return false;
2698  }
2699 
2701  point.setX( snap_it.value().snappedVertex.x() );
2702  point.setY( snap_it.value().snappedVertex.y() );
2703  return true;
2704 }
2705 
2706 
2707 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2708  QMultiMap<double, QgsSnappingResult>& snappingResults,
2709  QgsSnapper::SnappingType snap_to )
2710 {
2711  if ( !hasGeometryType() )
2712  return 1;
2713 
2714  if ( snappingTolerance <= 0 || !mDataProvider )
2715  {
2716  return 1;
2717  }
2718 
2719  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2720  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2721  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2722 
2723  int n = 0;
2724  QgsFeature f;
2725 
2726  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2727  {
2728  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2729  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2730  {
2731  QgsGeometry* g = &( it.value() );
2732  if ( g->boundingBox().intersects( searchRect ) )
2733  {
2734  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2735  ++n;
2736  }
2737  }
2738  }
2739  else
2740  {
2741  // snapping outside cached area
2742 
2744  .setFilterRect( searchRect )
2746  .setSubsetOfAttributes( QgsAttributeList() ) );
2747 
2748  while ( fit.nextFeature( f ) )
2749  {
2750  snapToGeometry( startPoint, f.id(), f.constGeometry(), sqrSnappingTolerance, snappingResults, snap_to );
2751  ++n;
2752  }
2753  }
2754 
2755  return n == 0 ? 2 : 0;
2756 }
2757 
2758 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2759  QgsFeatureId featureId,
2760  const QgsGeometry* geom,
2761  double sqrSnappingTolerance,
2762  QMultiMap<double, QgsSnappingResult>& snappingResults,
2763  QgsSnapper::SnappingType snap_to ) const
2764 {
2765  if ( !geom )
2766  {
2767  return;
2768  }
2769 
2770  int atVertex, beforeVertex, afterVertex;
2771  double sqrDistVertexSnap, sqrDistSegmentSnap;
2772  QgsPoint snappedPoint;
2773  QgsSnappingResult snappingResultVertex;
2774  QgsSnappingResult snappingResultSegment;
2775 
2776  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2777  {
2778  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2779  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2780  {
2781  snappingResultVertex.snappedVertex = snappedPoint;
2782  snappingResultVertex.snappedVertexNr = atVertex;
2783  snappingResultVertex.beforeVertexNr = beforeVertex;
2784  if ( beforeVertex != -1 ) // make sure the vertex is valid
2785  {
2786  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2787  }
2788  snappingResultVertex.afterVertexNr = afterVertex;
2789  if ( afterVertex != -1 ) // make sure the vertex is valid
2790  {
2791  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2792  }
2793  snappingResultVertex.snappedAtGeometry = featureId;
2794  snappingResultVertex.layer = this;
2795  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2796  return;
2797  }
2798  }
2799  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2800  {
2801  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2802  {
2803  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, nullptr, crs().geographicFlag() ? 1e-12 : 1e-8 );
2804 
2805  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2806  {
2807  snappingResultSegment.snappedVertex = snappedPoint;
2808  snappingResultSegment.snappedVertexNr = -1;
2809  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2810  snappingResultSegment.afterVertexNr = afterVertex;
2811  snappingResultSegment.snappedAtGeometry = featureId;
2812  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2813  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2814  snappingResultSegment.layer = this;
2815  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2816  }
2817  }
2818  }
2819 }
2820 
2822 {
2823  QgsVectorLayerEditUtils utils( this );
2824  return utils.insertSegmentVerticesForSnap( snapResults );
2825 }
2826 
2827 
2829 {
2830  QgsDebugMsg( "----- Computing Coordinate System" );
2831 
2832  //
2833  // Get the layers project info and set up the QgsCoordinateTransform
2834  // for this layer
2835  //
2836 
2837  if ( hasGeometryType() )
2838  {
2839  // get CRS directly from provider
2840  setCrs( mDataProvider->crs() );
2841  }
2842  else
2843  {
2845  }
2846 }
2847 
2848 
2850 {
2851  return mDisplayField;
2852 }
2853 
2855 {
2856  mDisplayExpression = displayExpression;
2857 }
2858 
2860 {
2861  return mDisplayExpression;
2862 }
2863 
2865 {
2866  return ( mEditBuffer && mDataProvider );
2867 }
2868 
2870 {
2871  return geometryType() != QGis::NoGeometry;
2872 }
2873 
2875 {
2876  return mReadOnly;
2877 }
2878 
2879 bool QgsVectorLayer::setReadOnly( bool readonly )
2880 {
2881  // exit if the layer is in editing mode
2882  if ( readonly && mEditBuffer )
2883  return false;
2884 
2885  mReadOnly = readonly;
2886  return true;
2887 }
2888 
2890 {
2891  emit beforeModifiedCheck();
2892  return mEditBuffer && mEditBuffer->isModified();
2893 }
2894 
2896 {
2897  if ( idx < 0 || idx >= mUpdatedFields.count() )
2898  return Hidden;
2899 
2901  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
2903 }
2904 
2906 {
2907  if ( idx < 0 || idx >= mUpdatedFields.count() )
2908  return;
2909 
2911 
2913  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
2914 
2915  setEditorWidgetV2( idx, widgetType );
2916  setEditorWidgetV2Config( idx, cfg );
2918 }
2919 
2921 {
2922  mAnnotationForm = ui;
2923 }
2924 
2926 {
2928  return editorWidgetV2Config( idx );
2930 }
2931 
2933 {
2935  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2936  return RangeData(
2937  cfg.value( "Min" ),
2938  cfg.value( "Max" ),
2939  cfg.value( "Step" )
2940  );
2942 }
2943 
2945 {
2947  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
2949 }
2950 
2952 {
2954  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2955  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
2957 }
2958 
2960 {
2961  if ( !hasGeometryType() )
2962  return;
2963 
2964  if ( r != mRendererV2 )
2965  {
2966  delete mRendererV2;
2967  mRendererV2 = r;
2968  mSymbolFeatureCounted = false;
2969  mSymbolFeatureCountMap.clear();
2970 
2971  emit rendererChanged();
2972  emit styleChanged();
2973  }
2974 }
2975 
2977 {
2978  if ( !mDataProvider )
2979  {
2980  return;
2981  }
2982  if ( !mDataProvider->transaction() )
2983  {
2984  undoStack()->beginMacro( text );
2985  mEditCommandActive = true;
2986  emit editCommandStarted( text );
2987  }
2988 }
2989 
2991 {
2992  if ( !mDataProvider )
2993  {
2994  return;
2995  }
2996  if ( !mDataProvider->transaction() )
2997  {
2998  undoStack()->endMacro();
2999  mEditCommandActive = false;
3000  if ( !mDeletedFids.isEmpty() )
3001  {
3002  emit featuresDeleted( mDeletedFids );
3003  mDeletedFids.clear();
3004  }
3005  emit editCommandEnded();
3006  }
3007 }
3008 
3010 {
3011  if ( !mDataProvider )
3012  {
3013  return;
3014  }
3015  if ( !mDataProvider->transaction() )
3016  {
3017  undoStack()->endMacro();
3018  undoStack()->undo();
3019  mEditCommandActive = false;
3020  mDeletedFids.clear();
3021  emit editCommandDestroyed();
3022  }
3023 }
3024 
3025 
3026 void QgsVectorLayer::setCheckedState( int idx, const QString& checked, const QString& unchecked )
3027 {
3030  cfg["CheckedState"] = checked;
3031  cfg["UncheckedState"] = unchecked;
3032  setEditorWidgetV2Config( idx, cfg );
3034 }
3035 
3036 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
3037 {
3038  return fields().fieldNameIndex( fieldName );
3039 }
3040 
3042 {
3043  return mJoinBuffer && mJoinBuffer->addJoin( joinInfo );
3044 }
3045 
3047 {
3048  removeJoin( theLayerId );
3049 }
3050 
3051 bool QgsVectorLayer::removeJoin( const QString& joinLayerId )
3052 {
3053  bool res = false;
3054  if ( mJoinBuffer )
3055  {
3056  res = mJoinBuffer->removeJoin( joinLayerId );
3057  }
3058  return res;
3059 }
3060 
3062 {
3063  if ( mJoinBuffer )
3064  return mJoinBuffer->vectorJoins();
3065  else
3066  return QList< QgsVectorJoinInfo >();
3067 }
3068 
3070 {
3071  emit beforeAddingExpressionField( fld.name() );
3072  mExpressionFieldBuffer->addExpression( exp, fld );
3073  updateFields();
3074  int idx = mUpdatedFields.indexFromName( fld.name() );
3075  emit attributeAdded( idx );
3076  return idx;
3077 }
3078 
3080 {
3081  emit beforeRemovingExpressionField( index );
3082  int oi = mUpdatedFields.fieldOriginIndex( index );
3083  mExpressionFieldBuffer->removeExpression( oi );
3084  updateFields();
3085  emit attributeDeleted( index );
3086 }
3087 
3089 {
3090  int oi = mUpdatedFields.fieldOriginIndex( index );
3091  return mExpressionFieldBuffer->expressions().value( oi ).expression;
3092 }
3093 
3095 {
3096  int oi = mUpdatedFields.fieldOriginIndex( index );
3097  mExpressionFieldBuffer->updateExpression( oi, exp );
3098 }
3099 
3101 {
3102  if ( !mDataProvider )
3103  return;
3104 
3105  QgsFields oldFields = mUpdatedFields;
3106 
3107  mUpdatedFields = mDataProvider->fields();
3108 
3109  // added / removed fields
3110  if ( mEditBuffer )
3111  mEditBuffer->updateFields( mUpdatedFields );
3112 
3113  // joined fields
3114  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
3115  mJoinBuffer->updateFields( mUpdatedFields );
3116 
3117  if ( mExpressionFieldBuffer )
3118  mExpressionFieldBuffer->updateFields( mUpdatedFields );
3119 
3120  if ( oldFields != mUpdatedFields )
3121  {
3122  emit updatedFields();
3123  mEditFormConfig->setFields( mUpdatedFields );
3124  }
3125 }
3126 
3127 
3129 {
3130  if ( mJoinBuffer->containsJoins() )
3131  {
3132  mJoinBuffer->createJoinCaches();
3133  }
3134 }
3135 
3137 {
3138  uniqueValues.clear();
3139  if ( !mDataProvider )
3140  {
3141  return;
3142  }
3143 
3144  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3145  switch ( origin )
3146  {
3148  return;
3149 
3150  case QgsFields::OriginProvider: //a provider field
3151  {
3152  mDataProvider->uniqueValues( index, uniqueValues, limit );
3153 
3154  if ( mEditBuffer )
3155  {
3156  QSet<QString> vals;
3157  Q_FOREACH ( const QVariant& v, uniqueValues )
3158  {
3159  vals << v.toString();
3160  }
3161 
3162  QgsFeatureMap added = mEditBuffer->addedFeatures();
3164  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3165  {
3166  addedIt.next();
3167  QVariant v = addedIt.value().attribute( index );
3168  if ( v.isValid() )
3169  {
3170  QString vs = v.toString();
3171  if ( !vals.contains( vs ) )
3172  {
3173  vals << vs;
3174  uniqueValues << v;
3175  }
3176  }
3177  }
3178 
3179  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3180  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3181  {
3182  it.next();
3183  QVariant v = it.value().value( index );
3184  if ( v.isValid() )
3185  {
3186  QString vs = v.toString();
3187  if ( !vals.contains( vs ) )
3188  {
3189  vals << vs;
3190  uniqueValues << v;
3191  }
3192  }
3193  }
3194  }
3195 
3196  return;
3197  }
3198 
3199  case QgsFields::OriginEdit:
3200  // the layer is editable, but in certain cases it can still be avoided going through all features
3201  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3202  mEditBuffer->mAddedFeatures.isEmpty() &&
3203  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3204  mEditBuffer->mChangedAttributeValues.isEmpty() )
3205  {
3206  mDataProvider->uniqueValues( index, uniqueValues, limit );
3207  return;
3208  }
3209  FALLTHROUGH;
3210  //we need to go through each feature
3211  case QgsFields::OriginJoin:
3213  {
3214  QgsAttributeList attList;
3215  attList << index;
3216 
3218  .setFlags( QgsFeatureRequest::NoGeometry )
3219  .setSubsetOfAttributes( attList ) );
3220 
3221  QgsFeature f;
3222  QVariant currentValue;
3224  while ( fit.nextFeature( f ) )
3225  {
3226  currentValue = f.attribute( index );
3227  val.insert( currentValue.toString(), currentValue );
3228  if ( limit >= 0 && val.size() >= limit )
3229  {
3230  break;
3231  }
3232  }
3233 
3234  uniqueValues = val.values();
3235  return;
3236  }
3237  }
3238 
3239  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3240 }
3241 
3243 {
3244  if ( !mDataProvider )
3245  {
3246  return QVariant();
3247  }
3248 
3249  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3250 
3251  switch ( origin )
3252  {
3254  return QVariant();
3255 
3256  case QgsFields::OriginProvider: //a provider field
3257  {
3258  QVariant min = mDataProvider->minimumValue( index );
3259  if ( mEditBuffer )
3260  {
3261  QgsFeatureMap added = mEditBuffer->addedFeatures();
3263  while ( addedIt.hasNext() )
3264  {
3265  addedIt.next();
3266  QVariant v = addedIt.value().attribute( index );
3267  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3268  {
3269  min = v;
3270  }
3271  }
3272 
3273  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3274  while ( it.hasNext() )
3275  {
3276  it.next();
3277  QVariant v = it.value().value( index );
3278  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3279  {
3280  min = v;
3281  }
3282  }
3283  }
3284  return min;
3285  }
3286 
3287  case QgsFields::OriginEdit:
3288  {
3289  // the layer is editable, but in certain cases it can still be avoided going through all features
3290  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3291  mEditBuffer->mAddedFeatures.isEmpty() && !
3292  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3293  mEditBuffer->mChangedAttributeValues.isEmpty() )
3294  {
3295  return mDataProvider->minimumValue( index );
3296  }
3297  }
3298  FALLTHROUGH;
3299  // no choice but to go through all features
3301  case QgsFields::OriginJoin:
3302  {
3303  // we need to go through each feature
3304  QgsAttributeList attList;
3305  attList << index;
3306 
3308  .setFlags( QgsFeatureRequest::NoGeometry )
3309  .setSubsetOfAttributes( attList ) );
3310 
3311  QgsFeature f;
3313  double currentValue = 0;
3314  while ( fit.nextFeature( f ) )
3315  {
3316  currentValue = f.attribute( index ).toDouble();
3317  if ( currentValue < minimumValue )
3318  {
3319  minimumValue = currentValue;
3320  }
3321  }
3322  return QVariant( minimumValue );
3323  }
3324  }
3325 
3326  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3327  return QVariant();
3328 }
3329 
3331 {
3332  if ( !mDataProvider )
3333  {
3334  return QVariant();
3335  }
3336 
3337  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3338  switch ( origin )
3339  {
3341  return QVariant();
3342 
3343  case QgsFields::OriginProvider: //a provider field
3344  {
3345  QVariant min = mDataProvider->maximumValue( index );
3346  if ( mEditBuffer )
3347  {
3348  QgsFeatureMap added = mEditBuffer->addedFeatures();
3350  while ( addedIt.hasNext() )
3351  {
3352  addedIt.next();
3353  QVariant v = addedIt.value().attribute( index );
3354  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3355  {
3356  min = v;
3357  }
3358  }
3359 
3360  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3361  while ( it.hasNext() )
3362  {
3363  it.next();
3364  QVariant v = it.value().value( index );
3365  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3366  {
3367  min = v;
3368  }
3369  }
3370  }
3371  return min;
3372  }
3373 
3374  case QgsFields::OriginEdit:
3375  // the layer is editable, but in certain cases it can still be avoided going through all features
3376  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3377  mEditBuffer->mAddedFeatures.isEmpty() &&
3378  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3379  mEditBuffer->mChangedAttributeValues.isEmpty() )
3380  {
3381  return mDataProvider->maximumValue( index );
3382  }
3383 
3384  FALLTHROUGH;
3385  //no choice but to go through each feature
3386  case QgsFields::OriginJoin:
3388  {
3389  QgsAttributeList attList;
3390  attList << index;
3391 
3393  .setFlags( QgsFeatureRequest::NoGeometry )
3394  .setSubsetOfAttributes( attList ) );
3395 
3396  QgsFeature f;
3398  double currentValue = 0;
3399  while ( fit.nextFeature( f ) )
3400  {
3401  currentValue = f.attribute( index ).toDouble();
3402  if ( currentValue > maximumValue )
3403  {
3404  maximumValue = currentValue;
3405  }
3406  }
3407  return QVariant( maximumValue );
3408  }
3409  }
3410 
3411  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3412  return QVariant();
3413 }
3414 
3416  const QgsAggregateCalculator::AggregateParameters& parameters, QgsExpressionContext* context, bool* ok )
3417 {
3418  if ( ok )
3419  *ok = false;
3420 
3421  if ( !mDataProvider )
3422  {
3423  return QVariant();
3424  }
3425 
3426  // test if we are calculating based on a field
3427  int attrIndex = mUpdatedFields.fieldNameIndex( fieldOrExpression );
3428  if ( attrIndex >= 0 )
3429  {
3430  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
3431  // to the provider itself
3432  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( attrIndex );
3433  if ( origin == QgsFields::OriginProvider )
3434  {
3435  bool providerOk = false;
3436  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk );
3437  if ( providerOk )
3438  {
3439  // provider handled calculation
3440  if ( ok )
3441  *ok = true;
3442  return val;
3443  }
3444  }
3445  }
3446 
3447  // fallback to using aggregate calculator to determine aggregate
3448  QgsAggregateCalculator c( this );
3449  c.setParameters( parameters );
3450  return c.calculate( aggregate, fieldOrExpression, context, ok );
3451 }
3452 
3453 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly )
3454 {
3455  QList<QVariant> values;
3456 
3457  QScopedPointer<QgsExpression> expression;
3458  QgsExpressionContext context;
3459 
3460  int attrNum = fieldNameIndex( fieldOrExpression );
3461 
3462  if ( attrNum == -1 )
3463  {
3464  // try to use expression
3465  expression.reset( new QgsExpression( fieldOrExpression ) );
3469 
3470  if ( expression->hasParserError() || !expression->prepare( &context ) )
3471  {
3472  ok = false;
3473  return values;
3474  }
3475  }
3476 
3477  QgsFeature f;
3478  QStringList lst;
3479  if ( expression.isNull() )
3480  lst.append( fieldOrExpression );
3481  else
3482  lst = expression->referencedColumns();
3483 
3485  .setFlags(( expression && expression->needsGeometry() ) ?
3488  .setSubsetOfAttributes( lst, fields() );
3489 
3490  QgsFeatureIterator fit;
3491  if ( !selectedOnly )
3492  {
3493  fit = getFeatures( request );
3494  }
3495  else
3496  {
3497  fit = selectedFeaturesIterator( request );
3498  }
3499 
3500  // create list of non-null attribute values
3501  while ( fit.nextFeature( f ) )
3502  {
3503  if ( expression )
3504  {
3505  context.setFeature( f );
3506  QVariant v = expression->evaluate( &context );
3507  values << v;
3508  }
3509  else
3510  {
3511  values << f.attribute( attrNum );
3512  }
3513  }
3514  ok = true;
3515  return values;
3516 }
3517 
3518 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly, int* nullCount )
3519 {
3520  QList<double> values;
3521 
3522  if ( nullCount )
3523  *nullCount = 0;
3524 
3525  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3526  if ( !ok )
3527  return values;
3528 
3529  bool convertOk;
3530  Q_FOREACH ( const QVariant& value, variantValues )
3531  {
3532  double val = value.toDouble( &convertOk );
3533  if ( convertOk )
3534  values << val;
3535  else if ( value.isNull() )
3536  {
3537  if ( nullCount )
3538  *nullCount += 1;
3539  }
3540  }
3541  ok = true;
3542  return values;
3543 }
3544 
3545 
3548 {
3549  mFeatureBlendMode = featureBlendMode;
3550  emit featureBlendModeChanged( featureBlendMode );
3551  emit styleChanged();
3552 }
3553 
3555 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3556 {
3557  return mFeatureBlendMode;
3558 }
3559 
3562 {
3563  mLayerTransparency = layerTransparency;
3564  emit layerTransparencyChanged( layerTransparency );
3565  emit styleChanged();
3566 }
3567 
3570 {
3571  return mLayerTransparency;
3572 }
3573 
3574 
3575 
3576 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3577 {
3578  QDomElement element = node.toElement();
3579  if ( element.isNull() )
3580  return;
3581 
3582  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3583  if ( userStyleElem.isNull() )
3584  {
3585  QgsDebugMsg( "Info: UserStyle element not found." );
3586  return;
3587  }
3588 
3589  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3590  if ( featureTypeStyleElem.isNull() )
3591  {
3592  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3593  return;
3594  }
3595 
3596  // use last rule
3597  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3598  if ( ruleElem.isNull() )
3599  {
3600  QgsDebugMsg( "Info: Rule element not found." );
3601  return;
3602  }
3603 
3604  // use last text symbolizer
3605  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3606  if ( textSymbolizerElem.isNull() )
3607  {
3608  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3609  return;
3610  }
3611 
3612  // Label
3613  setCustomProperty( "labeling/enabled", false );
3614  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3615  if ( !labelElem.isNull() )
3616  {
3617  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3618  if ( !propertyNameElem.isNull() )
3619  {
3620  // enable labeling
3621  setCustomProperty( "labeling", "pal" );
3622  setCustomProperty( "labeling/enabled", true );
3623 
3624  // set labeling defaults
3625  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3626  setCustomProperty( "labeling/fontItalic", false );
3627  setCustomProperty( "labeling/fontSize", 10 );
3628  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3629  setCustomProperty( "labeling/fontBold", false );
3630  setCustomProperty( "labeling/fontUnderline", false );
3631  setCustomProperty( "labeling/textColorR", 0 );
3632  setCustomProperty( "labeling/textColorG", 0 );
3633  setCustomProperty( "labeling/textColorB", 0 );
3634  setCustomProperty( "labeling/textTransp", 0 );
3635  setCustomProperty( "labeling/bufferDraw", false );
3636  setCustomProperty( "labeling/bufferSize", 1 );
3637  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3638  setCustomProperty( "labeling/bufferColorR", 255 );
3639  setCustomProperty( "labeling/bufferColorG", 255 );
3640  setCustomProperty( "labeling/bufferColorB", 255 );
3641  setCustomProperty( "labeling/bufferTransp", 0 );
3642  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3643  setCustomProperty( "labeling/xOffset", 0 );
3644  setCustomProperty( "labeling/yOffset", 0 );
3645  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3646  setCustomProperty( "labeling/angleOffset", 0 );
3647 
3648  // label attribute
3649  QString labelAttribute = propertyNameElem.text();
3650  setCustomProperty( "labeling/fieldName", labelAttribute );
3651  setCustomProperty( "labeling/isExpression", false );
3652 
3653  int fieldIndex = fieldNameIndex( labelAttribute );
3654  if ( fieldIndex == -1 )
3655  {
3656  // label attribute is not in columns, check if it is an expression
3657  QgsExpression exp( labelAttribute );
3658  if ( !exp.hasEvalError() )
3659  {
3660  setCustomProperty( "labeling/isExpression", true );
3661  }
3662  else
3663  {
3664  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3665  }
3666  }
3667  }
3668  else
3669  {
3670  QgsDebugMsg( "Info: PropertyName element not found." );
3671  return;
3672  }
3673  }
3674  else
3675  {
3676  QgsDebugMsg( "Info: Label element not found." );
3677  return;
3678  }
3679 
3680  // Font
3681  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3682  if ( !fontElem.isNull() )
3683  {
3684  QString cssName;
3685  QString elemText;
3686  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3687  while ( !cssElem.isNull() )
3688  {
3689  cssName = cssElem.attribute( "name", "not_found" );
3690  if ( cssName != "not_found" )
3691  {
3692  elemText = cssElem.text();
3693  if ( cssName == "font-family" )
3694  {
3695  setCustomProperty( "labeling/fontFamily", elemText );
3696  }
3697  else if ( cssName == "font-style" )
3698  {
3699  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3700  }
3701  else if ( cssName == "font-size" )
3702  {
3703  bool ok;
3704  int fontSize = elemText.toInt( &ok );
3705  if ( ok )
3706  {
3707  setCustomProperty( "labeling/fontSize", fontSize );
3708  }
3709  }
3710  else if ( cssName == "font-weight" )
3711  {
3712  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3713  }
3714  else if ( cssName == "font-underline" )
3715  {
3716  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3717  }
3718  }
3719 
3720  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3721  }
3722  }
3723 
3724  // Fill
3725  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3726  if ( textColor.isValid() )
3727  {
3728  setCustomProperty( "labeling/textColorR", textColor.red() );
3729  setCustomProperty( "labeling/textColorG", textColor.green() );
3730  setCustomProperty( "labeling/textColorB", textColor.blue() );
3731  setCustomProperty( "labeling/textTransp", 100 - static_cast< int >( 100 * textColor.alphaF() ) );
3732  }
3733 
3734  // Halo
3735  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3736  if ( !haloElem.isNull() )
3737  {
3738  setCustomProperty( "labeling/bufferDraw", true );
3739  setCustomProperty( "labeling/bufferSize", 1 );
3740 
3741  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3742  if ( !radiusElem.isNull() )
3743  {
3744  bool ok;
3745  double bufferSize = radiusElem.text().toDouble( &ok );
3746  if ( ok )
3747  {
3748  setCustomProperty( "labeling/bufferSize", bufferSize );
3749  }
3750  }
3751 
3752  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3753  if ( bufferColor.isValid() )
3754  {
3755  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3756  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3757  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3758  setCustomProperty( "labeling/bufferTransp", 100 - static_cast< int >( 100 * bufferColor.alphaF() ) );
3759  }
3760  }
3761 
3762  // LabelPlacement
3763  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3764  if ( !labelPlacementElem.isNull() )
3765  {
3766  // PointPlacement
3767  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3768  if ( !pointPlacementElem.isNull() )
3769  {
3770  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3771 
3772  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3773  if ( !displacementElem.isNull() )
3774  {
3775  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3776  if ( !displacementXElem.isNull() )
3777  {
3778  bool ok;
3779  double xOffset = displacementXElem.text().toDouble( &ok );
3780  if ( ok )
3781  {
3782  setCustomProperty( "labeling/xOffset", xOffset );
3783  }
3784  }
3785  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3786  if ( !displacementYElem.isNull() )
3787  {
3788  bool ok;
3789  double yOffset = displacementYElem.text().toDouble( &ok );
3790  if ( ok )
3791  {
3792  setCustomProperty( "labeling/yOffset", yOffset );
3793  }
3794  }
3795  }
3796 
3797  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
3798  if ( !rotationElem.isNull() )
3799  {
3800  bool ok;
3801  double rotation = rotationElem.text().toDouble( &ok );
3802  if ( ok )
3803  {
3804  setCustomProperty( "labeling/angleOffset", rotation );
3805  }
3806  }
3807  }
3808  }
3809 }
3810 
3812 {
3813  QgsAttributeTableConfig config = mAttributeTableConfig;
3814 
3815  if ( config.isEmpty() )
3816  config.update( fields() );
3817 
3818  return config;
3819 }
3820 
3822 {
3823  if ( mAttributeTableConfig != attributeTableConfig )
3824  {
3825  mAttributeTableConfig = attributeTableConfig;
3826  emit configChanged();
3827  }
3828 }
3829 
3831 {
3832  if ( !mDiagramLayerSettings )
3833  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3834  *mDiagramLayerSettings = s;
3835 }
3836 
3838 {
3839  QString myMetadata = "<html><body>";
3840 
3841  //-------------
3842 
3843  myMetadata += "<p class=\"subheaderglossy\">";
3844  myMetadata += tr( "General" );
3845  myMetadata += "</p>\n";
3846 
3847  // data comment
3848  if ( !( dataComment().isEmpty() ) )
3849  {
3850  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
3851  myMetadata += "<p>";
3852  myMetadata += dataComment();
3853  myMetadata += "</p>\n";
3854  }
3855 
3856  //storage type
3857  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
3858  myMetadata += "<p>";
3859  myMetadata += storageType();
3860  myMetadata += "</p>\n";
3861 
3862  if ( dataProvider() )
3863  {
3864  //provider description
3865  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
3866  myMetadata += "<p>";
3867  myMetadata += dataProvider()->description().replace( '\n', "<br>" );
3868  myMetadata += "</p>\n";
3869  }
3870 
3871  // data source
3872  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
3873  myMetadata += "<p>";
3874  myMetadata += publicSource();
3875  myMetadata += "</p>\n";
3876 
3877  //geom type
3878 
3880 
3881  if ( type < 0 || type > QGis::NoGeometry )
3882  {
3883  QgsDebugMsg( "Invalid vector type" );
3884  }
3885  else
3886  {
3887  QString typeString( QGis::vectorGeometryType( geometryType() ) );
3888  QString wkbTypeString = QgsWKBTypes::displayString( QGis::fromOldWkbType( mWkbType ) );
3889 
3890  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
3891  myMetadata += QString( "<p>%1 (WKB type: \"%2\")</p>\n" ).arg( typeString, wkbTypeString );
3892  }
3893 
3894  QgsAttributeList pkAttrList = pkAttributeList();
3895  if ( !pkAttrList.isEmpty() )
3896  {
3897  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
3898  myMetadata += "<p>";
3899  Q_FOREACH ( int idx, pkAttrList )
3900  {
3901  myMetadata += fields().at( idx ).name() + ' ';
3902  }
3903  myMetadata += "</p>\n";
3904  }
3905 
3906 
3907  //feature count
3908  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
3909  myMetadata += "<p>";
3910  myMetadata += QString::number( featureCount() );
3911  myMetadata += "</p>\n";
3912  //capabilities
3913  myMetadata += "<p class=\"glossy\">" + tr( "Capabilities of this layer" ) + "</p>\n";
3914  myMetadata += "<p>";
3915  myMetadata += capabilitiesString();
3916  myMetadata += "</p>\n";
3917 
3918  //-------------
3919 
3920  QgsRectangle myExtent = extent();
3921  myMetadata += "<p class=\"subheaderglossy\">";
3922  myMetadata += tr( "Extents" );
3923  myMetadata += "</p>\n";
3924 
3925  //extents in layer cs TODO...maybe make a little nested table to improve layout...
3926  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
3927  myMetadata += "<p>";
3928  // Try to be a bit clever over what number format we use for the
3929  // extents. Some people don't like it using scientific notation when the
3930  // numbers get large, but for small numbers this is the more practical
3931  // option (so we can't force the format to 'f' for all values).
3932  // The scheme:
3933  // - for all numbers with more than 5 digits, force non-scientific notation
3934  // and 2 digits after the decimal point.
3935  // - for all smaller numbers let the OS decide which format to use (it will
3936  // generally use non-scientific unless the number gets much less than 1).
3937 
3938  if ( !myExtent.isEmpty() )
3939  {
3940  QString xMin, yMin, xMax, yMax;
3941  double changeoverValue = 99999; // The 'largest' 5 digit number
3942  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
3943  {
3944  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
3945  }
3946  else
3947  {
3948  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
3949  }
3950  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
3951  {
3952  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
3953  }
3954  else
3955  {
3956  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
3957  }
3958  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
3959  {
3960  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
3961  }
3962  else
3963  {
3964  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
3965  }
3966  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
3967  {
3968  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
3969  }
3970  else
3971  {
3972  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
3973  }
3974 
3975  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3976  .arg( xMin, yMin, xMax, yMax );
3977  }
3978  else
3979  {
3980  myMetadata += tr( "unknown extent" );
3981  }
3982 
3983  myMetadata += "</p>\n";
3984 
3985  //extents in project cs
3986 
3987  try
3988  {
3989 #if 0
3990  // TODO: currently disabled, will revisit later [MD]
3991  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
3992  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3993  myMetadata += "<p>";
3994  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3995  .arg( myProjectedExtent.xMinimum() )
3996  .arg( myProjectedExtent.yMinimum() )
3997  .arg( myProjectedExtent.xMaximum() )
3998  .arg( myProjectedExtent.yMaximum() );
3999  myMetadata += "</p>\n";
4000 #endif
4001 
4002  //
4003  // Display layer spatial ref system
4004  //
4005  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
4006  myMetadata += "<p>";
4007  myMetadata += crs().toProj4().replace( '"', " \"" );
4008  myMetadata += "</p>\n";
4009 
4010  //
4011  // Display project (output) spatial ref system
4012  //
4013 #if 0
4014  // TODO: disabled for now, will revisit later [MD]
4015  //myMetadata += "<tr><td bgcolor=\"gray\">";
4016  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
4017  myMetadata += "<p>";
4018  myMetadata += coordinateTransform->destCRS().toProj4().replace( '"', " \"" );
4019  myMetadata += "</p>\n";
4020 #endif
4021  }
4022  catch ( QgsCsException &cse )
4023  {
4024  Q_UNUSED( cse );
4025  QgsDebugMsg( cse.what() );
4026 
4027  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
4028  myMetadata += "<p>";
4029  myMetadata += tr( "(Invalid transformation of layer extents)" );
4030  myMetadata += "</p>\n";
4031 
4032  }
4033 
4034 #if 0
4035  //
4036  // Add the info about each field in the attribute table
4037  //
4038  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
4039  myMetadata += "<p>";
4040 
4041  // Start a nested table in this trow
4042  myMetadata += "<table width=\"100%\">";
4043  myMetadata += "<tr><th>";
4044  myMetadata += tr( "Field" );
4045  myMetadata += "</th>";
4046  myMetadata += "<th>";
4047  myMetadata += tr( "Type" );
4048  myMetadata += "</th>";
4049  myMetadata += "<th>";
4050  myMetadata += tr( "Length" );
4051  myMetadata += "</th>";
4052  myMetadata += "<th>";
4053  myMetadata += tr( "Precision" );
4054  myMetadata += "</th>";
4055  myMetadata += "<th>";
4056  myMetadata += tr( "Comment" );
4057  myMetadata += "</th>";
4058 
4059  //get info for each field by looping through them
4060  const QgsFields& myFields = pendingFields();
4061  for ( int i = 0, n = myFields.size(); i < n; ++i )
4062  {
4063  const QgsField& myField = fields[i];
4064 
4065  myMetadata += "<tr><td>";
4066  myMetadata += myField.name();
4067  myMetadata += "</td>";
4068  myMetadata += "<td>";
4069  myMetadata += myField.typeName();
4070  myMetadata += "</td>";
4071  myMetadata += "<td>";
4072  myMetadata += QString( "%1" ).arg( myField.length() );
4073  myMetadata += "</td>";
4074  myMetadata += "<td>";
4075  myMetadata += QString( "%1" ).arg( myField.precision() );
4076  myMetadata += "</td>";
4077  myMetadata += "<td>";
4078  myMetadata += QString( "%1" ).arg( myField.comment() );
4079  myMetadata += "</td></tr>";
4080  }
4081 
4082  //close field list
4083  myMetadata += "</table>"; //end of nested table
4084 #endif
4085 
4086  myMetadata += "</body></html>";
4087  return myMetadata;
4088 }
4089 
4091 {
4092  mSymbolFeatureCounted = false;
4093 }
4094 
4095 void QgsVectorLayer::onJoinedFieldsChanged()
4096 {
4097  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4098  updateFields();
4099 }
4100 
4101 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4102 {
4103  if ( mEditCommandActive )
4104  mDeletedFids << fid;
4105  else
4106  emit featuresDeleted( QgsFeatureIds() << fid );
4107 
4108  emit featureDeleted( fid );
4109 }
4110 
4112 {
4113  if ( mEditFormConfig->widgetType( idx ) == "ValueRelation" )
4114  {
4115  QgsEditorWidgetConfig cfg = mEditFormConfig->widgetConfig( idx );
4116 
4117  return ValueRelationData( cfg.value( "Layer" ).toString(),
4118  cfg.value( "Key" ).toString(),
4119  cfg.value( "Value" ).toString(),
4120  cfg.value( "AllowNull" ).toBool(),
4121  cfg.value( "OrderByValue" ).toBool(),
4122  cfg.value( "AllowMulti" ).toBool(),
4123  cfg.value( "FilterExpression" ).toString()
4124  );
4125  }
4126  else
4127  {
4128  return ValueRelationData();
4129  }
4130 }
4131 
4133 {
4134  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4135 }
4136 
4138 {
4140  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4141  if ( !myLib )
4142  {
4143  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4144  return -1;
4145  }
4146  listStyles_t* listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
4147 
4148  if ( !listStylesExternalMethod )
4149  {
4150  delete myLib;
4151  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "listStyles" );
4152  return -1;
4153  }
4154 
4155  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
4156 }
4157 
4159 {
4161  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4162  if ( !myLib )
4163  {
4164  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4165  return QObject::tr( "" );
4166  }
4167  getStyleById_t* getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
4168 
4169  if ( !getStyleByIdMethod )
4170  {
4171  delete myLib;
4172  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "getStyleById" );
4173  return QObject::tr( "" );
4174  }
4175 
4176  return getStyleByIdMethod( mDataSource, styleId, msgError );
4177 }
4178 
4179 
4180 void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& description,
4181  bool useAsDefault, const QString& uiFileContent, QString &msgError )
4182 {
4183 
4184  QString sldStyle, qmlStyle;
4186  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4187  if ( !myLib )
4188  {
4189  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4190  return;
4191  }
4192  saveStyle_t* saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4193 
4194  if ( !saveStyleExternalMethod )
4195  {
4196  delete myLib;
4197  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "saveStyle" );
4198  return;
4199  }
4200 
4201  QDomDocument qmlDocument, sldDocument;
4202  this->exportNamedStyle( qmlDocument, msgError );
4203  if ( !msgError.isNull() )
4204  {
4205  return;
4206  }
4207  qmlStyle = qmlDocument.toString();
4208 
4209  this->exportSldStyle( sldDocument, msgError );
4210  if ( !msgError.isNull() )
4211  {
4212  return;
4213  }
4214  sldStyle = sldDocument.toString();
4215 
4216  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4217  description, uiFileContent, useAsDefault, msgError );
4218 }
4219 
4220 
4221 
4222 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
4223 {
4224  return loadNamedStyle( theURI, theResultFlag, false );
4225 }
4226 
4227 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
4228 {
4229  QgsDataSourceURI dsUri( theURI );
4230  if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
4231  {
4233  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4234  if ( myLib )
4235  {
4236  loadStyle_t* loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4237  if ( loadStyleExternalMethod )
4238  {
4239  QString qml, errorMsg;
4240  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4241  if ( !qml.isEmpty() )
4242  {
4244  theResultFlag = applyNamedStyle( qml, errorMsg );
4246  return QObject::tr( "Loaded from Provider" );
4247  }
4248  }
4249  }
4250  }
4251 
4252  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
4253 }
4254 
4255 bool QgsVectorLayer::applyNamedStyle( const QString& namedStyle, QString& errorMsg )
4256 {
4257  QDomDocument myDocument( "qgis" );
4258  myDocument.setContent( namedStyle );
4259 
4260  return importNamedStyle( myDocument, errorMsg );
4261 }
4262 
4264 {
4265  if ( mDataProvider )
4266  {
4267  return mDataProvider->layerDependencies();
4268  }
4269  return QSet<QString>();
4270 }
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.
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.
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
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:217
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
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.
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.
QString name
Definition: qgsfield.h:52
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith="")
Read custom properties from project file.
int precision
Definition: qgsfield.h:50
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 the maximum value for an attribute column or an 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:218
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)
Calculates a list of unique values contained within an attribute in the layer.
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:539
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)
QString comment
Definition: qgsfield.h:51
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:515
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:209
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.
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:216
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.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
Definition: qgis.cpp:337
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 the minimum value for an attribute column or an 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
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:269
it has not been specified where the field comes from
Definition: qgsfield.h:215
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.
int length
Definition: qgsfield.h:49
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
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
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.
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.
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
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.
const T & value() const
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:390
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
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.
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:29
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)
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:375
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
void recalculateExtents()
This is used to send a request that any mapcanvas using this layer update its extents.
int length() const
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.
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.
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
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.
A vector of attributes.
Definition: qgsfeature.h:115
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QgsFeatureIds allFeatureIds()
Get all feature Ids.
static QgsFeatureRendererV2 * readOldRenderer(const QDomNode &layerNode, QGis::GeometryType geomType)
Read old renderer definition from XML and create matching new renderer.
virtual QgsRectangle extent()
Return the extent of the layer.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QgsAttributeTableConfig attributeTableConfig() const
Get the attribute table configuration object.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void modifySelection(QgsFeatureIds selectIds, QgsFeatureIds deselectIds)
Modifies the curre