QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 pkeyElem = pkeyNode.toElement();
1634  if ( !pkeyElem.isNull() )
1635  {
1636  QString encodingString = pkeyElem.attribute( "encoding" );
1637  if ( !encodingString.isEmpty() )
1638  {
1639  mDataProvider->setEncoding( encodingString );
1640  }
1641  }
1642 
1643  //load vector joins
1644  if ( !mJoinBuffer )
1645  {
1646  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1647  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1648  }
1649  mJoinBuffer->readXml( layer_node );
1650 
1651  if ( !mExpressionFieldBuffer )
1652  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1653  mExpressionFieldBuffer->readXml( layer_node );
1654 
1655  updateFields();
1656  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1657 
1658  QString errorMsg;
1659  if ( !readSymbology( layer_node, errorMsg ) )
1660  {
1661  return false;
1662  }
1663 
1664  readStyleManager( layer_node );
1665 
1666  updateFields();
1667 
1669 
1670  return mValid; // should be true if read successfully
1671 
1672 } // void QgsVectorLayer::readXml
1673 
1674 
1675 void QgsVectorLayer::setDataSource( const QString& dataSource, const QString& baseName, const QString& provider, bool loadDefaultStyleFlag )
1676 {
1677  QGis::GeometryType oldGeomType = mValid && mDataProvider ? geometryType() : QGis::UnknownGeometry;
1678 
1679  mDataSource = dataSource;
1680  mLayerName = capitaliseLayerName( baseName );
1681  setName( mLayerName );
1682  setDataProvider( provider );
1683 
1684  if ( !mValid )
1685  return;
1686 
1687  // Always set crs
1689 
1690  // reset style if loading default style, style is missing, or geometry type has changed
1691  if ( !rendererV2() || !legend() || oldGeomType != geometryType() || loadDefaultStyleFlag )
1692  {
1693  // check if there is a default style / propertysheet defined
1694  // for this layer and if so apply it
1695  bool defaultLoadedFlag = false;
1696  if ( loadDefaultStyleFlag )
1697  {
1698  loadDefaultStyle( defaultLoadedFlag );
1699  }
1700 
1701  // if the default style failed to load or was disabled use some very basic defaults
1702  if ( !defaultLoadedFlag && hasGeometryType() )
1703  {
1704  // add single symbol renderer
1706  }
1707 
1709  }
1710 
1711  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1712  emit repaintRequested();
1713 }
1714 
1715 
1716 bool QgsVectorLayer::setDataProvider( QString const & provider )
1717 {
1718  mProviderKey = provider; // XXX is this necessary? Usually already set
1719  // XXX when execution gets here.
1720 
1721  //XXX - This was a dynamic cast but that kills the Windows
1722  // version big-time with an abnormal termination error
1723  delete mDataProvider;
1724  mDataProvider = ( QgsVectorDataProvider* )( QgsProviderRegistry::instance()->provider( provider, mDataSource ) );
1725  if ( !mDataProvider )
1726  {
1727  QgsDebugMsg( " unable to get data provider" );
1728  return false;
1729  }
1730 
1731  connect( mDataProvider, SIGNAL( raiseError( QString ) ), this, SIGNAL( raiseError( QString ) ) );
1732 
1733  QgsDebugMsg( "Instantiated the data provider plugin" );
1734 
1735  mValid = mDataProvider->isValid();
1736  if ( !mValid )
1737  {
1738  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1739  return false;
1740  }
1741 
1742  // TODO: Check if the provider has the capability to send fullExtentCalculated
1743  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
1744 
1745  // get and store the feature type
1746  mWkbType = mDataProvider->geometryType();
1747 
1748  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1749  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1750  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1751  updateFields();
1752 
1753  // look at the fields in the layer and set the primary
1754  // display field using some real fuzzy logic
1755  setDisplayField();
1756 
1757  if ( mProviderKey == "postgres" )
1758  {
1759  QgsDebugMsg( "Beautifying layer name " + name() );
1760 
1761  // adjust the display name for postgres layers
1762  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1763  if ( reg.indexIn( name() ) >= 0 )
1764  {
1765  QStringList stuff = reg.capturedTexts();
1766  QString lName = stuff[1];
1767 
1769 
1771  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1772  ;
1773 
1774  if ( it != layers.constEnd() && stuff.size() > 2 )
1775  {
1776  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1777  }
1778 
1779  if ( !lName.isEmpty() )
1780  setName( lName );
1781  }
1782 
1783  QgsDebugMsg( "Beautified layer name " + name() );
1784 
1785  // deal with unnecessary schema qualification to make v.in.ogr happy
1786  mDataSource = mDataProvider->dataSourceUri();
1787  }
1788  else if ( mProviderKey == "osm" )
1789  {
1790  // make sure that the "observer" has been removed from URI to avoid crashes
1791  mDataSource = mDataProvider->dataSourceUri();
1792  }
1793  else if ( provider == "ogr" )
1794  {
1795  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1796  mDataSource = mDataProvider->dataSourceUri();
1797  if ( mDataSource.right( 10 ) == "|layerid=0" )
1798  mDataSource.chop( 10 );
1799  }
1800 
1801  // label
1802  mLabel = new QgsLabel( mDataProvider->fields() );
1803  mLabelOn = false;
1804 
1805  connect( mDataProvider, SIGNAL( dataChanged() ), this, SIGNAL( dataChanged() ) );
1806  connect( mDataProvider, SIGNAL( dataChanged() ), this, SLOT( removeSelection() ) );
1807 
1808  return true;
1809 } // QgsVectorLayer:: setDataProvider
1810 
1811 
1812 
1813 
1814 /* virtual */
1816  QDomDocument & document )
1817 {
1818  // first get the layer element so that we can append the type attribute
1819 
1820  QDomElement mapLayerNode = layer_node.toElement();
1821 
1822  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1823  {
1824  QgsDebugMsg( "can't find <maplayer>" );
1825  return false;
1826  }
1827 
1828  mapLayerNode.setAttribute( "type", "vector" );
1829 
1830  // set the geometry type
1831  mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
1832 
1833  // add provider node
1834  if ( mDataProvider )
1835  {
1836  QDomElement provider = document.createElement( "provider" );
1837  provider.setAttribute( "encoding", mDataProvider->encoding() );
1838  QDomText providerText = document.createTextNode( providerType() );
1839  provider.appendChild( providerText );
1840  layer_node.appendChild( provider );
1841  }
1842 
1843  //save joins
1844  mJoinBuffer->writeXml( layer_node, document );
1845 
1846  // dependencies
1847  QDomElement dependenciesElement = document.createElement( "layerDependencies" );
1848  Q_FOREACH ( QString layerId, layerDependencies() )
1849  {
1850  QDomElement depElem = document.createElement( "layer" );
1851  depElem.setAttribute( "id", layerId );
1852  dependenciesElement.appendChild( depElem );
1853  }
1854  layer_node.appendChild( dependenciesElement );
1855 
1856  // save expression fields
1857  mExpressionFieldBuffer->writeXml( layer_node, document );
1858 
1859  writeStyleManager( layer_node, document );
1860 
1861  // renderer specific settings
1862  QString errorMsg;
1863  return writeSymbology( layer_node, document, errorMsg );
1864 } // bool QgsVectorLayer::writeXml
1865 
1866 
1867 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
1868 {
1869  updateFields();
1870 
1871  readStyle( node, errorMessage );
1872 
1873  // process the attribute actions
1874  mActions->readXML( node );
1875 
1876  mEditFormConfig->readXml( node );
1877 
1878  QDomNode annotationFormNode = node.namedItem( "annotationform" );
1879  if ( !annotationFormNode.isNull() )
1880  {
1881  QDomElement e = annotationFormNode.toElement();
1882  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1883  }
1884 
1885  mAttributeAliasMap.clear();
1886  QDomNode aliasesNode = node.namedItem( "aliases" );
1887  if ( !aliasesNode.isNull() )
1888  {
1889  QDomElement aliasElem;
1890 
1891  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
1892  for ( int i = 0; i < aliasNodeList.size(); ++i )
1893  {
1894  aliasElem = aliasNodeList.at( i ).toElement();
1895 
1896  QString field;
1897  if ( aliasElem.hasAttribute( "field" ) )
1898  {
1899  field = aliasElem.attribute( "field" );
1900  }
1901  else
1902  {
1903  int index = aliasElem.attribute( "index" ).toInt();
1904 
1905  if ( index >= 0 && index < fields().count() )
1906  field = fields().at( index ).name();
1907  }
1908 
1909  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
1910  }
1911  }
1912  // default expressions
1913  mDefaultExpressionMap.clear();
1914  QDomNode defaultsNode = node.namedItem( "defaults" );
1915  if ( !defaultsNode.isNull() )
1916  {
1917  QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( "default" );
1918  for ( int i = 0; i < defaultNodeList.size(); ++i )
1919  {
1920  QDomElement defaultElem = defaultNodeList.at( i ).toElement();
1921 
1922  QString field = defaultElem.attribute( "field", QString() );
1923  QString expression = defaultElem.attribute( "expression", QString() );
1924  if ( field.isEmpty() || expression.isEmpty() )
1925  continue;
1926 
1927  mDefaultExpressionMap.insert( field, expression );
1928  }
1929  }
1930  updateFields();
1931 
1932  //Attributes excluded from WMS and WFS
1933  mExcludeAttributesWMS.clear();
1934  QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
1935  if ( !excludeWMSNode.isNull() )
1936  {
1937  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
1938  for ( int i = 0; i < attributeNodeList.size(); ++i )
1939  {
1940  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1941  }
1942  }
1943 
1944  mExcludeAttributesWFS.clear();
1945  QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
1946  if ( !excludeWFSNode.isNull() )
1947  {
1948  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
1949  for ( int i = 0; i < attributeNodeList.size(); ++i )
1950  {
1951  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1952  }
1953  }
1954 
1955  mEditFormConfig->readXml( node );
1956 
1957  mAttributeTableConfig.readXml( node );
1958 
1959  mConditionalStyles->readXml( node );
1960 
1961  QDomNode prevExpNode = node.namedItem( "previewExpression" );
1962 
1963  if ( prevExpNode.isNull() )
1964  {
1965  mDisplayExpression = "";
1966  }
1967  else
1968  {
1969  QDomElement prevExpElem = prevExpNode.toElement();
1970  mDisplayExpression = prevExpElem.text();
1971  }
1972 
1973 
1974  readCustomProperties( node, "variable" );
1975 
1976  QDomElement mapLayerNode = node.toElement();
1977  if ( mapLayerNode.attribute( "readOnly", "0" ).toInt() == 1 )
1978  mReadOnly = true;
1979 
1980  return true;
1981 }
1982 
1983 bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage )
1984 {
1985  emit readCustomSymbology( node.toElement(), errorMessage );
1986 
1987  if ( hasGeometryType() )
1988  {
1989  // try renderer v2 first
1990  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1991  if ( !rendererElement.isNull() )
1992  {
1993  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
1994  if ( !r )
1995  return false;
1996 
1997  setRendererV2( r );
1998  }
1999  else
2000  {
2002  if ( !r )
2004 
2005  setRendererV2( r );
2006  }
2007 
2008  QDomElement labelingElement = node.firstChildElement( "labeling" );
2009  if ( !labelingElement.isNull() )
2010  {
2013  }
2014 
2015  // get and set the display field if it exists.
2016  QDomNode displayFieldNode = node.namedItem( "displayfield" );
2017  if ( !displayFieldNode.isNull() )
2018  {
2019  QDomElement e = displayFieldNode.toElement();
2020  setDisplayField( e.text() );
2021  }
2022 
2023  // get and set the blend mode if it exists
2024  QDomNode blendModeNode = node.namedItem( "blendMode" );
2025  if ( !blendModeNode.isNull() )
2026  {
2027  QDomElement e = blendModeNode.toElement();
2028  setBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
2029  }
2030 
2031  // get and set the feature blend mode if it exists
2032  QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
2033  if ( !featureBlendModeNode.isNull() )
2034  {
2035  QDomElement e = featureBlendModeNode.toElement();
2036  setFeatureBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
2037  }
2038 
2039  // get and set the layer transparency if it exists
2040  QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
2041  if ( !layerTransparencyNode.isNull() )
2042  {
2043  QDomElement e = layerTransparencyNode.toElement();
2044  setLayerTransparency( e.text().toInt() );
2045  }
2046 
2047  // use scale dependent visibility flag
2048  QDomElement e = node.toElement();
2049  if ( mLabel )
2050  {
2051  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
2052  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
2053  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
2054  }
2055 
2056  // get the simplification drawing settings
2057  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( "simplifyDrawingHints", "1" ).toInt() ) );
2058  mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( "simplifyAlgorithm", "0" ).toInt() ) );
2059  mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
2060  mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
2061  mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
2062 
2063  //also restore custom properties (for labeling-ng)
2064  readCustomProperties( node, "labeling" );
2065 
2066  // Test if labeling is on or off
2067  QDomNode labelnode = node.namedItem( "label" );
2068  QDomElement element = labelnode.toElement();
2069  int hasLabelsEnabled = element.text().toInt();
2071  if ( hasLabelsEnabled < 1 )
2072  {
2073  enableLabels( false );
2074  }
2075  else
2076  {
2077  enableLabels( true );
2078  }
2080 
2081  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
2082 
2083  if ( !labelattributesnode.isNull() && mLabel )
2084  {
2085  mLabel->readXML( labelattributesnode );
2086  }
2087 
2088  //diagram renderer and diagram layer settings
2089  delete mDiagramRenderer;
2090  mDiagramRenderer = nullptr;
2091  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
2092  if ( !singleCatDiagramElem.isNull() )
2093  {
2094  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2095  mDiagramRenderer->readXML( singleCatDiagramElem, this );
2096  }
2097  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
2098  if ( !linearDiagramElem.isNull() )
2099  {
2100  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2101  mDiagramRenderer->readXML( linearDiagramElem, this );
2102  }
2103 
2104  if ( mDiagramRenderer )
2105  {
2106  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
2107  if ( !diagramSettingsElem.isNull() )
2108  {
2109  delete mDiagramLayerSettings;
2110  mDiagramLayerSettings = new QgsDiagramLayerSettings();
2111  mDiagramLayerSettings->readXML( diagramSettingsElem, this );
2112  }
2113  }
2114  }
2115  return true;
2116 }
2117 
2118 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2119 {
2120  ( void )writeStyle( node, doc, errorMessage );
2121 
2122  // FIXME
2123  // edittypes are written to the layerNode
2124  // by slot QgsEditorWidgetRegistry::writeMapLayer()
2125  // triggered by signal QgsProject::writeMapLayer()
2126  // still other editing settings are written here,
2127  // although they are not part of symbology either
2128 
2129  QDomElement afField = doc.createElement( "annotationform" );
2130  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
2131  afField.appendChild( afText );
2132  node.appendChild( afField );
2133 
2134  //attribute aliases
2135  QDomElement aliasElem = doc.createElement( "aliases" );
2136  Q_FOREACH ( const QgsField& field, mUpdatedFields )
2137  {
2138  QDomElement aliasEntryElem = doc.createElement( "alias" );
2139  aliasEntryElem.setAttribute( "field", field.name() );
2140  aliasEntryElem.setAttribute( "index", mUpdatedFields.indexFromName( field.name() ) );
2141  aliasEntryElem.setAttribute( "name", field.alias() );
2142  aliasElem.appendChild( aliasEntryElem );
2143  }
2144  node.appendChild( aliasElem );
2145 
2146  //exclude attributes WMS
2147  QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
2148  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2149  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2150  {
2151  QDomElement attrElem = doc.createElement( "attribute" );
2152  QDomText attrText = doc.createTextNode( *attWMSIt );
2153  attrElem.appendChild( attrText );
2154  excludeWMSElem.appendChild( attrElem );
2155  }
2156  node.appendChild( excludeWMSElem );
2157 
2158  //exclude attributes WFS
2159  QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
2160  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2161  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2162  {
2163  QDomElement attrElem = doc.createElement( "attribute" );
2164  QDomText attrText = doc.createTextNode( *attWFSIt );
2165  attrElem.appendChild( attrText );
2166  excludeWFSElem.appendChild( attrElem );
2167  }
2168  node.appendChild( excludeWFSElem );
2169 
2170  // add attribute actions
2171  mActions->writeXML( node, doc );
2172  mAttributeTableConfig.writeXml( node );
2173  mEditFormConfig->writeXml( node );
2174  mConditionalStyles->writeXml( node, doc );
2175 
2176  // save readonly state
2177  node.toElement().setAttribute( "readOnly", mReadOnly );
2178 
2179  //default expressions
2180  QDomElement defaultsElem = node.ownerDocument().createElement( "defaults" );
2181  Q_FOREACH ( const QgsField& field, mUpdatedFields )
2182  {
2183  QDomElement defaultElem = doc.createElement( "default" );
2184  defaultElem.setAttribute( "field", field.name() );
2185  defaultElem.setAttribute( "expression", field.defaultValueExpression() );
2186  defaultsElem.appendChild( defaultElem );
2187  }
2188  node.appendChild( defaultsElem );
2189 
2190  // preview expression
2191  QDomElement prevExpElem = doc.createElement( "previewExpression" );
2192  QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2193  prevExpElem.appendChild( prevExpText );
2194  node.appendChild( prevExpElem );
2195 
2196  return true;
2197 }
2198 
2199 bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage ) const
2200 {
2201  QDomElement mapLayerNode = node.toElement();
2202 
2203  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2204 
2205  if ( hasGeometryType() )
2206  {
2207  if ( mRendererV2 )
2208  {
2209  QDomElement rendererElement = mRendererV2->save( doc );
2210  node.appendChild( rendererElement );
2211  }
2212 
2213  if ( mLabeling )
2214  {
2215  QDomElement labelingElement = mLabeling->save( doc );
2216  node.appendChild( labelingElement );
2217  }
2218 
2219  // use scale dependent visibility flag
2220  if ( mLabel )
2221  {
2222  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
2223  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
2224  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
2225  }
2226 
2227  // save the simplification drawing settings
2228  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
2229  mapLayerNode.setAttribute( "simplifyAlgorithm", QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2230  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
2231  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2232  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
2233 
2234  //save customproperties (for labeling ng)
2235  writeCustomProperties( node, doc );
2236 
2237  // add the blend mode field
2238  QDomElement blendModeElem = doc.createElement( "blendMode" );
2240  blendModeElem.appendChild( blendModeText );
2241  node.appendChild( blendModeElem );
2242 
2243  // add the feature blend mode field
2244  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
2246  featureBlendModeElem.appendChild( featureBlendModeText );
2247  node.appendChild( featureBlendModeElem );
2248 
2249  // add the layer transparency
2250  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
2251  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
2252  layerTransparencyElem.appendChild( layerTransparencyText );
2253  node.appendChild( layerTransparencyElem );
2254 
2255  // add the display field
2256  QDomElement dField = doc.createElement( "displayfield" );
2257  QDomText dFieldText = doc.createTextNode( displayField() );
2258  dField.appendChild( dFieldText );
2259  node.appendChild( dField );
2260 
2261  // add label node
2262  QDomElement labelElem = doc.createElement( "label" );
2263  QDomText labelText = doc.createTextNode( "" );
2264 
2266  if ( hasLabelsEnabled() )
2267  {
2268  labelText.setData( "1" );
2269  }
2270  else
2271  {
2272  labelText.setData( "0" );
2273  }
2275  labelElem.appendChild( labelText );
2276 
2277  node.appendChild( labelElem );
2278 
2279  // Now we get to do all that all over again for QgsLabel
2280 
2281  if ( mLabel )
2282  {
2283  QString fieldname = mLabel->labelField( QgsLabel::Text );
2284  if ( fieldname != "" )
2285  {
2286  dField = doc.createElement( "labelfield" );
2287  dFieldText = doc.createTextNode( fieldname );
2288  dField.appendChild( dFieldText );
2289  node.appendChild( dField );
2290  }
2291 
2292  mLabel->writeXML( node, doc );
2293  }
2294 
2295  if ( mDiagramRenderer )
2296  {
2297  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
2298  if ( mDiagramLayerSettings )
2299  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
2300  }
2301  }
2302  return true;
2303 }
2304 
2305 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2306 {
2307  // get the Name element
2308  QDomElement nameElem = node.firstChildElement( "Name" );
2309  if ( nameElem.isNull() )
2310  {
2311  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
2312  }
2313 
2314  if ( hasGeometryType() )
2315  {
2316  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
2317  if ( !r )
2318  return false;
2319 
2320  setRendererV2( r );
2321 
2322  // labeling
2323  readSldLabeling( node );
2324  }
2325  return true;
2326 }
2327 
2328 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2329 {
2330  return writeSld( node, doc, errorMessage, QgsStringMap() );
2331 }
2332 
2333 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, const QgsStringMap& props ) const
2334 {
2335  Q_UNUSED( errorMessage );
2336 
2337  // store the Name element
2338  QDomElement nameNode = doc.createElement( "se:Name" );
2339  nameNode.appendChild( doc.createTextNode( name() ) );
2340  node.appendChild( nameNode );
2341 
2342  QgsStringMap localProps = QgsStringMap( props );
2343  if ( hasScaleBasedVisibility() )
2344  {
2346  }
2347 
2348  if ( hasGeometryType() )
2349  {
2350  node.appendChild( mRendererV2->writeSld( doc, name(), localProps ) );
2351  }
2352  return true;
2353 }
2354 
2355 
2357 {
2358  if ( !mEditBuffer || !mDataProvider )
2359  {
2360  return false;
2361  }
2362 
2363  updateExtents();
2364 
2365  bool result = mEditBuffer->changeGeometry( fid, geom );
2366 
2367  if ( result )
2368  updateExtents();
2369  return result;
2370 }
2371 
2372 
2373 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant& value, bool emitSignal )
2374 {
2375  Q_UNUSED( emitSignal );
2376  return changeAttributeValue( fid, field, value );
2377 }
2378 
2379 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2380 {
2381  if ( !mEditBuffer || !mDataProvider )
2382  return false;
2383 
2384  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2385 }
2386 
2388 {
2389  bool result = true;
2390 
2391  QgsAttributeMap newValidValues;
2392  QgsAttributeMap oldValidValues;
2393 
2394  QgsAttributeMap::const_iterator it;
2395  for ( it = newValues.constBegin(); it != newValues.constEnd(); ++it )
2396  {
2397  const int field = it.key();
2398  const QVariant newValue = it.value();
2399  QVariant oldValue;
2400 
2401  if ( oldValues.contains( field ) )
2402  oldValue = oldValues[field];
2403 
2404  switch ( fields().fieldOrigin( field ) )
2405  {
2407  case QgsFields::OriginEdit:
2409  {
2410  newValidValues[field] = newValue;
2411  oldValidValues[field] = oldValue;
2412  break;
2413  }
2414 
2415  case QgsFields::OriginJoin:
2417  break;
2418  }
2419  }
2420 
2421  if ( ! newValidValues.isEmpty() && mEditBuffer && mDataProvider )
2422  {
2423  result &= mEditBuffer->changeAttributeValues( fid, newValidValues, oldValidValues );
2424  }
2425 
2426  return result;
2427 }
2428 
2430 {
2431  if ( !mEditBuffer || !mDataProvider )
2432  return false;
2433 
2434  return mEditBuffer->addAttribute( field );
2435 }
2436 
2438 {
2439  if ( attIndex < 0 || attIndex >= fields().count() )
2440  return;
2441 
2442  QString name = fields().at( attIndex ).name();
2443  mUpdatedFields[ attIndex ].setAlias( QString() );
2444  if ( mAttributeAliasMap.contains( name ) )
2445  {
2446  mAttributeAliasMap.remove( name );
2447  updateFields();
2448  emit layerModified();
2449  }
2450 }
2451 
2452 bool QgsVectorLayer::renameAttribute( int index, const QString& newName )
2453 {
2454  if ( index < 0 || index >= fields().count() )
2455  return false;
2456 
2457  switch ( mUpdatedFields.fieldOrigin( index ) )
2458  {
2460  {
2461  if ( mExpressionFieldBuffer )
2462  {
2463  int oi = mUpdatedFields.fieldOriginIndex( index );
2464  mExpressionFieldBuffer->renameExpression( oi, newName );
2465  updateFields();
2466  return true;
2467  }
2468  else
2469  {
2470  return false;
2471  }
2472  }
2473 
2475  case QgsFields::OriginEdit:
2476 
2477  if ( !mEditBuffer || !mDataProvider )
2478  return false;
2479 
2480  return mEditBuffer->renameAttribute( index, newName );
2481 
2482  case QgsFields::OriginJoin:
2484  return false;
2485 
2486  }
2487 
2488  return false; //avoid warning
2489 }
2490 
2491 void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString )
2492 {
2493  if ( attIndex < 0 || attIndex >= fields().count() )
2494  return;
2495 
2496  QString name = fields().at( attIndex ).name();
2497 
2498  mAttributeAliasMap.insert( name, aliasString );
2499  mUpdatedFields[ attIndex ].setAlias( aliasString );
2500  emit layerModified(); // TODO[MD]: should have a different signal?
2501 }
2502 
2503 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2504 {
2505  if ( attributeIndex < 0 || attributeIndex >= fields().count() )
2506  return QString();
2507 
2508  return fields().at( attributeIndex ).alias();
2509 }
2510 
2512 {
2513  if ( attributeIndex >= 0 && attributeIndex < mUpdatedFields.count() )
2514  return mUpdatedFields.at( attributeIndex ).displayName();
2515  else
2516  return QString();
2517 }
2518 
2520 {
2521  QgsStringMap map;
2522  Q_FOREACH ( const QgsField& field, fields() )
2523  {
2524  if ( !field.alias().isEmpty() )
2525  map.insert( field.name(), field.alias() );
2526  }
2527  return map;
2528 }
2529 
2531 {
2532  if ( index < 0 || index >= fields().count() )
2533  return false;
2534 
2535  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2536  {
2537  removeExpressionField( index );
2538  return true;
2539  }
2540 
2541  if ( !mEditBuffer || !mDataProvider )
2542  return false;
2543 
2544  return mEditBuffer->deleteAttribute( index );
2545 }
2546 
2548 {
2549  bool deleted = false;
2550 
2551  // Remove multiple occurrences of same attribute
2552  attrs = attrs.toSet().toList();
2553 
2554  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2555 
2556  Q_FOREACH ( int attr, attrs )
2557  {
2558  if ( deleteAttribute( attr ) )
2559  {
2560  deleted = true;
2561  }
2562  }
2563 
2564  return deleted;
2565 }
2566 
2568 {
2569  if ( !mEditBuffer )
2570  return false;
2571 
2572  bool res = mEditBuffer->deleteFeature( fid );
2573  if ( res )
2574  {
2575  mSelectedFeatureIds.remove( fid ); // remove it from selection
2576  updateExtents();
2577  }
2578 
2579  return res;
2580 }
2581 
2583 {
2584  if ( !mEditBuffer )
2585  return false;
2586 
2587  bool res = mEditBuffer->deleteFeatures( fids );
2588 
2589  if ( res )
2590  {
2591  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2592  updateExtents();
2593  }
2594 
2595  return res;
2596 }
2597 
2599 {
2600  QgsAttributeList pkAttributesList;
2601 
2602  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2603  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2604  {
2605  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2606  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2607  pkAttributesList << i;
2608  }
2609 
2610  return pkAttributesList;
2611 }
2612 
2614 {
2615  return mDataProvider->featureCount() +
2616  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2617 }
2618 
2620 {
2621  mCommitErrors.clear();
2622 
2623  if ( !mDataProvider )
2624  {
2625  mCommitErrors << tr( "ERROR: no provider" );
2626  return false;
2627  }
2628 
2629  if ( !mEditBuffer )
2630  {
2631  mCommitErrors << tr( "ERROR: layer not editable" );
2632  return false;
2633  }
2634 
2635  emit beforeCommitChanges();
2636 
2637  bool success = mEditBuffer->commitChanges( mCommitErrors );
2638 
2639  if ( success )
2640  {
2641  delete mEditBuffer;
2642  mEditBuffer = nullptr;
2643  undoStack()->clear();
2644  emit editingStopped();
2645  }
2646  else
2647  {
2648  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2649  }
2650 
2651  if ( mCache )
2652  {
2653  mCache->deleteCachedGeometries();
2654  }
2655 
2656  updateFields();
2657  mDataProvider->updateExtents();
2658 
2659  mDataProvider->leaveUpdateMode();
2660 
2661  emit repaintRequested();
2662 
2663  return success;
2664 }
2665 
2667 {
2668  return mCommitErrors;
2669 }
2670 
2671 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2672 {
2673  if ( !mEditBuffer )
2674  {
2675  return false;
2676  }
2677 
2678  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2679  !mEditBuffer->mAddedFeatures.isEmpty() ||
2680  !mEditBuffer->mChangedGeometries.isEmpty();
2681 
2682  emit beforeRollBack();
2683 
2684  mEditBuffer->rollBack();
2685 
2686  if ( isModified() )
2687  {
2688  // new undo stack roll back method
2689  // old method of calling every undo could cause many canvas refreshes
2690  undoStack()->setIndex( 0 );
2691  }
2692 
2693  updateFields();
2694 
2695  if ( deleteBuffer )
2696  {
2697  delete mEditBuffer;
2698  mEditBuffer = nullptr;
2699  undoStack()->clear();
2700  }
2701  emit editingStopped();
2702 
2703  if ( mCache )
2704  {
2705  mCache->deleteCachedGeometries();
2706  }
2707 
2708  if ( rollbackExtent )
2709  updateExtents();
2710 
2711  mDataProvider->leaveUpdateMode();
2712 
2713  emit repaintRequested();
2714  return true;
2715 }
2716 
2718 {
2719  selectByIds( ids, SetSelection );
2720 }
2721 
2723 {
2724  return mSelectedFeatureIds.size();
2725 }
2726 
2728 {
2729  return mSelectedFeatureIds;
2730 }
2731 
2733 {
2734  QgsFeatureList features;
2735  QgsFeature f;
2736 
2737  if ( mSelectedFeatureIds.count() <= 8 )
2738  {
2739  // for small amount of selected features, fetch them directly
2740  // because request with FilterFids would go iterate over the whole layer
2741  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2742  {
2743  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2744  features << f;
2745  }
2746  }
2747  else
2748  {
2750 
2751  while ( it.nextFeature( f ) )
2752  {
2753  features.push_back( f );
2754  }
2755  }
2756 
2757  return features;
2758 }
2759 
2761 {
2762  if ( mSelectedFeatureIds.isEmpty() )
2763  return QgsFeatureIterator();
2764 
2765  if ( geometryType() == QGis::NoGeometry )
2767 
2768  if ( mSelectedFeatureIds.count() == 1 )
2769  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2770  else
2771  request.setFilterFids( mSelectedFeatureIds );
2772 
2773  return getFeatures( request );
2774 }
2775 
2776 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2777 {
2778  if ( !mEditBuffer || !mDataProvider )
2779  return false;
2780 
2781  bool res = mEditBuffer->addFeatures( features );
2782 
2783  if ( makeSelected )
2784  {
2785  QgsFeatureIds ids;
2786 
2787  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2788  ids << iter->id();
2789 
2790  selectByIds( ids );
2791  }
2792 
2793  updateExtents();
2794 
2795  return res;
2796 }
2797 
2798 
2799 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2800 {
2801  if ( !hasGeometryType() )
2802  return false;
2803 
2805  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2806 
2807  if ( result != 0 )
2808  {
2809  return false;
2810  }
2811 
2812  if ( snapResults.size() < 1 )
2813  {
2814  return false;
2815  }
2816 
2818  point.setX( snap_it.value().snappedVertex.x() );
2819  point.setY( snap_it.value().snappedVertex.y() );
2820  return true;
2821 }
2822 
2823 
2824 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2825  QMultiMap<double, QgsSnappingResult>& snappingResults,
2826  QgsSnapper::SnappingType snap_to )
2827 {
2828  if ( !hasGeometryType() )
2829  return 1;
2830 
2831  if ( snappingTolerance <= 0 || !mDataProvider )
2832  {
2833  return 1;
2834  }
2835 
2836  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2837  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2838  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2839 
2840  int n = 0;
2841  QgsFeature f;
2842 
2843  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2844  {
2845  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2846  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2847  {
2848  QgsGeometry* g = &( it.value() );
2849  if ( g->boundingBox().intersects( searchRect ) )
2850  {
2851  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2852  ++n;
2853  }
2854  }
2855  }
2856  else
2857  {
2858  // snapping outside cached area
2859 
2861  .setFilterRect( searchRect )
2863  .setSubsetOfAttributes( QgsAttributeList() ) );
2864 
2865  while ( fit.nextFeature( f ) )
2866  {
2867  snapToGeometry( startPoint, f.id(), f.constGeometry(), sqrSnappingTolerance, snappingResults, snap_to );
2868  ++n;
2869  }
2870  }
2871 
2872  return n == 0 ? 2 : 0;
2873 }
2874 
2875 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2876  QgsFeatureId featureId,
2877  const QgsGeometry* geom,
2878  double sqrSnappingTolerance,
2879  QMultiMap<double, QgsSnappingResult>& snappingResults,
2880  QgsSnapper::SnappingType snap_to ) const
2881 {
2882  if ( !geom )
2883  {
2884  return;
2885  }
2886 
2887  int atVertex, beforeVertex, afterVertex;
2888  double sqrDistVertexSnap, sqrDistSegmentSnap;
2889  QgsPoint snappedPoint;
2890  QgsSnappingResult snappingResultVertex;
2891  QgsSnappingResult snappingResultSegment;
2892 
2893  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2894  {
2895  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2896  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2897  {
2898  snappingResultVertex.snappedVertex = snappedPoint;
2899  snappingResultVertex.snappedVertexNr = atVertex;
2900  snappingResultVertex.beforeVertexNr = beforeVertex;
2901  if ( beforeVertex != -1 ) // make sure the vertex is valid
2902  {
2903  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2904  }
2905  snappingResultVertex.afterVertexNr = afterVertex;
2906  if ( afterVertex != -1 ) // make sure the vertex is valid
2907  {
2908  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2909  }
2910  snappingResultVertex.snappedAtGeometry = featureId;
2911  snappingResultVertex.layer = this;
2912  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2913  return;
2914  }
2915  }
2916  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2917  {
2918  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2919  {
2920  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, nullptr, crs().geographicFlag() ? 1e-12 : 1e-8 );
2921 
2922  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2923  {
2924  snappingResultSegment.snappedVertex = snappedPoint;
2925  snappingResultSegment.snappedVertexNr = -1;
2926  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2927  snappingResultSegment.afterVertexNr = afterVertex;
2928  snappingResultSegment.snappedAtGeometry = featureId;
2929  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2930  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2931  snappingResultSegment.layer = this;
2932  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2933  }
2934  }
2935  }
2936 }
2937 
2939 {
2940  QgsVectorLayerEditUtils utils( this );
2941  return utils.insertSegmentVerticesForSnap( snapResults );
2942 }
2943 
2944 
2946 {
2947  QgsDebugMsg( "----- Computing Coordinate System" );
2948 
2949  //
2950  // Get the layers project info and set up the QgsCoordinateTransform
2951  // for this layer
2952  //
2953 
2954  if ( hasGeometryType() )
2955  {
2956  // get CRS directly from provider
2957  setCrs( mDataProvider->crs() );
2958  }
2959  else
2960  {
2962  }
2963 }
2964 
2965 
2967 {
2968  return mDisplayField;
2969 }
2970 
2972 {
2973  mDisplayExpression = displayExpression;
2974 }
2975 
2977 {
2978  return mDisplayExpression;
2979 }
2980 
2982 {
2983  return ( mEditBuffer && mDataProvider );
2984 }
2985 
2987 {
2988  return geometryType() != QGis::NoGeometry;
2989 }
2990 
2992 {
2993  return mReadOnly;
2994 }
2995 
2996 bool QgsVectorLayer::setReadOnly( bool readonly )
2997 {
2998  // exit if the layer is in editing mode
2999  if ( readonly && mEditBuffer )
3000  return false;
3001 
3002  mReadOnly = readonly;
3003  return true;
3004 }
3005 
3007 {
3008  emit beforeModifiedCheck();
3009  return mEditBuffer && mEditBuffer->isModified();
3010 }
3011 
3013 {
3014  if ( idx < 0 || idx >= mUpdatedFields.count() )
3015  return Hidden;
3016 
3018  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
3020 }
3021 
3023 {
3024  if ( idx < 0 || idx >= mUpdatedFields.count() )
3025  return;
3026 
3028 
3030  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
3031 
3032  setEditorWidgetV2( idx, widgetType );
3033  setEditorWidgetV2Config( idx, cfg );
3035 }
3036 
3038 {
3039  mAnnotationForm = ui;
3040 }
3041 
3043 {
3045  return editorWidgetV2Config( idx );
3047 }
3048 
3050 {
3052  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
3053  return RangeData(
3054  cfg.value( "Min" ),
3055  cfg.value( "Max" ),
3056  cfg.value( "Step" )
3057  );
3059 }
3060 
3062 {
3064  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
3066 }
3067 
3069 {
3071  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
3072  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
3074 }
3075 
3077 {
3078  if ( !hasGeometryType() )
3079  return;
3080 
3081  if ( r != mRendererV2 )
3082  {
3083  delete mRendererV2;
3084  mRendererV2 = r;
3085  mSymbolFeatureCounted = false;
3086  mSymbolFeatureCountMap.clear();
3087 
3088  emit rendererChanged();
3089  emit styleChanged();
3090  }
3091 }
3092 
3094 {
3095  if ( !mDataProvider )
3096  {
3097  return;
3098  }
3099  if ( !mDataProvider->transaction() )
3100  {
3101  undoStack()->beginMacro( text );
3102  mEditCommandActive = true;
3103  emit editCommandStarted( text );
3104  }
3105 }
3106 
3108 {
3109  if ( !mDataProvider )
3110  {
3111  return;
3112  }
3113  if ( !mDataProvider->transaction() )
3114  {
3115  undoStack()->endMacro();
3116  mEditCommandActive = false;
3117  if ( !mDeletedFids.isEmpty() )
3118  {
3119  emit featuresDeleted( mDeletedFids );
3120  mDeletedFids.clear();
3121  }
3122  emit editCommandEnded();
3123  }
3124 }
3125 
3127 {
3128  if ( !mDataProvider )
3129  {
3130  return;
3131  }
3132  if ( !mDataProvider->transaction() )
3133  {
3134  undoStack()->endMacro();
3135  undoStack()->undo();
3136  mEditCommandActive = false;
3137  mDeletedFids.clear();
3138  emit editCommandDestroyed();
3139  }
3140 }
3141 
3142 
3143 void QgsVectorLayer::setCheckedState( int idx, const QString& checked, const QString& unchecked )
3144 {
3147  cfg["CheckedState"] = checked;
3148  cfg["UncheckedState"] = unchecked;
3149  setEditorWidgetV2Config( idx, cfg );
3151 }
3152 
3153 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
3154 {
3155  return fields().fieldNameIndex( fieldName );
3156 }
3157 
3159 {
3160  return mJoinBuffer && mJoinBuffer->addJoin( joinInfo );
3161 }
3162 
3164 {
3165  removeJoin( theLayerId );
3166 }
3167 
3168 bool QgsVectorLayer::removeJoin( const QString& joinLayerId )
3169 {
3170  bool res = false;
3171  if ( mJoinBuffer )
3172  {
3173  res = mJoinBuffer->removeJoin( joinLayerId );
3174  }
3175  return res;
3176 }
3177 
3179 {
3180  if ( mJoinBuffer )
3181  return mJoinBuffer->vectorJoins();
3182  else
3183  return QList< QgsVectorJoinInfo >();
3184 }
3185 
3187 {
3188  emit beforeAddingExpressionField( fld.name() );
3189  mExpressionFieldBuffer->addExpression( exp, fld );
3190  updateFields();
3191  int idx = mUpdatedFields.indexFromName( fld.name() );
3192  emit attributeAdded( idx );
3193  return idx;
3194 }
3195 
3197 {
3198  emit beforeRemovingExpressionField( index );
3199  int oi = mUpdatedFields.fieldOriginIndex( index );
3200  mExpressionFieldBuffer->removeExpression( oi );
3201  updateFields();
3202  emit attributeDeleted( index );
3203 }
3204 
3206 {
3207  int oi = mUpdatedFields.fieldOriginIndex( index );
3208  return mExpressionFieldBuffer->expressions().value( oi ).expression;
3209 }
3210 
3212 {
3213  int oi = mUpdatedFields.fieldOriginIndex( index );
3214  mExpressionFieldBuffer->updateExpression( oi, exp );
3215 }
3216 
3218 {
3219  if ( !mDataProvider )
3220  return;
3221 
3222  QgsFields oldFields = mUpdatedFields;
3223 
3224  mUpdatedFields = mDataProvider->fields();
3225 
3226  // added / removed fields
3227  if ( mEditBuffer )
3228  mEditBuffer->updateFields( mUpdatedFields );
3229 
3230  // joined fields
3231  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
3232  mJoinBuffer->updateFields( mUpdatedFields );
3233 
3234  if ( mExpressionFieldBuffer )
3235  mExpressionFieldBuffer->updateFields( mUpdatedFields );
3236 
3237  // set aliases and default values
3238  QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
3239  for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
3240  {
3241  int index = mUpdatedFields.fieldNameIndex( aliasIt.key() );
3242  if ( index < 0 )
3243  continue;
3244 
3245  mUpdatedFields[ index ].setAlias( aliasIt.value() );
3246  }
3247  QMap< QString, QString >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
3248  for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
3249  {
3250  int index = mUpdatedFields.fieldNameIndex( defaultIt.key() );
3251  if ( index < 0 )
3252  continue;
3253 
3254  mUpdatedFields[ index ].setDefaultValueExpression( defaultIt.value() );
3255  }
3256  if ( oldFields != mUpdatedFields )
3257  {
3258  emit updatedFields();
3259  mEditFormConfig->setFields( mUpdatedFields );
3260  }
3261 }
3262 
3263 
3265 {
3266  if ( mJoinBuffer->containsJoins() )
3267  {
3268  mJoinBuffer->createJoinCaches();
3269  }
3270 }
3271 
3273 {
3274  if ( index < 0 || index >= mUpdatedFields.count() )
3275  return QVariant();
3276 
3277  QString expression = mUpdatedFields.at( index ).defaultValueExpression();
3278  if ( expression.isEmpty() )
3279  return mDataProvider->defaultValue( index );
3280 
3281  QgsExpressionContext* evalContext = context;
3283  if ( !evalContext )
3284  {
3285  // no context passed, so we create a default one
3286  tempContext.reset( new QgsExpressionContext() );
3287  tempContext->appendScope( QgsExpressionContextUtils::globalScope() );
3288  tempContext->appendScope( QgsExpressionContextUtils::projectScope() );
3289  tempContext->appendScope( QgsExpressionContextUtils::layerScope( this ) );
3290  evalContext = tempContext.data();
3291  }
3292 
3293  if ( feature.isValid() )
3294  {
3296  featScope->setFeature( feature );
3297  featScope->setFields( *feature.fields() );
3298  evalContext->appendScope( featScope );
3299  }
3300 
3301  QVariant val;
3302  QgsExpression exp( expression );
3303  exp.prepare( evalContext );
3304  if ( exp.hasEvalError() )
3305  {
3306  QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
3307  }
3308  else
3309  {
3310  val = exp.evaluate( evalContext );
3311  }
3312 
3313  if ( feature.isValid() )
3314  {
3315  delete evalContext->popScope();
3316  }
3317 
3318  return val;
3319 }
3320 
3322 {
3323  if ( index < 0 || index >= mUpdatedFields.count() )
3324  return;
3325 
3326  if ( expression.isEmpty() )
3327  {
3328  mDefaultExpressionMap.remove( mUpdatedFields.at( index ).name() );
3329  }
3330  else
3331  {
3332  mDefaultExpressionMap.insert( mUpdatedFields.at( index ).name(), expression );
3333  }
3334  updateFields();
3335 }
3336 
3338 {
3339  if ( index < 0 || index >= mUpdatedFields.count() )
3340  return QString();
3341  else
3342  return mUpdatedFields.at( index ).defaultValueExpression();
3343 }
3344 
3346 {
3347  uniqueValues.clear();
3348  if ( !mDataProvider )
3349  {
3350  return;
3351  }
3352 
3353  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3354  switch ( origin )
3355  {
3357  return;
3358 
3359  case QgsFields::OriginProvider: //a provider field
3360  {
3361  mDataProvider->uniqueValues( index, uniqueValues, limit );
3362 
3363  if ( mEditBuffer )
3364  {
3365  QSet<QString> vals;
3366  Q_FOREACH ( const QVariant& v, uniqueValues )
3367  {
3368  vals << v.toString();
3369  }
3370 
3371  QgsFeatureMap added = mEditBuffer->addedFeatures();
3373  while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3374  {
3375  addedIt.next();
3376  QVariant v = addedIt.value().attribute( index );
3377  if ( v.isValid() )
3378  {
3379  QString vs = v.toString();
3380  if ( !vals.contains( vs ) )
3381  {
3382  vals << vs;
3383  uniqueValues << v;
3384  }
3385  }
3386  }
3387 
3388  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3389  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3390  {
3391  it.next();
3392  QVariant v = it.value().value( index );
3393  if ( v.isValid() )
3394  {
3395  QString vs = v.toString();
3396  if ( !vals.contains( vs ) )
3397  {
3398  vals << vs;
3399  uniqueValues << v;
3400  }
3401  }
3402  }
3403  }
3404 
3405  return;
3406  }
3407 
3408  case QgsFields::OriginEdit:
3409  // the layer is editable, but in certain cases it can still be avoided going through all features
3410  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3411  mEditBuffer->mAddedFeatures.isEmpty() &&
3412  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3413  mEditBuffer->mChangedAttributeValues.isEmpty() )
3414  {
3415  mDataProvider->uniqueValues( index, uniqueValues, limit );
3416  return;
3417  }
3418  FALLTHROUGH;
3419  //we need to go through each feature
3420  case QgsFields::OriginJoin:
3422  {
3423  QgsAttributeList attList;
3424  attList << index;
3425 
3427  .setFlags( QgsFeatureRequest::NoGeometry )
3428  .setSubsetOfAttributes( attList ) );
3429 
3430  QgsFeature f;
3431  QVariant currentValue;
3433  while ( fit.nextFeature( f ) )
3434  {
3435  currentValue = f.attribute( index );
3436  val.insert( currentValue.toString(), currentValue );
3437  if ( limit >= 0 && val.size() >= limit )
3438  {
3439  break;
3440  }
3441  }
3442 
3443  uniqueValues = val.values();
3444  return;
3445  }
3446  }
3447 
3448  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3449 }
3450 
3452 {
3453  if ( !mDataProvider )
3454  {
3455  return QVariant();
3456  }
3457 
3458  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3459 
3460  switch ( origin )
3461  {
3463  return QVariant();
3464 
3465  case QgsFields::OriginProvider: //a provider field
3466  {
3467  QVariant min = mDataProvider->minimumValue( index );
3468  if ( mEditBuffer )
3469  {
3470  QgsFeatureMap added = mEditBuffer->addedFeatures();
3472  while ( addedIt.hasNext() )
3473  {
3474  addedIt.next();
3475  QVariant v = addedIt.value().attribute( index );
3476  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3477  {
3478  min = v;
3479  }
3480  }
3481 
3482  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3483  while ( it.hasNext() )
3484  {
3485  it.next();
3486  QVariant v = it.value().value( index );
3487  if ( v.isValid() && qgsVariantLessThan( v, min ) )
3488  {
3489  min = v;
3490  }
3491  }
3492  }
3493  return min;
3494  }
3495 
3496  case QgsFields::OriginEdit:
3497  {
3498  // the layer is editable, but in certain cases it can still be avoided going through all features
3499  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3500  mEditBuffer->mAddedFeatures.isEmpty() && !
3501  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3502  mEditBuffer->mChangedAttributeValues.isEmpty() )
3503  {
3504  return mDataProvider->minimumValue( index );
3505  }
3506  }
3507  FALLTHROUGH;
3508  // no choice but to go through all features
3510  case QgsFields::OriginJoin:
3511  {
3512  // we need to go through each feature
3513  QgsAttributeList attList;
3514  attList << index;
3515 
3517  .setFlags( QgsFeatureRequest::NoGeometry )
3518  .setSubsetOfAttributes( attList ) );
3519 
3520  QgsFeature f;
3522  double currentValue = 0;
3523  while ( fit.nextFeature( f ) )
3524  {
3525  currentValue = f.attribute( index ).toDouble();
3526  if ( currentValue < minimumValue )
3527  {
3528  minimumValue = currentValue;
3529  }
3530  }
3531  return QVariant( minimumValue );
3532  }
3533  }
3534 
3535  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3536  return QVariant();
3537 }
3538 
3540 {
3541  if ( !mDataProvider )
3542  {
3543  return QVariant();
3544  }
3545 
3546  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3547  switch ( origin )
3548  {
3550  return QVariant();
3551 
3552  case QgsFields::OriginProvider: //a provider field
3553  {
3554  QVariant min = mDataProvider->maximumValue( index );
3555  if ( mEditBuffer )
3556  {
3557  QgsFeatureMap added = mEditBuffer->addedFeatures();
3559  while ( addedIt.hasNext() )
3560  {
3561  addedIt.next();
3562  QVariant v = addedIt.value().attribute( index );
3563  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3564  {
3565  min = v;
3566  }
3567  }
3568 
3569  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3570  while ( it.hasNext() )
3571  {
3572  it.next();
3573  QVariant v = it.value().value( index );
3574  if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
3575  {
3576  min = v;
3577  }
3578  }
3579  }
3580  return min;
3581  }
3582 
3583  case QgsFields::OriginEdit:
3584  // the layer is editable, but in certain cases it can still be avoided going through all features
3585  if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3586  mEditBuffer->mAddedFeatures.isEmpty() &&
3587  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3588  mEditBuffer->mChangedAttributeValues.isEmpty() )
3589  {
3590  return mDataProvider->maximumValue( index );
3591  }
3592 
3593  FALLTHROUGH;
3594  //no choice but to go through each feature
3595  case QgsFields::OriginJoin:
3597  {
3598  QgsAttributeList attList;
3599  attList << index;
3600 
3602  .setFlags( QgsFeatureRequest::NoGeometry )
3603  .setSubsetOfAttributes( attList ) );
3604 
3605  QgsFeature f;
3607  double currentValue = 0;
3608  while ( fit.nextFeature( f ) )
3609  {
3610  currentValue = f.attribute( index ).toDouble();
3611  if ( currentValue > maximumValue )
3612  {
3613  maximumValue = currentValue;
3614  }
3615  }
3616  return QVariant( maximumValue );
3617  }
3618  }
3619 
3620  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3621  return QVariant();
3622 }
3623 
3625  const QgsAggregateCalculator::AggregateParameters& parameters, QgsExpressionContext* context, bool* ok )
3626 {
3627  if ( ok )
3628  *ok = false;
3629 
3630  if ( !mDataProvider )
3631  {
3632  return QVariant();
3633  }
3634 
3635  // test if we are calculating based on a field
3636  int attrIndex = mUpdatedFields.fieldNameIndex( fieldOrExpression );
3637  if ( attrIndex >= 0 )
3638  {
3639  // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
3640  // to the provider itself
3641  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( attrIndex );
3642  if ( origin == QgsFields::OriginProvider )
3643  {
3644  bool providerOk = false;
3645  QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk );
3646  if ( providerOk )
3647  {
3648  // provider handled calculation
3649  if ( ok )
3650  *ok = true;
3651  return val;
3652  }
3653  }
3654  }
3655 
3656  // fallback to using aggregate calculator to determine aggregate
3657  QgsAggregateCalculator c( this );
3658  c.setParameters( parameters );
3659  return c.calculate( aggregate, fieldOrExpression, context, ok );
3660 }
3661 
3662 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly )
3663 {
3664  QList<QVariant> values;
3665 
3666  QScopedPointer<QgsExpression> expression;
3667  QgsExpressionContext context;
3668 
3669  int attrNum = fieldNameIndex( fieldOrExpression );
3670 
3671  if ( attrNum == -1 )
3672  {
3673  // try to use expression
3674  expression.reset( new QgsExpression( fieldOrExpression ) );
3678 
3679  if ( expression->hasParserError() || !expression->prepare( &context ) )
3680  {
3681  ok = false;
3682  return values;
3683  }
3684  }
3685 
3686  QgsFeature f;
3687  QStringList lst;
3688  if ( expression.isNull() )
3689  lst.append( fieldOrExpression );
3690  else
3691  lst = expression->referencedColumns();
3692 
3694  .setFlags(( expression && expression->needsGeometry() ) ?
3697  .setSubsetOfAttributes( lst, fields() );
3698 
3699  QgsFeatureIterator fit;
3700  if ( !selectedOnly )
3701  {
3702  fit = getFeatures( request );
3703  }
3704  else
3705  {
3706  fit = selectedFeaturesIterator( request );
3707  }
3708 
3709  // create list of non-null attribute values
3710  while ( fit.nextFeature( f ) )
3711  {
3712  if ( expression )
3713  {
3714  context.setFeature( f );
3715  QVariant v = expression->evaluate( &context );
3716  values << v;
3717  }
3718  else
3719  {
3720  values << f.attribute( attrNum );
3721  }
3722  }
3723  ok = true;
3724  return values;
3725 }
3726 
3727 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly, int* nullCount )
3728 {
3729  QList<double> values;
3730 
3731  if ( nullCount )
3732  *nullCount = 0;
3733 
3734  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3735  if ( !ok )
3736  return values;
3737 
3738  bool convertOk;
3739  Q_FOREACH ( const QVariant& value, variantValues )
3740  {
3741  double val = value.toDouble( &convertOk );
3742  if ( convertOk )
3743  values << val;
3744  else if ( value.isNull() )
3745  {
3746  if ( nullCount )
3747  *nullCount += 1;
3748  }
3749  }
3750  ok = true;
3751  return values;
3752 }
3753 
3754 
3757 {
3758  mFeatureBlendMode = featureBlendMode;
3759  emit featureBlendModeChanged( featureBlendMode );
3760  emit styleChanged();
3761 }
3762 
3764 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3765 {
3766  return mFeatureBlendMode;
3767 }
3768 
3771 {
3772  mLayerTransparency = layerTransparency;
3773  emit layerTransparencyChanged( layerTransparency );
3774  emit styleChanged();
3775 }
3776 
3779 {
3780  return mLayerTransparency;
3781 }
3782 
3783 
3784 
3785 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3786 {
3787  QDomElement element = node.toElement();
3788  if ( element.isNull() )
3789  return;
3790 
3791  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3792  if ( userStyleElem.isNull() )
3793  {
3794  QgsDebugMsg( "Info: UserStyle element not found." );
3795  return;
3796  }
3797 
3798  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3799  if ( featureTypeStyleElem.isNull() )
3800  {
3801  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3802  return;
3803  }
3804 
3805  // use last rule
3806  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3807  if ( ruleElem.isNull() )
3808  {
3809  QgsDebugMsg( "Info: Rule element not found." );
3810  return;
3811  }
3812 
3813  // use last text symbolizer
3814  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3815  if ( textSymbolizerElem.isNull() )
3816  {
3817  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3818  return;
3819  }
3820 
3821  // Label
3822  setCustomProperty( "labeling/enabled", false );
3823  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3824  if ( !labelElem.isNull() )
3825  {
3826  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3827  if ( !propertyNameElem.isNull() )
3828  {
3829  // enable labeling
3830  setCustomProperty( "labeling", "pal" );
3831  setCustomProperty( "labeling/enabled", true );
3832 
3833  // set labeling defaults
3834  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3835  setCustomProperty( "labeling/fontItalic", false );
3836  setCustomProperty( "labeling/fontSize", 10 );
3837  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3838  setCustomProperty( "labeling/fontBold", false );
3839  setCustomProperty( "labeling/fontUnderline", false );
3840  setCustomProperty( "labeling/textColorR", 0 );
3841  setCustomProperty( "labeling/textColorG", 0 );
3842  setCustomProperty( "labeling/textColorB", 0 );
3843  setCustomProperty( "labeling/textTransp", 0 );
3844  setCustomProperty( "labeling/bufferDraw", false );
3845  setCustomProperty( "labeling/bufferSize", 1 );
3846  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3847  setCustomProperty( "labeling/bufferColorR", 255 );
3848  setCustomProperty( "labeling/bufferColorG", 255 );
3849  setCustomProperty( "labeling/bufferColorB", 255 );
3850  setCustomProperty( "labeling/bufferTransp", 0 );
3851  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3852  setCustomProperty( "labeling/xOffset", 0 );
3853  setCustomProperty( "labeling/yOffset", 0 );
3854  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3855  setCustomProperty( "labeling/angleOffset", 0 );
3856 
3857  // label attribute
3858  QString labelAttribute = propertyNameElem.text();
3859  setCustomProperty( "labeling/fieldName", labelAttribute );
3860  setCustomProperty( "labeling/isExpression", false );
3861 
3862  int fieldIndex = fieldNameIndex( labelAttribute );
3863  if ( fieldIndex == -1 )
3864  {
3865  // label attribute is not in columns, check if it is an expression
3866  QgsExpression exp( labelAttribute );
3867  if ( !exp.hasEvalError() )
3868  {
3869  setCustomProperty( "labeling/isExpression", true );
3870  }
3871  else
3872  {
3873  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3874  }
3875  }
3876  }
3877  else
3878  {
3879  QgsDebugMsg( "Info: PropertyName element not found." );
3880  return;
3881  }
3882  }
3883  else
3884  {
3885  QgsDebugMsg( "Info: Label element not found." );
3886  return;
3887  }
3888 
3889  // Font
3890  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3891  if ( !fontElem.isNull() )
3892  {
3893  QString cssName;
3894  QString elemText;
3895  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3896  while ( !cssElem.isNull() )
3897  {
3898  cssName = cssElem.attribute( "name", "not_found" );
3899  if ( cssName != "not_found" )
3900  {
3901  elemText = cssElem.text();
3902  if ( cssName == "font-family" )
3903  {
3904  setCustomProperty( "labeling/fontFamily", elemText );
3905  }
3906  else if ( cssName == "font-style" )
3907  {
3908  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3909  }
3910  else if ( cssName == "font-size" )
3911  {
3912  bool ok;
3913  int fontSize = elemText.toInt( &ok );
3914  if ( ok )
3915  {
3916  setCustomProperty( "labeling/fontSize", fontSize );
3917  }
3918  }
3919  else if ( cssName == "font-weight" )
3920  {
3921  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3922  }
3923  else if ( cssName == "font-underline" )
3924  {
3925  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3926  }
3927  }
3928 
3929  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3930  }
3931  }
3932 
3933  // Fill
3934  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3935  if ( textColor.isValid() )
3936  {
3937  setCustomProperty( "labeling/textColorR", textColor.red() );
3938  setCustomProperty( "labeling/textColorG", textColor.green() );
3939  setCustomProperty( "labeling/textColorB", textColor.blue() );
3940  setCustomProperty( "labeling/textTransp", 100 - static_cast< int >( 100 * textColor.alphaF() ) );
3941  }
3942 
3943  // Halo
3944  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3945  if ( !haloElem.isNull() )
3946  {
3947  setCustomProperty( "labeling/bufferDraw", true );
3948  setCustomProperty( "labeling/bufferSize", 1 );
3949 
3950  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3951  if ( !radiusElem.isNull() )
3952  {
3953  bool ok;
3954  double bufferSize = radiusElem.text().toDouble( &ok );
3955  if ( ok )
3956  {
3957  setCustomProperty( "labeling/bufferSize", bufferSize );
3958  }
3959  }
3960 
3961  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3962  if ( bufferColor.isValid() )
3963  {
3964  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3965  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3966  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3967  setCustomProperty( "labeling/bufferTransp", 100 - static_cast< int >( 100 * bufferColor.alphaF() ) );
3968  }
3969  }
3970 
3971  // LabelPlacement
3972  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3973  if ( !labelPlacementElem.isNull() )
3974  {
3975  // PointPlacement
3976  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3977  if ( !pointPlacementElem.isNull() )
3978  {
3979  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3980 
3981  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3982  if ( !displacementElem.isNull() )
3983  {
3984  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3985  if ( !displacementXElem.isNull() )
3986  {
3987  bool ok;
3988  double xOffset = displacementXElem.text().toDouble( &ok );
3989  if ( ok )
3990  {
3991  setCustomProperty( "labeling/xOffset", xOffset );
3992  }
3993  }
3994  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3995  if ( !displacementYElem.isNull() )
3996  {
3997  bool ok;
3998  double yOffset = displacementYElem.text().toDouble( &ok );
3999  if ( ok )
4000  {
4001  setCustomProperty( "labeling/yOffset", yOffset );
4002  }
4003  }
4004  }
4005 
4006  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
4007  if ( !rotationElem.isNull() )
4008  {
4009  bool ok;
4010  double rotation = rotationElem.text().toDouble( &ok );
4011  if ( ok )
4012  {
4013  setCustomProperty( "labeling/angleOffset", rotation );
4014  }
4015  }
4016  }
4017  }
4018 }
4019 
4021 {
4022  QgsAttributeTableConfig config = mAttributeTableConfig;
4023 
4024  if ( config.isEmpty() )
4025  config.update( fields() );
4026 
4027  return config;
4028 }
4029 
4031 {
4032  if ( mAttributeTableConfig != attributeTableConfig )
4033  {
4034  mAttributeTableConfig = attributeTableConfig;
4035  emit configChanged();
4036  }
4037 }
4038 
4040 {
4041  if ( !mDiagramLayerSettings )
4042  mDiagramLayerSettings = new QgsDiagramLayerSettings();
4043  *mDiagramLayerSettings = s;
4044 }
4045 
4047 {
4048  QString myMetadata = "<html><body>";
4049 
4050  //-------------
4051 
4052  myMetadata += "<p class=\"subheaderglossy\">";
4053  myMetadata += tr( "General" );
4054  myMetadata += "</p>\n";
4055 
4056  // data comment
4057  if ( !( dataComment().isEmpty() ) )
4058  {
4059  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
4060  myMetadata += "<p>";
4061  myMetadata += dataComment();
4062  myMetadata += "</p>\n";
4063  }
4064 
4065  //storage type
4066  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
4067  myMetadata += "<p>";
4068  myMetadata += storageType();
4069  myMetadata += "</p>\n";
4070 
4071  if ( dataProvider() )
4072  {
4073  //provider description
4074  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
4075  myMetadata += "<p>";
4076  myMetadata += dataProvider()->description().replace( '\n', "<br>" );
4077  myMetadata += "</p>\n";
4078  }
4079 
4080  // data source
4081  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
4082  myMetadata += "<p>";
4083  myMetadata += publicSource();
4084  myMetadata += "</p>\n";
4085 
4086  //geom type
4087 
4089 
4090  if ( type < 0 || type > QGis::NoGeometry )
4091  {
4092  QgsDebugMsg( "Invalid vector type" );
4093  }
4094  else
4095  {
4096  QString typeString( QGis::vectorGeometryType( geometryType() ) );
4097  QString wkbTypeString = QgsWKBTypes::displayString( QGis::fromOldWkbType( mWkbType ) );
4098 
4099  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
4100  myMetadata += QString( "<p>%1 (WKB type: \"%2\")</p>\n" ).arg( typeString, wkbTypeString );
4101  }
4102 
4103  QgsAttributeList pkAttrList = pkAttributeList();
4104  if ( !pkAttrList.isEmpty() )
4105  {
4106  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
4107  myMetadata += "<p>";
4108  Q_FOREACH ( int idx, pkAttrList )
4109  {
4110  myMetadata += fields().at( idx ).name() + ' ';
4111  }
4112  myMetadata += "</p>\n";
4113  }
4114 
4115 
4116  //feature count
4117  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
4118  myMetadata += "<p>";
4119  myMetadata += QString::number( featureCount() );
4120  myMetadata += "</p>\n";
4121  //capabilities
4122  myMetadata += "<p class=\"glossy\">" + tr( "Capabilities of this layer" ) + "</p>\n";
4123  myMetadata += "<p>";
4124  myMetadata += capabilitiesString();
4125  myMetadata += "</p>\n";
4126 
4127  //-------------
4128 
4129  QgsRectangle myExtent = extent();
4130  myMetadata += "<p class=\"subheaderglossy\">";
4131  myMetadata += tr( "Extents" );
4132  myMetadata += "</p>\n";
4133 
4134  //extents in layer cs TODO...maybe make a little nested table to improve layout...
4135  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
4136  myMetadata += "<p>";
4137  // Try to be a bit clever over what number format we use for the
4138  // extents. Some people don't like it using scientific notation when the
4139  // numbers get large, but for small numbers this is the more practical
4140  // option (so we can't force the format to 'f' for all values).
4141  // The scheme:
4142  // - for all numbers with more than 5 digits, force non-scientific notation
4143  // and 2 digits after the decimal point.
4144  // - for all smaller numbers let the OS decide which format to use (it will
4145  // generally use non-scientific unless the number gets much less than 1).
4146 
4147  if ( !myExtent.isEmpty() )
4148  {
4149  QString xMin, yMin, xMax, yMax;
4150  double changeoverValue = 99999; // The 'largest' 5 digit number
4151  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
4152  {
4153  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
4154  }
4155  else
4156  {
4157  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
4158  }
4159  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
4160  {
4161  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
4162  }
4163  else
4164  {
4165  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
4166  }
4167  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
4168  {
4169  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
4170  }
4171  else
4172  {
4173  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
4174  }
4175  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
4176  {
4177  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
4178  }
4179  else
4180  {
4181  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
4182  }
4183 
4184  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
4185  .arg( xMin, yMin, xMax, yMax );
4186  }
4187  else
4188  {
4189  myMetadata += tr( "unknown extent" );
4190  }
4191 
4192  myMetadata += "</p>\n";
4193 
4194  //extents in project cs
4195 
4196  try
4197  {
4198 #if 0
4199  // TODO: currently disabled, will revisit later [MD]
4200  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
4201  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
4202  myMetadata += "<p>";
4203  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
4204  .arg( myProjectedExtent.xMinimum() )
4205  .arg( myProjectedExtent.yMinimum() )
4206  .arg( myProjectedExtent.xMaximum() )
4207  .arg( myProjectedExtent.yMaximum() );
4208  myMetadata += "</p>\n";
4209 #endif
4210 
4211  //
4212  // Display layer spatial ref system
4213  //
4214  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
4215  myMetadata += "<p>";
4216  myMetadata += crs().toProj4().replace( '"', " \"" );
4217  myMetadata += "</p>\n";
4218 
4219  //
4220  // Display project (output) spatial ref system
4221  //
4222 #if 0
4223  // TODO: disabled for now, will revisit later [MD]
4224  //myMetadata += "<tr><td bgcolor=\"gray\">";
4225  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
4226  myMetadata += "<p>";
4227  myMetadata += coordinateTransform->destCRS().toProj4().replace( '"', " \"" );
4228  myMetadata += "</p>\n";
4229 #endif
4230  }
4231  catch ( QgsCsException &cse )
4232  {
4233  Q_UNUSED( cse );
4234  QgsDebugMsg( cse.what() );
4235 
4236  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
4237  myMetadata += "<p>";
4238  myMetadata += tr( "(Invalid transformation of layer extents)" );
4239  myMetadata += "</p>\n";
4240 
4241  }
4242 
4243 #if 0
4244  //
4245  // Add the info about each field in the attribute table
4246  //
4247  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
4248  myMetadata += "<p>";
4249 
4250  // Start a nested table in this trow
4251  myMetadata += "<table width=\"100%\">";
4252  myMetadata += "<tr><th>";
4253  myMetadata += tr( "Field" );
4254  myMetadata += "</th>";
4255  myMetadata += "<th>";
4256  myMetadata += tr( "Type" );
4257  myMetadata += "</th>";
4258  myMetadata += "<th>";
4259  myMetadata += tr( "Length" );
4260  myMetadata += "</th>";
4261  myMetadata += "<th>";
4262  myMetadata += tr( "Precision" );
4263  myMetadata += "</th>";
4264  myMetadata += "<th>";
4265  myMetadata += tr( "Comment" );
4266  myMetadata += "</th>";
4267 
4268  //get info for each field by looping through them
4269  const QgsFields& myFields = pendingFields();
4270  for ( int i = 0, n = myFields.size(); i < n; ++i )
4271  {
4272  const QgsField& myField = fields[i];
4273 
4274  myMetadata += "<tr><td>";
4275  myMetadata += myField.name();
4276  myMetadata += "</td>";
4277  myMetadata += "<td>";
4278  myMetadata += myField.typeName();
4279  myMetadata += "</td>";
4280  myMetadata += "<td>";
4281  myMetadata += QString( "%1" ).arg( myField.length() );
4282  myMetadata += "</td>";
4283  myMetadata += "<td>";
4284  myMetadata += QString( "%1" ).arg( myField.precision() );
4285  myMetadata += "</td>";
4286  myMetadata += "<td>";
4287  myMetadata += QString( "%1" ).arg( myField.comment() );
4288  myMetadata += "</td></tr>";
4289  }
4290 
4291  //close field list
4292  myMetadata += "</table>"; //end of nested table
4293 #endif
4294 
4295  myMetadata += "</body></html>";
4296  return myMetadata;
4297 }
4298 
4300 {
4301  mSymbolFeatureCounted = false;
4302 }
4303 
4304 void QgsVectorLayer::onJoinedFieldsChanged()
4305 {
4306  // some of the fields of joined layers have changed -> we need to update this layer's fields too
4307  updateFields();
4308 }
4309 
4310 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
4311 {
4312  if ( mEditCommandActive )
4313  mDeletedFids << fid;
4314  else
4315  emit featuresDeleted( QgsFeatureIds() << fid );
4316 
4317  emit featureDeleted( fid );
4318 }
4319 
4321 {
4322  if ( mEditFormConfig->widgetType( idx ) == "ValueRelation" )
4323  {
4324  QgsEditorWidgetConfig cfg = mEditFormConfig->widgetConfig( idx );
4325 
4326  return ValueRelationData( cfg.value( "Layer" ).toString(),
4327  cfg.value( "Key" ).toString(),
4328  cfg.value( "Value" ).toString(),
4329  cfg.value( "AllowNull" ).toBool(),
4330  cfg.value( "OrderByValue" ).toBool(),
4331  cfg.value( "AllowMulti" ).toBool(),
4332  cfg.value( "FilterExpression" ).toString()
4333  );
4334  }
4335  else
4336  {
4337  return ValueRelationData();
4338  }
4339 }
4340 
4342 {
4343  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
4344 }
4345 
4347 {
4349  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4350  if ( !myLib )
4351  {
4352  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4353  return -1;
4354  }
4355  listStyles_t* listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
4356 
4357  if ( !listStylesExternalMethod )
4358  {
4359  delete myLib;
4360  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "listStyles" );
4361  return -1;
4362  }
4363 
4364  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
4365 }
4366 
4368 {
4370  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4371  if ( !myLib )
4372  {
4373  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4374  return QObject::tr( "" );
4375  }
4376  getStyleById_t* getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
4377 
4378  if ( !getStyleByIdMethod )
4379  {
4380  delete myLib;
4381  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "getStyleById" );
4382  return QObject::tr( "" );
4383  }
4384 
4385  return getStyleByIdMethod( mDataSource, styleId, msgError );
4386 }
4387 
4388 
4389 void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& description,
4390  bool useAsDefault, const QString& uiFileContent, QString &msgError )
4391 {
4392 
4393  QString sldStyle, qmlStyle;
4395  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4396  if ( !myLib )
4397  {
4398  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4399  return;
4400  }
4401  saveStyle_t* saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4402 
4403  if ( !saveStyleExternalMethod )
4404  {
4405  delete myLib;
4406  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "saveStyle" );
4407  return;
4408  }
4409 
4410  QDomDocument qmlDocument, sldDocument;
4411  this->exportNamedStyle( qmlDocument, msgError );
4412  if ( !msgError.isEmpty() )
4413  {
4414  return;
4415  }
4416  qmlStyle = qmlDocument.toString();
4417 
4418  this->exportSldStyle( sldDocument, msgError );
4419  if ( !msgError.isEmpty() )
4420  {
4421  return;
4422  }
4423  sldStyle = sldDocument.toString();
4424 
4425  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4426  description, uiFileContent, useAsDefault, msgError );
4427 }
4428 
4429 
4430 
4431 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
4432 {
4433  return loadNamedStyle( theURI, theResultFlag, false );
4434 }
4435 
4436 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
4437 {
4438  QgsDataSourceURI dsUri( theURI );
4439  if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDBSupported() )
4440  {
4442  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4443  if ( myLib )
4444  {
4445  loadStyle_t* loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4446  if ( loadStyleExternalMethod )
4447  {
4448  QString qml, errorMsg;
4449  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4450  if ( !qml.isEmpty() )
4451  {
4453  theResultFlag = applyNamedStyle( qml, errorMsg );
4455  return QObject::tr( "Loaded from Provider" );
4456  }
4457  }
4458  }
4459  }
4460 
4461  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
4462 }
4463 
4464 bool QgsVectorLayer::applyNamedStyle( const QString& namedStyle, QString& errorMsg )
4465 {
4466  QDomDocument myDocument( "qgis" );
4467  myDocument.setContent( namedStyle );
4468 
4469  return importNamedStyle( myDocument, errorMsg );
4470 }
4471 
4473 {
4474  if ( mDataProvider )
4475  {
4476  return mDataProvider->layerDependencies();
4477  }
4478  return QSet<QString>();
4479 }
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 labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
bool draw(QgsRenderContext &rendererContext) override
Draws the layer.
virtual QString subsetString()
Get the string (typically sql) used to define a subset of the layer.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:199
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)...
void clear()
QString encoding() const
Get encoding which is used for accessing data.
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
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
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
double rendererScale() const
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
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:260
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
QgsFeatureList selectedFeatures()
Get a copy of the user-selected features.
virtual bool writeXml(QDomNode &layer_node, QDomDocument &doc) override
Write vector layer specific state to project file Dom node.
int size() const
Return number of items.
Definition: qgsfield.cpp:407
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:448
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
bool contains(const Key &key) const
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
void selectByRect(QgsRectangle &rect, SelectBehaviour behaviour=SetSelection)
Select features found within the search rectangle (in layer&#39;s coordinates)
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...
QString alias
Definition: qgsfield.h:53
QgsMapLayerLegend * legend() const
Can be null.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
Modify current selection to include only select features which match.
Renders the diagrams for all features with the same settings.
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:261
int addTopologicalPoints(const QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
void beginMacro(const QString &text)
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
void layerTransparencyChanged(int layerTransparency)
Signal emitted when setLayerTransparency() is called.
QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures(QProgressDialog *dialog)
Constructor.
bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
void 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
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
QStringList referencedColumns() const
Get list of columns referenced by the expression.
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:124
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...
void invertSelectionInRectangle(QgsRectangle &rect)
Invert selection of features found within the search rectangle (in layer&#39;s coordinates) ...
QLibrary * providerLibrary(const QString &providerKey) const
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.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
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
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues)
Changes attributes&#39; values for a feature (but does not immediately commit the changes).
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:515
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.
QString toProj4() const
Returns a Proj4 string representation of this CRS.
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.
QString evalErrorString() const
Returns evaluation error.
QDomElement nextSiblingElement(const QString &tagName) const
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it)
int insertSegmentVerticesForSnap(const QList< QgsSnappingResult > &snapResults)
Inserts vertices to the snapped segments.
void setDefaultValueExpression(int index, const QString &expression)
Sets an expression to use when calculating the default value for a field.
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:252
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all registered layers by layer ID.
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...
static const char * vectorGeometryType(GeometryType type)
description strings for geometry types
Definition: qgis.cpp:441
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
WkbType
Used for symbology operations.
Definition: qgis.h:61
static void mergeScaleDependencies(int mScaleMinDenom, int mScaleMaxDenom, QgsStringMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
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:259
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.
QgsRelationManager * relationManager() const
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.
const QList< QgsVectorJoinInfo > vectorJoins() const
Q_DECL_DEPRECATED void setCheckedState(int idx, const QString &checked, const QString &notChecked)
Set string representing &#39;true&#39; for a checkbox.
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.
virtual QSet< QString > layerDependencies() const
Get the list of layer ids on which this layer depends.
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.
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:99
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.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:492
long featureCount() const
Returns feature count including changes which have not yet been committed If you need only the count ...
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:774
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
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...
void invertSelection()
Select not selected features and deselect selected ones.
void setParameters(const AggregateParameters &parameters)
Sets all aggregate parameters from a parameter bundle.
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:269
it has not been specified where the field comes from
Definition: qgsfield.h:258
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.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:422
int size() const
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
Needs to be called when a new render cycle is started.
virtual void updateExtents()
Update the extents for the layer.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
QString what() const
Definition: qgsexception.h:36
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
void removeSelection()
Clear selection.
Manages joined fields for a vector layer.
void reset(T *other)
QgsFields fields() const
Returns the list of fields of this layer.
QgsConditionalLayerStyles * conditionalStyles() const
Return the conditional styles that are set for this layer.
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
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Q_DECL_DEPRECATED void setEditorWidgetV2(int attrIdx, const QString &widgetType)
Set the editor widget type for a field.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
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.
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)
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)
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
int count(const T &value) const
QVariantMap QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
void append(const T &value)
QList< QgsRelation > referencingRelations(QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Get all relations where the specified layer (and field) is the referencing part (i.e.
void setIndex(int idx)
const QgsFields * fields() const
Returns the field map associated with the feature.
Definition: qgsfeature.cpp:188
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void deselect(const QgsFeatureId featureId)
Deselect feature by its ID.
void layerDeleted()
TODO QGIS3: remove in favor of QObject::destroyed.
QString & insert(int position, QChar ch)
#define FALLTHROUGH
Definition: qgis.h:539
QgsRectangle extent() override
Return the extent of the layer.
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any).
QDomDocument ownerDocument() const
bool rollBack(bool deleteBuffer=true)
Stop editing and discard the edits.
QString text() const
bool isInScaleRange(double scale) const
Return true if the label is visible at the given scale.
Definition: qgslabel.cpp:1418
int toInt(bool *ok) const
bool isNull() const
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurvev2.cpp:29
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
QgsDataProvider * provider(const QString &providerKey, const QString &dataSource)
Create an instance of the provider.
bool hasAttribute(const QString &name) const
bool isEmpty() const
test if rectangle is empty.
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:102
const QgsRectangle & extent() const
The attribute value should not be shown in the attribute form.
void featureBlendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when setFeatureBlendMode() is called.
QString defaultValueExpression
Definition: qgsfield.h:54
Represents the result of a snapping operation.
Definition: qgssnapper.h:36
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
int red() const
void setPen(const QColor &color)
void beforeModifiedCheck() const
Is emitted, when layer is checked for modifications.
QStringList capturedTexts() const
void drawEllipse(const QRectF &rectangle)
QString dataComment() const
Returns a comment for the data in the layer.
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.
int snapWithContext(const QgsPoint &startPoint, double snappingTolerance, QMultiMap< double, QgsSnappingResult > &snappingResults, QgsSnapper::SnappingType snap_to)
Snaps to segment or vertex within given tolerance.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
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.
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)...
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
float threshold() const
Gets the simplification threshold of the vector layer managed.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
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()
Storage and management of actions associated with a layer.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
const 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_iterator constEnd() const
int layerTransparency() const
Returns the current transparency for the vector layer.
bool setReadOnly(bool readonly=true)
Make layer read-only (editing disabled) or not.
bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
Change feature&#39;s geometry.
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
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
const QgsAbstractVectorLayerLabeling * labeling() const
Access to labeling configuration.
void rendererChanged()
Signal emitted when renderer is changed.
virtual QGis::WkbType geometryType() const =0
Get feature type.
Single scope for storing variables and functions for use within a QgsExpressionContext.
double minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
Fast access to features using their ID.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
QgsFeatureId snappedAtGeometry
Index of the snapped geometry.
Definition: qgssnapper.h:54
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
double maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:768
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.
void raiseError(const QString &msg)
Signals an error related to this vector layer.
void editingStarted()
Is emitted, when editing on this layer has started.
void setName(const QString &name)
Set the display name of the layer.
QgsAttributeList pkAttributeList() const
Returns list of attributes making up the primary key.
QString capabilitiesString() const
Capabilities for this layer in a friendly format.
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
bool addFeatures(QgsFeatureList features, bool makeSelected=true)
Insert a copy of the given features into the layer (but does not commit it)
QVariant calculate(Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr) const
Calculates the value of an aggregate.
A class to represent a point.
Definition: qgspoint.h: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.
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
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
QString displayField() const
Returns the primary display field name used in the identify results dialog.
const QStringList & commitErrors()
QDomText createTextNode(const QString &value)
T * data() const
int green() const
void invalidateSymbolCountedFlag()
iterator end()
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
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
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
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:571
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
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
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
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists).
Stores the settings for rendering of all diagrams for a layer.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
bool renameAttribute(int attIndex, const QString &newName)
Renames an attribute field (but does not commit it).
bool contains(const T &value) const
bool isNull() const
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QString defaultValueExpression(int index) const
Returns the expression used when calculating the default value for a field.
QgsFeatureIterator selectedFeaturesIterator(QgsFeatureRequest request=QgsFeatureRequest())
Get an iterator of the selected features.
QString capabilitiesString() const
Returns the above in friendly format.
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
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 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.
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 & replace(int position, int n, QChar after)
Add selection to current selection.
QgsAttributeTableConfig attributeTableConfig() const
Get the attribute table configuration object.
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=nullptr)
render label
Definition: qgslabel.cpp:72
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.
int blue() const
const T & at(int i) const
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.
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.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
QString name() const
Get the display name of the layer.
Buffers information about expression fields for a vector layer.
QString getStyleById_t(const QString &uri, QString styleID, QString &errCause)
bool isEmpty() const
Returns true if the configuration is empty, ie it contains no columns.
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.
QgsVectorLayer(const QString &path=QString::null, const QString &baseName=QString::null, const QString &providerLib=QString::null, bool loadDefaultStyleFlag=true)
Constructor - creates a vector layer.
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
bool 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:771
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)
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
QgsVectorLayer::EditResult deleteVertexV2(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
Q_DECL_DEPRECATED void setSelectedFeatures(const QgsFeatureIds &ids)
Change selection to the new set of features.
void endMacro()
bool isEmpty() const
static QgsFeatureRendererV2 * load(QDomElement &symbologyElem)
create a renderer from XML element
virtual void reloadData()
Reloads the data from the source.
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.
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported...
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)...
QString readPath(QString filename, const QString &relativeBasePath=QString()) const
Turn filename read from the project file to an absolute path.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void repaintRequested()
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
This signal is emitted, when attributes are added to the provider.
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
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
virtual QString dataComment() const
Return a short comment for the data that this provider is providing access to (e.g.
Class for storing a coordinate reference system (CRS)
friend class QgsVectorLayerEditBuffer
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
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.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
virtual QString description() const =0
Return description.
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
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written. ...
virtual bool setSubsetString(const QString &subset)
Set the string (typically sql) used to define a subset of the layer.
bool toBool() const
virtual bool mustStop() const
return true if the iterator must stop as soon as possible
char * data()
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
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
Read the symbology of the layer according to the information contained in the UserStyle element of a ...
Basic implementation of the labeling interface.
void undo()
qint64 QgsFeatureId
Definition: qgsfeature.h:31
QgsFields pendingFields() const
Returns the list of fields of this layer.
void dataChanged()
Data of layer changed.
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
Base class for utility classes that encapsulate information necessary for rendering of map layers...
bool isValid() const
Remove from current selection.
void start()
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
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.
iterator insert(const Key &key, const T &value)
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.
bool isEmpty() const
void addRequiredFields(QgsAttributeList &fields) const
add vector of required fields to existing list of fields
Definition: qgslabel.cpp:459
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.
Edit failed due to invalid layer.
Custom exception class for Coordinate Reference System related exceptions.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QUndoStack * undoStack()
Return pointer to layer&#39;s undo stack.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
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.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
QString providerType() const
Return the provider type for this layer.
const_iterator constEnd() const
void normalize()
Normalize the rectangle so it has non-negative width/height.
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.
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
Q_DECL_DEPRECATED bool hasLabelsEnabled() const
Label is on.
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.
bool intersects(const QgsRectangle &rect) const
returns true when rectangle intersects with other rectangle
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.
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.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QString displayExpression() const
Get the preview expression, used to create a human readable preview string.
virtual QgsRectangle extent()
Return the extent of the layer.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void modifySelection(QgsFeatureIds selectIds, QgsFeatureIds deselectIds)
Modifies the current selection on this layer.
field is calculated from an expression
Definition: qgsfield.h:262
int selectedFeatureCount()
The number of features that are selected in this layer.
void updatedFields()
Is emitted, whenever the fields available from this layer have been changed.
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 ...
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void updateExpressionField(int index, const QString &exp)
Changes the expression used to define an expression based (virtual) field.
EditResult
Result of an edit operation.
const QgsVectorLayer * layer
Layer where the snap occurred.
Definition: qgssnapper.h:56
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Set the attribute table configuration object.
void layerModified()
This signal is emitted when modifications has been done on layer.
Q_DECL_DEPRECATED void drawLabels(QgsRenderContext &rendererContext) override
Draws the layer labels using the old labeling engine.
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
iterator begin()
int size() const
int beforeVertexNr
The index of the vertex before snappedVertex or -1 if no such vertex.
Definition: qgssnapper.h:47
void createJoinCaches()
Caches joined attributes if required (and not already done)
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as SLD style in a QDomDocument.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
int splitFeatures(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
bool hasNext() const
Aggregate
Available aggregates to calculate.
QString attributeAlias(int attributeIndex) const
Returns the alias of an attribute name or a null string if there is no alias.
Used by QgsVectorLayer::countSymbolFeatures() to provide an interruption checker. ...
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
bool isValid() const
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QDomNode at(int index) const
const T value(const Key &key) const
A bundle of parameters controlling aggregate calculation.
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError)
Save named and sld style of the layer to the style table in the db.
Q_DECL_DEPRECATED void enableLabels(bool on)
Set labels on.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
QgsRectangle boundingBoxOfSelected()
Returns the bounding box of the selected features.
bool saveStyle_t(const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
QByteArray toUtf8() const