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