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