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