QGIS API Documentation
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 "qgsattributeaction.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 QgsAttributeAction( 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.setThreshold( settings.value( "/qgis/simplifyDrawingTol", mSimplifyMethod.threshold() ).toFloat() );
169  mSimplifyMethod.setForceLocalOptimization( settings.value( "/qgis/simplifyLocal", mSimplifyMethod.forceLocalOptimization() ).toBool() );
170  mSimplifyMethod.setMaximumScale( settings.value( "/qgis/simplifyMaxScale", mSimplifyMethod.maximumScale() ).toFloat() );
171 } // QgsVectorLayer ctor
172 
173 
174 
176 {
177  QgsDebugMsg( "entered." );
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  }
381 }
382 
384 {
385  return new QgsVectorLayerRenderer( this, rendererContext );
386 }
387 
388 bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
389 {
390  QgsVectorLayerRenderer renderer( this, rendererContext );
391  return renderer.render();
392 }
393 
395 {
397  {
398  p.setPen( QColor( 50, 100, 120, 200 ) );
399  p.setBrush( QColor( 200, 200, 210, 120 ) );
400  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
401  }
402  else if ( type == QgsVectorLayer::Cross )
403  {
404  p.setPen( QColor( 255, 0, 0 ) );
405  p.drawLine( x - m, y + m, x + m, y - m );
406  p.drawLine( x - m, y - m, x + m, y + m );
407  }
408 }
409 
411 {
412  mSelectedFeatureIds.insert( fid );
413 
414  emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
415 }
416 
417 void QgsVectorLayer::select( const QgsFeatureIds& featureIds )
418 {
419  mSelectedFeatureIds.unite( featureIds );
420 
421  emit selectionChanged( featureIds, QgsFeatureIds(), false );
422 }
423 
425 {
426  mSelectedFeatureIds.remove( fid );
427 
428  emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
429 }
430 
431 void QgsVectorLayer::deselect( const QgsFeatureIds& featureIds )
432 {
433  mSelectedFeatureIds.subtract( featureIds );
434 
435  emit selectionChanged( QgsFeatureIds(), featureIds, false );
436 }
437 
438 void QgsVectorLayer::select( QgsRectangle & rect, bool addToSelection )
439 {
440  // normalize the rectangle
441  rect.normalize();
442 
443  //select all the elements
445  .setFilterRect( rect )
447  .setSubsetOfAttributes( QgsAttributeList() ) );
448 
449  QgsFeatureIds ids;
450 
451  QgsFeature f;
452  while ( fit.nextFeature( f ) )
453  {
454  ids << f.id();
455  }
456 
457  if ( !addToSelection )
458  {
459  setSelectedFeatures( mSelectedFeatureIds + ids );
460  }
461  else
462  {
463  select( ids );
464  }
465 }
466 
468 {
469  QgsFeatureIds intersectingIds = selectIds & deselectIds;
470  if ( !intersectingIds.isEmpty() )
471  {
472  QgsDebugMsg( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." );
473  }
474 
475  mSelectedFeatureIds -= deselectIds;
476  mSelectedFeatureIds += selectIds;
477 
478  emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
479 }
480 
482 {
484  ids.subtract( mSelectedFeatureIds );
485  setSelectedFeatures( ids );
486 }
487 
489 {
491 }
492 
494 {
496  .setFlags( QgsFeatureRequest::NoGeometry )
497  .setSubsetOfAttributes( QgsAttributeList() ) );
498 
499  QgsFeatureIds ids;
500 
501  QgsFeature fet;
502  while ( fit.nextFeature( fet ) )
503  {
504  ids << fet.id();
505  }
506 
507  return ids;
508 }
509 
511 {
512  // normalize the rectangle
513  rect.normalize();
514 
516  .setFilterRect( rect )
518  .setSubsetOfAttributes( QgsAttributeList() ) );
519 
520  QgsFeatureIds selectIds;
521  QgsFeatureIds deselectIds;
522 
523  QgsFeature fet;
524  while ( fit.nextFeature( fet ) )
525  {
526  if ( mSelectedFeatureIds.contains( fet.id() ) )
527  {
528  deselectIds << fet.id();
529  }
530  else
531  {
532  selectIds << fet.id();
533  }
534  }
535 
536  modifySelection( selectIds, deselectIds );
537 }
538 
540 {
541  if ( mSelectedFeatureIds.isEmpty() )
542  return;
543 
545 }
546 
548 {
549  return mDataProvider;
550 }
551 
553 {
554  return mDataProvider;
555 }
556 
558 {
559  if ( mValid && mDataProvider && mDataProvider->encoding() != encoding )
560  {
561  mDataProvider->setEncoding( encoding );
562  updateFields();
563  }
564 }
565 
567 {
568  delete mDiagramRenderer;
569  mDiagramRenderer = r;
570  emit rendererChanged();
571 }
572 
574 {
575  if ( mValid && mDataProvider )
576  {
577  QGis::WkbType type = mDataProvider->geometryType();
578  return static_cast< QGis::GeometryType >( QgsWKBTypes::geometryType( static_cast< QgsWKBTypes::Type >( type ) ) );
579  }
580  else
581  {
582  QgsDebugMsg( "invalid layer or pointer to mDataProvider is null" );
583  }
584 
585  // We shouldn't get here, and if we have, other things are likely to
586  // go wrong. Code that uses the type() return value should be
587  // rewritten to cope with a value of QGis::Unknown. To make this
588  // need known, the following message is printed every time we get
589  // here.
590  QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
591 
592  return QGis::UnknownGeometry;
593 }
594 
596 {
598  return t != QGis::NoGeometry && t != QGis::UnknownGeometry;
599 }
600 
602 {
603  return mWkbType;
604 }
605 
607 {
608  if ( !mValid || mSelectedFeatureIds.isEmpty() ) //no selected features
609  {
610  return QgsRectangle( 0, 0, 0, 0 );
611  }
612 
613  QgsRectangle r, retval;
614  retval.setMinimal();
615 
616  QgsFeature fet;
617  if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
618  {
620  .setFilterFids( mSelectedFeatureIds )
621  .setSubsetOfAttributes( QgsAttributeList() ) );
622 
623  while ( fit.nextFeature( fet ) )
624  {
625  if ( !fet.constGeometry() || fet.constGeometry()->isEmpty() )
626  continue;
627  r = fet.constGeometry()->boundingBox();
628  retval.combineExtentWith( &r );
629  }
630  }
631  else
632  {
634  .setSubsetOfAttributes( QgsAttributeList() ) );
635 
636  while ( fit.nextFeature( fet ) )
637  {
638  if ( mSelectedFeatureIds.contains( fet.id() ) )
639  {
640  if ( fet.constGeometry() )
641  {
642  r = fet.constGeometry()->boundingBox();
643  retval.combineExtentWith( &r );
644  }
645  }
646  }
647  }
648 
649  if ( retval.width() == 0.0 || retval.height() == 0.0 )
650  {
651  // If all of the features are at the one point, buffer the
652  // rectangle a bit. If they are all at zero, do something a bit
653  // more crude.
654 
655  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
656  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
657  {
658  retval.set( -1.0, -1.0, 1.0, 1.0 );
659  }
660  }
661 
662  return retval;
663 }
664 
666 {
667  if ( !mLabeling )
668  return false;
669 
670  // for simple labeling the mode can be "no labels" - so we need to check
671  // in properties whether we are really enabled or not
672  if ( mLabeling->type() == "simple" )
673  return customProperty( "labeling/enabled", QVariant( false ) ).toBool();
674 
675  // for other labeling implementations we always assume that labeling is enabled
676  return true;
677 }
678 
680 {
681  if ( !mDiagramRenderer || !mDiagramLayerSettings )
682  return false;
683 
684  QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
685  if ( !settingList.isEmpty() )
686  {
687  return settingList.at( 0 ).enabled;
688  }
689  return false;
690 }
691 
693 {
694  if ( !mSymbolFeatureCounted )
695  return -1;
696 
697  return mSymbolFeatureCountMap.value( symbol );
698 }
699 
704 {
705  public:
706 
709  : mDialog( dialog )
710  {
711  }
712 
713  virtual bool mustStop() const
714  {
715  if ( mDialog->isVisible() )
716  {
717  // So that we get a chance of hitting the Abort button
718 #ifdef Q_OS_LINUX
719  // For some reason on Windows hasPendingEvents() always return true,
720  // but one iteration is actually enough on Windows to get good interactivity
721  // whereas on Linux we must allow for far more iterations.
722  // For safety limit the number of iterations
723  int nIters = 0;
724  while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
725 #endif
726  {
728  }
729  return mDialog->wasCanceled();
730  }
731  return false;
732  }
733 
734  private:
735  QProgressDialog* mDialog;
736 };
737 
738 bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
739 {
740  if ( mSymbolFeatureCounted )
741  return true;
742 
743  mSymbolFeatureCountMap.clear();
744 
745  if ( !mValid )
746  {
747  QgsDebugMsg( "invoked with invalid layer" );
748  return false;
749  }
750  if ( !mDataProvider )
751  {
752  QgsDebugMsg( "invoked with null mDataProvider" );
753  return false;
754  }
755  if ( !mRendererV2 )
756  {
757  QgsDebugMsg( "invoked with null mRendererV2" );
758  return false;
759  }
760 
761  QgsLegendSymbolList symbolList = mRendererV2->legendSymbolItems();
762  QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
763 
764  for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
765  {
766  mSymbolFeatureCountMap.insert( symbolIt->second, 0 );
767  }
768 
769  long nFeatures = featureCount();
770 
771  QWidget* mainWindow = nullptr;
772  Q_FOREACH ( QWidget* widget, qApp->topLevelWidgets() )
773  {
774  if ( widget->objectName() == "QgisApp" )
775  {
776  mainWindow = widget;
777  break;
778  }
779  }
780 
781  QProgressDialog progressDialog( tr( "Updating feature count for layer %1" ).arg( name() ), tr( "Abort" ), 0, nFeatures, mainWindow );
782  progressDialog.setWindowTitle( tr( "QGIS" ) );
783  progressDialog.setWindowModality( Qt::WindowModal );
784  if ( showProgress )
785  {
786  // Properly initialize to 0 as recommended in doc so that the evaluation
787  // of the total time properly works
788  progressDialog.setValue( 0 );
789  }
790  int featuresCounted = 0;
791 
793  QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures interruptionCheck( &progressDialog );
794  if ( showProgress )
795  {
796  fit.setInterruptionChecker( &interruptionCheck );
797  }
798 
799  // Renderer (rule based) may depend on context scale, with scale is ignored if 0
800  QgsRenderContext renderContext;
801  renderContext.setRendererScale( 0 );
805 
806  mRendererV2->startRender( renderContext, fields() );
807 
808  QgsFeature f;
809  QTime time;
810  time.start();
811  while ( fit.nextFeature( f ) )
812  {
813  renderContext.expressionContext().setFeature( f );
814  QgsSymbolV2List featureSymbolList = mRendererV2->originalSymbolsForFeature( f, renderContext );
815  for ( QgsSymbolV2List::iterator symbolIt = featureSymbolList.begin(); symbolIt != featureSymbolList.end(); ++symbolIt )
816  {
817  mSymbolFeatureCountMap[*symbolIt] += 1;
818  }
819  ++featuresCounted;
820 
821  if ( showProgress )
822  {
823  // Refresh progress every 50 features or second
824  if (( featuresCounted % 50 == 0 ) || time.elapsed() > 1000 )
825  {
826  time.restart();
827  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
828  {
829  progressDialog.setMaximum( 0 );
830  }
831  progressDialog.setValue( featuresCounted );
832  }
833  // So that we get a chance of hitting the Abort button
834 #ifdef Q_OS_LINUX
835  // For some reason on Windows hasPendingEvents() always return true,
836  // but one iteration is actually enough on Windows to get good interactivity
837  // whereas on Linux we must allow for far more iterations.
838  // For safety limit the number of iterations
839  int nIters = 0;
840  while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
841 #endif
842  {
844  }
845  if ( progressDialog.wasCanceled() )
846  {
847  mSymbolFeatureCountMap.clear();
848  mRendererV2->stopRender( renderContext );
849  return false;
850  }
851  }
852  }
853  mRendererV2->stopRender( renderContext );
854  progressDialog.setValue( nFeatures );
855  mSymbolFeatureCounted = true;
856  return true;
857 }
858 
860 {
861  mValidExtent = false;
862 }
863 
865 {
867  mValidExtent = true;
868 }
869 
871 {
872  QgsRectangle rect;
873  rect.setMinimal();
874 
875  if ( !hasGeometryType() )
876  return rect;
877 
878  if ( !mValidExtent && mLazyExtent && mDataProvider )
879  {
880  // get the extent
881  QgsRectangle mbr = mDataProvider->extent();
882 
883  // show the extent
884  QString s = mbr.toString();
885 
886  QgsDebugMsg( "Extent of layer: " + s );
887  // store the extent
888  setExtent( mbr );
889 
890  mLazyExtent = false;
891  }
892 
893  if ( mValidExtent )
894  return QgsMapLayer::extent();
895 
896  if ( !mValid || !mDataProvider )
897  {
898  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
899  return rect;
900  }
901 
902  if ( !mEditBuffer ||
903  ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() ) ||
904  QgsDataSourceURI( mDataProvider->dataSourceUri() ).useEstimatedMetadata() )
905  {
906  mDataProvider->updateExtents();
907 
908  // get the extent of the layer from the provider
909  // but only when there are some features already
910  if ( mDataProvider->featureCount() != 0 )
911  {
912  QgsRectangle r = mDataProvider->extent();
913  rect.combineExtentWith( &r );
914  }
915 
916  if ( mEditBuffer )
917  {
918  for ( QgsFeatureMap::const_iterator it = mEditBuffer->mAddedFeatures.constBegin(); it != mEditBuffer->mAddedFeatures.constEnd(); ++it )
919  {
920  if ( it->constGeometry() )
921  {
922  QgsRectangle r = it->constGeometry()->boundingBox();
923  rect.combineExtentWith( &r );
924  }
925  }
926  }
927  }
928  else
929  {
931  .setSubsetOfAttributes( QgsAttributeList() ) );
932 
933  QgsFeature fet;
934  while ( fit.nextFeature( fet ) )
935  {
936  if ( fet.constGeometry() && fet.constGeometry()->type() != QGis::UnknownGeometry )
937  {
938  QgsRectangle bb = fet.constGeometry()->boundingBox();
939  rect.combineExtentWith( &bb );
940  }
941  }
942  }
943 
944  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
945  {
946  // special case when there are no features in provider nor any added
947  rect = QgsRectangle(); // use rectangle with zero coordinates
948  }
949 
950  setExtent( rect );
951 
952  // Send this (hopefully) up the chain to the map canvas
953  emit recalculateExtents();
954 
955  return rect;
956 }
957 
959 {
960  if ( !mValid || !mDataProvider )
961  {
962  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
963  return nullptr;
964  }
965  return mDataProvider->subsetString();
966 }
967 
969 {
970  if ( !mValid || !mDataProvider )
971  {
972  QgsDebugMsg( "invoked with invalid layer or null mDataProvider" );
973  return false;
974  }
975 
976  bool res = mDataProvider->setSubsetString( subset );
977 
978  // get the updated data source string from the provider
979  mDataSource = mDataProvider->dataSourceUri();
980  updateExtents();
981 
982  if ( res )
983  emit repaintRequested();
984 
985  return res;
986 }
987 
989 {
990  if ( mValid && mDataProvider && !mEditBuffer && ( hasGeometryType() && geometryType() != QGis::Point ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
991  {
992  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
993 
994  // check maximum scale at which generalisation should be carried out
995  if ( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale )
996  return false;
997 
998  return true;
999  }
1000  return false;
1001 }
1002 
1004 {
1005  return mConditionalStyles;
1006 }
1007 
1009 {
1010  if ( !mValid || !mDataProvider )
1011  return QgsFeatureIterator();
1012 
1013  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
1014 }
1015 
1016 
1017 bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
1018 {
1019  Q_UNUSED( alsoUpdateExtent ); // TODO[MD]
1020  if ( !mValid || !mEditBuffer || !mDataProvider )
1021  return false;
1022 
1023  bool success = mEditBuffer->addFeature( f );
1024 
1025  if ( success )
1026  updateExtents();
1027 
1028  return success;
1029 }
1030 
1032 {
1033  QgsFeatureRequest req;
1034  req.setFilterFid( f.id() );
1035  if ( !f.constGeometry() )
1037  if ( f.attributes().isEmpty() )
1039 
1040  QgsFeature current;
1041  if ( !getFeatures( req ).nextFeature( current ) )
1042  {
1043  QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( f.id() ) );
1044  return false;
1045  }
1046 
1047  if ( f.constGeometry() && current.constGeometry() && f.constGeometry() != current.constGeometry() && !f.constGeometry()->isGeosEqual( *current.constGeometry() ) )
1048  {
1049  if ( !changeGeometry( f.id(), f.geometry() ) )
1050  {
1051  QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( f.id() ) );
1052  return false;
1053  }
1054  }
1055 
1056  QgsAttributes fa = f.attributes();
1057  QgsAttributes ca = current.attributes();
1058 
1059  for ( int attr = 0; attr < fa.count(); ++attr )
1060  {
1061  if ( fa.at( attr ) != ca.at( attr ) )
1062  {
1063  if ( !changeAttributeValue( f.id(), attr, fa.at( attr ), ca.at( attr ) ) )
1064  {
1065  QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( f.id() ) );
1066  return false;
1067  }
1068  }
1069  }
1070 
1071  return true;
1072 }
1073 
1074 
1075 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1076 {
1077  if ( !mValid || !mEditBuffer || !mDataProvider )
1078  return false;
1079 
1080  QgsVectorLayerEditUtils utils( this );
1081  bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
1082  if ( result )
1083  updateExtents();
1084  return result;
1085 }
1086 
1087 
1088 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1089 {
1090  if ( !mValid || !mEditBuffer || !mDataProvider )
1091  return false;
1092 
1093  QgsVectorLayerEditUtils utils( this );
1094  bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
1095 
1096  if ( result )
1097  updateExtents();
1098  return result;
1099 }
1100 
1101 bool QgsVectorLayer::moveVertex( const QgsPointV2& p, QgsFeatureId atFeatureId, int atVertex )
1102 {
1103  if ( !mValid || !mEditBuffer || !mDataProvider )
1104  return false;
1105 
1106  QgsVectorLayerEditUtils utils( this );
1107  bool result = utils.moveVertex( p, atFeatureId, atVertex );
1108 
1109  if ( result )
1110  updateExtents();
1111  return result;
1112 }
1113 
1114 bool QgsVectorLayer::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
1115 {
1116  QgsVectorLayer::EditResult res = deleteVertexV2( atFeatureId, atVertex );
1117  bool result = ( res == QgsVectorLayer::Success || res == QgsVectorLayer::EmptyGeometry );
1118 
1119  if ( result )
1120  updateExtents();
1121  return result;
1122 }
1123 
1125 {
1126  if ( !mValid || !mEditBuffer || !mDataProvider )
1128 
1129  QgsVectorLayerEditUtils utils( this );
1130  EditResult result = utils.deleteVertexV2( featureId, vertex );
1131 
1132  if ( result == Success )
1133  updateExtents();
1134  return result;
1135 }
1136 
1137 
1139 {
1140  if ( !mValid || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1141  {
1142  return false;
1143  }
1144 
1145  if ( !isEditable() )
1146  {
1147  return false;
1148  }
1149 
1150  int deleted = 0;
1151  int count = mSelectedFeatureIds.size();
1152  // Make a copy since deleteFeature modifies mSelectedFeatureIds
1153  QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1154  Q_FOREACH ( QgsFeatureId fid, selectedFeatures )
1155  {
1156  deleted += deleteFeature( fid ); // removes from selection
1157  }
1158 
1159  triggerRepaint();
1160  updateExtents();
1161 
1162  if ( deletedCount )
1163  {
1164  *deletedCount = deleted;
1165  }
1166 
1167  return deleted == count;
1168 }
1169 
1171 {
1172  if ( !mValid || !mEditBuffer || !mDataProvider )
1173  return 6;
1174 
1175  QgsVectorLayerEditUtils utils( this );
1176  int result = 5;
1177 
1178  //first try with selected features
1179  if ( !mSelectedFeatureIds.isEmpty() )
1180  {
1181  result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1182  }
1183 
1184  if ( result != 0 )
1185  {
1186  //try with all intersecting features
1187  result = utils.addRing( ring, QgsFeatureIds(), featureId );
1188  }
1189 
1190  return result;
1191 }
1192 
1194 {
1195  if ( !mValid || !mEditBuffer || !mDataProvider )
1196  {
1197  delete ring;
1198  return 6;
1199  }
1200 
1201  if ( !ring )
1202  {
1203  return 1;
1204  }
1205 
1206  if ( !ring->isClosed() )
1207  {
1208  delete ring;
1209  return 2;
1210  }
1211 
1212  QgsVectorLayerEditUtils utils( this );
1213  int result = 5;
1214 
1215  //first try with selected features
1216  if ( !mSelectedFeatureIds.isEmpty() )
1217  {
1218  result = utils.addRing( static_cast< QgsCurveV2* >( ring->clone() ), mSelectedFeatureIds, featureId );
1219  }
1220 
1221  if ( result != 0 )
1222  {
1223  //try with all intersecting features
1224  result = utils.addRing( static_cast< QgsCurveV2* >( ring->clone() ), QgsFeatureIds(), featureId );
1225  }
1226 
1227  delete ring;
1228  return result;
1229 }
1230 
1232 {
1233  if ( !mValid || !mEditBuffer || !mDataProvider )
1234  return 7;
1235 
1236  //number of selected features must be 1
1237 
1238  if ( mSelectedFeatureIds.size() < 1 )
1239  {
1240  QgsDebugMsg( "Number of selected features <1" );
1241  return 4;
1242  }
1243  else if ( mSelectedFeatureIds.size() > 1 )
1244  {
1245  QgsDebugMsg( "Number of selected features >1" );
1246  return 5;
1247  }
1248 
1249  QgsVectorLayerEditUtils utils( this );
1250  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1251 
1252  if ( result == 0 )
1253  updateExtents();
1254  return result;
1255 }
1256 
1258 {
1259  if ( !mValid || !mEditBuffer || !mDataProvider )
1260  return 7;
1261 
1262  //number of selected features must be 1
1263 
1264  if ( mSelectedFeatureIds.size() < 1 )
1265  {
1266  QgsDebugMsg( "Number of selected features <1" );
1267  return 4;
1268  }
1269  else if ( mSelectedFeatureIds.size() > 1 )
1270  {
1271  QgsDebugMsg( "Number of selected features >1" );
1272  return 5;
1273  }
1274 
1275  QgsVectorLayerEditUtils utils( this );
1276  int result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1277 
1278  if ( result == 0 )
1279  updateExtents();
1280  return result;
1281 }
1282 
1284 {
1285  if ( !mValid || !mEditBuffer || !mDataProvider )
1286  return 7;
1287 
1288  //number of selected features must be 1
1289 
1290  if ( mSelectedFeatureIds.size() < 1 )
1291  {
1292  QgsDebugMsg( "Number of selected features <1" );
1293  return 4;
1294  }
1295  else if ( mSelectedFeatureIds.size() > 1 )
1296  {
1297  QgsDebugMsg( "Number of selected features >1" );
1298  return 5;
1299  }
1300 
1301  QgsVectorLayerEditUtils utils( this );
1302  int result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1303 
1304  if ( result == 0 )
1305  updateExtents();
1306  return result;
1307 }
1308 
1309 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1310 {
1311  if ( !mValid || !mEditBuffer || !mDataProvider )
1312  return -1;
1313 
1314  QgsVectorLayerEditUtils utils( this );
1315  int result = utils.translateFeature( featureId, dx, dy );
1316 
1317  if ( result == 0 )
1318  updateExtents();
1319  return result;
1320 }
1321 
1322 int QgsVectorLayer::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1323 {
1324  if ( !mValid || !mEditBuffer || !mDataProvider )
1325  return -1;
1326 
1327  QgsVectorLayerEditUtils utils( this );
1328  return utils.splitParts( splitLine, topologicalEditing );
1329 }
1330 
1331 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1332 {
1333  if ( !mValid || !mEditBuffer || !mDataProvider )
1334  return -1;
1335 
1336  QgsVectorLayerEditUtils utils( this );
1337  return utils.splitFeatures( splitLine, topologicalEditing );
1338 }
1339 
1341 {
1342  if ( !hasGeometryType() )
1343  return 1;
1344 
1345  int returnValue = 0;
1346 
1347  //first test if geom really has type polygon or multipolygon
1348  if ( geom->type() != QGis::Polygon )
1349  {
1350  return 1;
1351  }
1352 
1353  //get bounding box of geom
1354  QgsRectangle geomBBox = geom->boundingBox();
1355 
1356  //get list of features that intersect this bounding box
1358  .setFilterRect( geomBBox )
1360  .setSubsetOfAttributes( QgsAttributeList() ) );
1361 
1362  QgsFeature f;
1363  while ( fit.nextFeature( f ) )
1364  {
1365  if ( ignoreFeatures.contains( f.id() ) )
1366  {
1367  continue;
1368  }
1369 
1370  //call geometry->makeDifference for each feature
1371  const QgsGeometry *currentGeom = f.constGeometry();
1372  if ( currentGeom )
1373  {
1374  if ( geom->makeDifference( currentGeom ) != 0 )
1375  {
1376  returnValue = 2;
1377  }
1378  }
1379  }
1380 
1381  return returnValue;
1382 }
1383 
1385 {
1386  if ( !mValid || !mEditBuffer || !mDataProvider )
1387  return -1;
1388 
1389  QgsVectorLayerEditUtils utils( this );
1390  return utils.addTopologicalPoints( geom );
1391 }
1392 
1394 {
1395  if ( !mValid || !mEditBuffer || !mDataProvider )
1396  return -1;
1397 
1398  QgsVectorLayerEditUtils utils( this );
1399  return utils.addTopologicalPoints( p );
1400 }
1401 
1403 {
1404  return mLabel;
1405 }
1406 
1408 {
1409  return mLabel;
1410 }
1411 
1413 {
1414  mLabelOn = on;
1415 }
1416 
1418 {
1419  return mLabelOn;
1420 }
1421 
1423 {
1424  if ( mLabeling == labeling )
1425  return;
1426 
1427  delete mLabeling;
1428  mLabeling = labeling;
1429 }
1430 
1432 {
1433  if ( !mValid || !mDataProvider )
1434  {
1435  return false;
1436  }
1437 
1438  // allow editing if provider supports any of the capabilities
1439  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1440  {
1441  return false;
1442  }
1443 
1444  if ( mReadOnly )
1445  {
1446  return false;
1447  }
1448 
1449  if ( mEditBuffer )
1450  {
1451  // editing already underway
1452  return false;
1453  }
1454 
1455  emit beforeEditingStarted();
1456 
1457  if ( mDataProvider->transaction() )
1458  {
1459  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1460  }
1461  else
1462  {
1463  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1464  }
1465  // forward signals
1466  connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( invalidateSymbolCountedFlag() ) );
1467  connect( mEditBuffer, SIGNAL( layerModified() ), this, SIGNAL( layerModified() ) ); // TODO[MD]: necessary?
1468  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1469  connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( featureAdded( QgsFeatureId ) ) );
1470  connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
1471  connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
1472  connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
1473  connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), this, SIGNAL( attributeAdded( int ) ) );
1474  connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), this, SIGNAL( attributeDeleted( int ) ) );
1475 
1476  connect( mEditBuffer, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ),
1477  this, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ) );
1478 
1479  connect( mEditBuffer, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ),
1480  this, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ) );
1481 
1482  connect( mEditBuffer, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ), this, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ) );
1483  connect( mEditBuffer, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ), this, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ) );
1484 
1485  connect( mEditBuffer, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ),
1486  this, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ) );
1487 
1488  connect( mEditBuffer, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ),
1489  this, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ) );
1490 
1491  updateFields();
1492 
1493  emit editingStarted();
1494 
1495  return true;
1496 }
1497 
1498 bool QgsVectorLayer::readXml( const QDomNode& layer_node )
1499 {
1500  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
1501 
1502  //process provider key
1503  QDomNode pkeyNode = layer_node.namedItem( "provider" );
1504 
1505  if ( pkeyNode.isNull() )
1506  {
1507  mProviderKey = "";
1508  }
1509  else
1510  {
1511  QDomElement pkeyElt = pkeyNode.toElement();
1512  mProviderKey = pkeyElt.text();
1513  }
1514 
1515  // determine type of vector layer
1516  if ( !mProviderKey.isNull() )
1517  {
1518  // if the provider string isn't empty, then we successfully
1519  // got the stored provider
1520  }
1521  else if ( mDataSource.contains( "dbname=" ) )
1522  {
1523  mProviderKey = "postgres";
1524  }
1525  else
1526  {
1527  mProviderKey = "ogr";
1528  }
1529 
1530  if ( !setDataProvider( mProviderKey ) )
1531  {
1532  return false;
1533  }
1534 
1535  QDomElement mapLayerNode = layer_node.toElement();
1536  if ( mapLayerNode.attribute( "readOnly", "0" ).toInt() == 1 )
1537  mReadOnly = true;
1538 
1539  QDomElement pkeyElem = pkeyNode.toElement();
1540  if ( !pkeyElem.isNull() )
1541  {
1542  QString encodingString = pkeyElem.attribute( "encoding" );
1543  if ( !encodingString.isEmpty() )
1544  {
1545  mDataProvider->setEncoding( encodingString );
1546  }
1547  }
1548 
1549  //load vector joins
1550  if ( !mJoinBuffer )
1551  {
1552  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1553  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1554  }
1555  mJoinBuffer->readXml( layer_node );
1556 
1557  if ( !mExpressionFieldBuffer )
1558  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1559  mExpressionFieldBuffer->readXml( layer_node );
1560 
1561  updateFields();
1562  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1563 
1564  QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );
1565 
1566  if ( prevExpNode.isNull() )
1567  {
1568  mDisplayExpression = "";
1569  }
1570  else
1571  {
1572  QDomElement prevExpElem = prevExpNode.toElement();
1573  mDisplayExpression = prevExpElem.text();
1574  }
1575 
1576  QString errorMsg;
1577  if ( !readSymbology( layer_node, errorMsg ) )
1578  {
1579  return false;
1580  }
1581 
1582  readStyleManager( layer_node );
1583 
1584 
1586 
1587  return mValid; // should be true if read successfully
1588 
1589 } // void QgsVectorLayer::readXml
1590 
1591 
1592 void QgsVectorLayer::setDataSource( const QString& dataSource, const QString& baseName, const QString& provider, bool loadDefaultStyleFlag )
1593 {
1594  QGis::GeometryType oldGeomType = geometryType();
1595 
1596  mDataSource = dataSource;
1597  mLayerName = capitaliseLayerName( baseName );
1599  setDataProvider( provider );
1600 
1601  if ( !mValid )
1602  return;
1603 
1604  // Always set crs
1606 
1607  // reset style if loading default style, style is missing, or geometry type has changed
1608  if ( !rendererV2() || !legend() || oldGeomType != geometryType() || loadDefaultStyleFlag )
1609  {
1610  // check if there is a default style / propertysheet defined
1611  // for this layer and if so apply it
1612  bool defaultLoadedFlag = false;
1613  if ( loadDefaultStyleFlag )
1614  {
1615  loadDefaultStyle( defaultLoadedFlag );
1616  }
1617 
1618  // if the default style failed to load or was disabled use some very basic defaults
1619  if ( !defaultLoadedFlag && hasGeometryType() )
1620  {
1621  // add single symbol renderer
1623  }
1624 
1626  }
1627 
1628  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1629  emit repaintRequested();
1630 }
1631 
1632 
1633 bool QgsVectorLayer::setDataProvider( QString const & provider )
1634 {
1635  mProviderKey = provider; // XXX is this necessary? Usually already set
1636  // XXX when execution gets here.
1637 
1638  //XXX - This was a dynamic cast but that kills the Windows
1639  // version big-time with an abnormal termination error
1640  delete mDataProvider;
1641  mDataProvider = ( QgsVectorDataProvider* )( QgsProviderRegistry::instance()->provider( provider, mDataSource ) );
1642  connect( mDataProvider, SIGNAL( raiseError( QString ) ), this, SIGNAL( raiseError( QString ) ) );
1643 
1644  if ( !mDataProvider )
1645  {
1646  QgsDebugMsg( " unable to get data provider" );
1647  return false;
1648  }
1649 
1650  QgsDebugMsg( "Instantiated the data provider plugin" );
1651 
1652  mValid = mDataProvider->isValid();
1653  if ( !mValid )
1654  {
1655  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1656  return false;
1657  }
1658 
1659  // TODO: Check if the provider has the capability to send fullExtentCalculated
1660  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
1661 
1662  // get and store the feature type
1663  mWkbType = mDataProvider->geometryType();
1664 
1665  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1666  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1667  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1668  updateFields();
1669 
1670  // look at the fields in the layer and set the primary
1671  // display field using some real fuzzy logic
1672  setDisplayField();
1673 
1674  if ( mProviderKey == "postgres" )
1675  {
1676  QgsDebugMsg( "Beautifying layer name " + name() );
1677 
1678  // adjust the display name for postgres layers
1679  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1680  if ( reg.indexIn( name() ) >= 0 )
1681  {
1682  QStringList stuff = reg.capturedTexts();
1683  QString lName = stuff[1];
1684 
1686 
1688  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1689  ;
1690 
1691  if ( it != layers.constEnd() && stuff.size() > 2 )
1692  {
1693  lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1694  }
1695 
1696  if ( !lName.isEmpty() )
1697  setLayerName( lName );
1698  }
1699 
1700  QgsDebugMsg( "Beautified layer name " + name() );
1701 
1702  // deal with unnecessary schema qualification to make v.in.ogr happy
1703  mDataSource = mDataProvider->dataSourceUri();
1704  }
1705  else if ( mProviderKey == "osm" )
1706  {
1707  // make sure that the "observer" has been removed from URI to avoid crashes
1708  mDataSource = mDataProvider->dataSourceUri();
1709  }
1710  else if ( provider == "ogr" )
1711  {
1712  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1713  mDataSource = mDataProvider->dataSourceUri();
1714  if ( mDataSource.right( 10 ) == "|layerid=0" )
1715  mDataSource.chop( 10 );
1716  }
1717 
1718  // label
1719  mLabel = new QgsLabel( mDataProvider->fields() );
1720  mLabelOn = false;
1721 
1722  connect( mDataProvider, SIGNAL( dataChanged() ), this, SIGNAL( dataChanged() ) );
1723  connect( mDataProvider, SIGNAL( dataChanged() ), this, SLOT( removeSelection() ) );
1724 
1725  return true;
1726 } // QgsVectorLayer:: setDataProvider
1727 
1728 
1729 
1730 
1731 /* virtual */
1733  QDomDocument & document )
1734 {
1735  // first get the layer element so that we can append the type attribute
1736 
1737  QDomElement mapLayerNode = layer_node.toElement();
1738 
1739  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1740  {
1741  QgsDebugMsg( "can't find <maplayer>" );
1742  return false;
1743  }
1744 
1745  mapLayerNode.setAttribute( "type", "vector" );
1746 
1747  // set the geometry type
1748  mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
1749 
1750  // add provider node
1751  if ( mDataProvider )
1752  {
1753  QDomElement provider = document.createElement( "provider" );
1754  provider.setAttribute( "encoding", mDataProvider->encoding() );
1755  QDomText providerText = document.createTextNode( providerType() );
1756  provider.appendChild( providerText );
1757  layer_node.appendChild( provider );
1758  }
1759 
1760  // save readonly state
1761  mapLayerNode.setAttribute( "readOnly", mReadOnly );
1762 
1763  // save preview expression
1764  QDomElement prevExpElem = document.createElement( "previewExpression" );
1765  QDomText prevExpText = document.createTextNode( mDisplayExpression );
1766  prevExpElem.appendChild( prevExpText );
1767  layer_node.appendChild( prevExpElem );
1768 
1769  //save joins
1770  mJoinBuffer->writeXml( layer_node, document );
1771 
1772  // dependencies
1773  QDomElement dependenciesElement = document.createElement( "layerDependencies" );
1774  Q_FOREACH ( QString layerId, layerDependencies() )
1775  {
1776  QDomElement depElem = document.createElement( "layer" );
1777  depElem.setAttribute( "id", layerId );
1778  dependenciesElement.appendChild( depElem );
1779  }
1780  layer_node.appendChild( dependenciesElement );
1781 
1782  // save expression fields
1783  mExpressionFieldBuffer->writeXml( layer_node, document );
1784 
1785  writeStyleManager( layer_node, document );
1786 
1787  // renderer specific settings
1788  QString errorMsg;
1789  return writeSymbology( layer_node, document, errorMsg );
1790 } // bool QgsVectorLayer::writeXml
1791 
1792 
1793 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
1794 {
1795  emit readCustomSymbology( node.toElement(), errorMessage );
1796 
1797  if ( hasGeometryType() )
1798  {
1799  // try renderer v2 first
1800  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1801  if ( !rendererElement.isNull() )
1802  {
1803  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
1804  if ( !r )
1805  return false;
1806 
1807  setRendererV2( r );
1808  }
1809  else
1810  {
1812  if ( !r )
1814 
1815  setRendererV2( r );
1816  }
1817 
1818  QDomElement labelingElement = node.firstChildElement( "labeling" );
1819  if ( !labelingElement.isNull() )
1820  {
1823  }
1824 
1825  // get and set the display field if it exists.
1826  QDomNode displayFieldNode = node.namedItem( "displayfield" );
1827  if ( !displayFieldNode.isNull() )
1828  {
1829  QDomElement e = displayFieldNode.toElement();
1830  setDisplayField( e.text() );
1831  }
1832 
1833  // get and set the blend mode if it exists
1834  QDomNode blendModeNode = node.namedItem( "blendMode" );
1835  if ( !blendModeNode.isNull() )
1836  {
1837  QDomElement e = blendModeNode.toElement();
1838  setBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
1839  }
1840 
1841  // get and set the feature blend mode if it exists
1842  QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
1843  if ( !featureBlendModeNode.isNull() )
1844  {
1845  QDomElement e = featureBlendModeNode.toElement();
1846  setFeatureBlendMode( QgsMapRenderer::getCompositionMode( static_cast< QgsMapRenderer::BlendMode >( e.text().toInt() ) ) );
1847  }
1848 
1849  // get and set the layer transparency if it exists
1850  QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
1851  if ( !layerTransparencyNode.isNull() )
1852  {
1853  QDomElement e = layerTransparencyNode.toElement();
1854  setLayerTransparency( e.text().toInt() );
1855  }
1856 
1857  // use scale dependent visibility flag
1858  QDomElement e = node.toElement();
1859  if ( mLabel )
1860  {
1861  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
1862  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
1863  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
1864  }
1865 
1866  // get the simplification drawing settings
1867  mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( "simplifyDrawingHints", "1" ).toInt() ) );
1868  mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
1869  mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
1870  mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
1871 
1872  //also restore custom properties (for labeling-ng)
1873  readCustomProperties( node, "labeling" );
1874 
1875  // Test if labeling is on or off
1876  QDomNode labelnode = node.namedItem( "label" );
1877  QDomElement element = labelnode.toElement();
1878  int hasLabelsEnabled = element.text().toInt();
1880  if ( hasLabelsEnabled < 1 )
1881  {
1882  enableLabels( false );
1883  }
1884  else
1885  {
1886  enableLabels( true );
1887  }
1889 
1890  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
1891 
1892  if ( !labelattributesnode.isNull() && mLabel )
1893  {
1894  QgsDebugMsg( "calling readXML" );
1895  mLabel->readXML( labelattributesnode );
1896  }
1897 
1898  //diagram renderer and diagram layer settings
1899  delete mDiagramRenderer;
1900  mDiagramRenderer = nullptr;
1901  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
1902  if ( !singleCatDiagramElem.isNull() )
1903  {
1904  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1905  mDiagramRenderer->readXML( singleCatDiagramElem, this );
1906  }
1907  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
1908  if ( !linearDiagramElem.isNull() )
1909  {
1910  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
1911  mDiagramRenderer->readXML( linearDiagramElem, this );
1912  }
1913 
1914  if ( mDiagramRenderer )
1915  {
1916  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
1917  if ( !diagramSettingsElem.isNull() )
1918  {
1919  delete mDiagramLayerSettings;
1920  mDiagramLayerSettings = new QgsDiagramLayerSettings();
1921  mDiagramLayerSettings->readXML( diagramSettingsElem, this );
1922  }
1923  }
1924  }
1925 
1926  // process the attribute actions
1927  mActions->readXML( node );
1928 
1929  mEditFormConfig->readXml( node );
1930 
1931  QDomNode annotationFormNode = node.namedItem( "annotationform" );
1932  if ( !annotationFormNode.isNull() )
1933  {
1934  QDomElement e = annotationFormNode.toElement();
1935  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1936  }
1937 
1938  mAttributeAliasMap.clear();
1939  QDomNode aliasesNode = node.namedItem( "aliases" );
1940  if ( !aliasesNode.isNull() )
1941  {
1942  QDomElement aliasElem;
1943 
1944  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
1945  for ( int i = 0; i < aliasNodeList.size(); ++i )
1946  {
1947  aliasElem = aliasNodeList.at( i ).toElement();
1948 
1949  QString field;
1950  if ( aliasElem.hasAttribute( "field" ) )
1951  {
1952  field = aliasElem.attribute( "field" );
1953  }
1954  else
1955  {
1956  int index = aliasElem.attribute( "index" ).toInt();
1957 
1958  if ( index >= 0 && index < fields().count() )
1959  field = fields().at( index ).name();
1960  }
1961 
1962  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
1963  }
1964  }
1965 
1966  //Attributes excluded from WMS and WFS
1967  mExcludeAttributesWMS.clear();
1968  QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
1969  if ( !excludeWMSNode.isNull() )
1970  {
1971  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
1972  for ( int i = 0; i < attributeNodeList.size(); ++i )
1973  {
1974  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1975  }
1976  }
1977 
1978  mExcludeAttributesWFS.clear();
1979  QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
1980  if ( !excludeWFSNode.isNull() )
1981  {
1982  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
1983  for ( int i = 0; i < attributeNodeList.size(); ++i )
1984  {
1985  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1986  }
1987  }
1988 
1989  mEditFormConfig->readXml( node );
1990 
1991  mConditionalStyles->readXml( node );
1992 
1993  return true;
1994 }
1995 
1996 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1997 {
1998  QDomElement mapLayerNode = node.toElement();
1999 
2000  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2001 
2002  if ( hasGeometryType() )
2003  {
2004  QDomElement rendererElement = mRendererV2->save( doc );
2005  node.appendChild( rendererElement );
2006 
2007  if ( mLabeling )
2008  {
2009  QDomElement labelingElement = mLabeling->save( doc );
2010  node.appendChild( labelingElement );
2011  }
2012 
2013  // use scale dependent visibility flag
2014  if ( mLabel )
2015  {
2016  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
2017  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
2018  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
2019  }
2020 
2021  // save the simplification drawing settings
2022  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
2023  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
2024  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2025  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
2026 
2027  //save customproperties (for labeling ng)
2028  writeCustomProperties( node, doc );
2029 
2030  // add the blend mode field
2031  QDomElement blendModeElem = doc.createElement( "blendMode" );
2033  blendModeElem.appendChild( blendModeText );
2034  node.appendChild( blendModeElem );
2035 
2036  // add the feature blend mode field
2037  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
2039  featureBlendModeElem.appendChild( featureBlendModeText );
2040  node.appendChild( featureBlendModeElem );
2041 
2042  // add the layer transparency
2043  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
2044  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
2045  layerTransparencyElem.appendChild( layerTransparencyText );
2046  node.appendChild( layerTransparencyElem );
2047 
2048  // add the display field
2049  QDomElement dField = doc.createElement( "displayfield" );
2050  QDomText dFieldText = doc.createTextNode( displayField() );
2051  dField.appendChild( dFieldText );
2052  node.appendChild( dField );
2053 
2054  // add label node
2055  QDomElement labelElem = doc.createElement( "label" );
2056  QDomText labelText = doc.createTextNode( "" );
2057 
2059  if ( hasLabelsEnabled() )
2060  {
2061  labelText.setData( "1" );
2062  }
2063  else
2064  {
2065  labelText.setData( "0" );
2066  }
2068  labelElem.appendChild( labelText );
2069 
2070  node.appendChild( labelElem );
2071 
2072  // Now we get to do all that all over again for QgsLabel
2073 
2074  if ( mLabel )
2075  {
2076  QString fieldname = mLabel->labelField( QgsLabel::Text );
2077  if ( fieldname != "" )
2078  {
2079  dField = doc.createElement( "labelfield" );
2080  dFieldText = doc.createTextNode( fieldname );
2081  dField.appendChild( dFieldText );
2082  node.appendChild( dField );
2083  }
2084 
2085  mLabel->writeXML( node, doc );
2086  }
2087 
2088  if ( mDiagramRenderer )
2089  {
2090  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
2091  if ( mDiagramLayerSettings )
2092  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
2093  }
2094  }
2095 
2096  // FIXME
2097  // edittypes are written to the layerNode
2098  // by slot QgsEditorWidgetRegistry::writeMapLayer()
2099  // triggered by signal QgsProject::writeMapLayer()
2100  // still other editing settings are written here,
2101  // although they are not part of symbology either
2102 
2103  QDomElement afField = doc.createElement( "annotationform" );
2104  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
2105  afField.appendChild( afText );
2106  node.appendChild( afField );
2107 
2108  //attribute aliases
2109  if ( !mAttributeAliasMap.isEmpty() )
2110  {
2111  QDomElement aliasElem = doc.createElement( "aliases" );
2112  QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
2113  for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
2114  {
2115  int idx = fieldNameIndex( a_it.key() );
2116  if ( idx < 0 )
2117  continue;
2118 
2119  QDomElement aliasEntryElem = doc.createElement( "alias" );
2120  aliasEntryElem.setAttribute( "field", a_it.key() );
2121  aliasEntryElem.setAttribute( "index", idx );
2122  aliasEntryElem.setAttribute( "name", a_it.value() );
2123  aliasElem.appendChild( aliasEntryElem );
2124  }
2125  node.appendChild( aliasElem );
2126  }
2127 
2128  //exclude attributes WMS
2129  QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
2130  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
2131  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
2132  {
2133  QDomElement attrElem = doc.createElement( "attribute" );
2134  QDomText attrText = doc.createTextNode( *attWMSIt );
2135  attrElem.appendChild( attrText );
2136  excludeWMSElem.appendChild( attrElem );
2137  }
2138  node.appendChild( excludeWMSElem );
2139 
2140  //exclude attributes WFS
2141  QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
2142  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
2143  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
2144  {
2145  QDomElement attrElem = doc.createElement( "attribute" );
2146  QDomText attrText = doc.createTextNode( *attWFSIt );
2147  attrElem.appendChild( attrText );
2148  excludeWFSElem.appendChild( attrElem );
2149  }
2150  node.appendChild( excludeWFSElem );
2151 
2152  // add attribute actions
2153  mActions->writeXML( node, doc );
2154 
2155  mEditFormConfig->writeXml( node );
2156 
2157  mConditionalStyles->writeXml( node, doc );
2158 
2159  return true;
2160 }
2161 
2162 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2163 {
2164  // get the Name element
2165  QDomElement nameElem = node.firstChildElement( "Name" );
2166  if ( nameElem.isNull() )
2167  {
2168  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
2169  }
2170 
2171  if ( hasGeometryType() )
2172  {
2173  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
2174  if ( !r )
2175  return false;
2176 
2177  setRendererV2( r );
2178 
2179  // labeling
2180  readSldLabeling( node );
2181  }
2182  return true;
2183 }
2184 
2185 
2186 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2187 {
2188  Q_UNUSED( errorMessage );
2189 
2190  // store the Name element
2191  QDomElement nameNode = doc.createElement( "se:Name" );
2192  nameNode.appendChild( doc.createTextNode( name() ) );
2193  node.appendChild( nameNode );
2194 
2195  if ( hasGeometryType() )
2196  {
2197  node.appendChild( mRendererV2->writeSld( doc, name() ) );
2198  }
2199  return true;
2200 }
2201 
2202 
2204 {
2205  if ( !mEditBuffer || !mDataProvider )
2206  {
2207  return false;
2208  }
2209 
2210  updateExtents();
2211 
2212  bool result = mEditBuffer->changeGeometry( fid, geom );
2213 
2214  if ( result )
2215  updateExtents();
2216  return result;
2217 }
2218 
2219 
2220 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant& value, bool emitSignal )
2221 {
2222  Q_UNUSED( emitSignal );
2223  return changeAttributeValue( fid, field, value );
2224 }
2225 
2226 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2227 {
2228  if ( !mEditBuffer || !mDataProvider )
2229  return false;
2230 
2231  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2232 }
2233 
2235 {
2236  if ( !mEditBuffer || !mDataProvider )
2237  return false;
2238 
2239  return mEditBuffer->addAttribute( field );
2240 }
2241 
2243 {
2244  if ( attIndex < 0 || attIndex >= fields().count() )
2245  return;
2246 
2247  QString name = fields().at( attIndex ).name();
2248  if ( mAttributeAliasMap.contains( name ) )
2249  {
2250  mAttributeAliasMap.remove( name );
2251  emit layerModified();
2252  }
2253 }
2254 
2255 void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString )
2256 {
2257  if ( attIndex < 0 || attIndex >= fields().count() )
2258  return;
2259 
2260  QString name = fields().at( attIndex ).name();
2261 
2262  mAttributeAliasMap.insert( name, aliasString );
2263  emit layerModified(); // TODO[MD]: should have a different signal?
2264 }
2265 
2266 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2267 {
2268  if ( attributeIndex < 0 || attributeIndex >= fields().count() )
2269  return "";
2270 
2271  QString name = fields().at( attributeIndex ).name();
2272 
2273  return mAttributeAliasMap.value( name, "" );
2274 }
2275 
2277 {
2278  QString displayName = attributeAlias( attributeIndex );
2279  if ( displayName.isEmpty() )
2280  {
2281  if ( attributeIndex >= 0 && attributeIndex < mUpdatedFields.count() )
2282  {
2283  displayName = mUpdatedFields.at( attributeIndex ).name();
2284  }
2285  }
2286  return displayName;
2287 }
2288 
2290 {
2291  if ( index < 0 || index >= fields().count() )
2292  return false;
2293 
2294  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2295  {
2296  removeExpressionField( index );
2297  return true;
2298  }
2299 
2300  if ( !mEditBuffer || !mDataProvider )
2301  return false;
2302 
2303  return mEditBuffer->deleteAttribute( index );
2304 }
2305 
2307 {
2308  bool deleted = false;
2309 
2310  // Remove multiple occurrences of same attribute
2311  attrs = attrs.toSet().toList();
2312 
2313  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2314 
2315  Q_FOREACH ( int attr, attrs )
2316  {
2317  if ( deleteAttribute( attr ) )
2318  {
2319  deleted = true;
2320  }
2321  }
2322 
2323  return deleted;
2324 }
2325 
2327 {
2328  if ( !mEditBuffer )
2329  return false;
2330 
2331  bool res = mEditBuffer->deleteFeature( fid );
2332  if ( res )
2333  {
2334  mSelectedFeatureIds.remove( fid ); // remove it from selection
2335  updateExtents();
2336  }
2337 
2338  return res;
2339 }
2340 
2342 {
2343  if ( !mEditBuffer )
2344  return false;
2345 
2346  bool res = mEditBuffer->deleteFeatures( fids );
2347 
2348  if ( res )
2349  {
2350  mSelectedFeatureIds.subtract( fids ); // remove it from selection
2351  updateExtents();
2352  }
2353 
2354  return res;
2355 }
2356 
2358 {
2359  QgsAttributeList pkAttributesList;
2360 
2361  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2362  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2363  {
2364  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2365  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2366  pkAttributesList << i;
2367  }
2368 
2369  return pkAttributesList;
2370 }
2371 
2373 {
2374  return mDataProvider->featureCount() +
2375  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2376 }
2377 
2379 {
2380  mCommitErrors.clear();
2381 
2382  if ( !mDataProvider )
2383  {
2384  mCommitErrors << tr( "ERROR: no provider" );
2385  return false;
2386  }
2387 
2388  if ( !mEditBuffer )
2389  {
2390  mCommitErrors << tr( "ERROR: layer not editable" );
2391  return false;
2392  }
2393 
2394  emit beforeCommitChanges();
2395 
2396  bool success = mEditBuffer->commitChanges( mCommitErrors );
2397 
2398  if ( success )
2399  {
2400  delete mEditBuffer;
2401  mEditBuffer = nullptr;
2402  undoStack()->clear();
2403  emit editingStopped();
2404  }
2405  else
2406  {
2407  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2408  }
2409 
2410  if ( mCache )
2411  {
2412  mCache->deleteCachedGeometries();
2413  }
2414 
2415  updateFields();
2416  mDataProvider->updateExtents();
2417 
2418  emit repaintRequested();
2419 
2420  return success;
2421 }
2422 
2424 {
2425  return mCommitErrors;
2426 }
2427 
2428 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2429 {
2430  if ( !mEditBuffer )
2431  {
2432  return false;
2433  }
2434 
2435  bool rollbackExtent = !mEditBuffer->mDeletedFeatureIds.isEmpty() ||
2436  !mEditBuffer->mAddedFeatures.isEmpty() ||
2437  !mEditBuffer->mChangedGeometries.isEmpty();
2438 
2439  emit beforeRollBack();
2440 
2441  mEditBuffer->rollBack();
2442 
2443  if ( isModified() )
2444  {
2445  // new undo stack roll back method
2446  // old method of calling every undo could cause many canvas refreshes
2447  undoStack()->setIndex( 0 );
2448  }
2449 
2450  updateFields();
2451 
2452  if ( deleteBuffer )
2453  {
2454  delete mEditBuffer;
2455  mEditBuffer = nullptr;
2456  undoStack()->clear();
2457  }
2458  emit editingStopped();
2459 
2460  if ( mCache )
2461  {
2462  mCache->deleteCachedGeometries();
2463  }
2464 
2465  if ( rollbackExtent )
2466  updateExtents();
2467 
2468  emit repaintRequested();
2469  return true;
2470 }
2471 
2473 {
2474  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - ids;
2475 
2476  mSelectedFeatureIds = ids;
2477 
2478  emit selectionChanged( ids, deselectedFeatures, true );
2479 }
2480 
2482 {
2483  return mSelectedFeatureIds.size();
2484 }
2485 
2487 {
2488  return mSelectedFeatureIds;
2489 }
2490 
2492 {
2493  QgsFeatureList features;
2494  QgsFeature f;
2495 
2496  if ( mSelectedFeatureIds.count() <= 8 )
2497  {
2498  // for small amount of selected features, fetch them directly
2499  // because request with FilterFids would go iterate over the whole layer
2500  Q_FOREACH ( QgsFeatureId fid, mSelectedFeatureIds )
2501  {
2502  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2503  features << f;
2504  }
2505  }
2506  else
2507  {
2509 
2510  while ( it.nextFeature( f ) )
2511  {
2512  features.push_back( f );
2513  }
2514  }
2515 
2516  return features;
2517 }
2518 
2520 {
2521  if ( mSelectedFeatureIds.isEmpty() )
2522  return QgsFeatureIterator();
2523 
2524  if ( geometryType() == QGis::NoGeometry )
2526 
2527  if ( mSelectedFeatureIds.count() == 1 )
2528  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2529  else
2530  request.setFilterFids( mSelectedFeatureIds );
2531 
2532  return getFeatures( request );
2533 }
2534 
2535 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2536 {
2537  if ( !mEditBuffer || !mDataProvider )
2538  return false;
2539 
2540  bool res = mEditBuffer->addFeatures( features );
2541 
2542  if ( makeSelected )
2543  {
2544  QgsFeatureIds ids;
2545 
2546  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2547  ids << iter->id();
2548 
2549  setSelectedFeatures( ids );
2550  }
2551 
2552  updateExtents();
2553 
2554  return res;
2555 }
2556 
2557 
2558 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2559 {
2560  if ( !hasGeometryType() )
2561  return false;
2562 
2564  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2565 
2566  if ( result != 0 )
2567  {
2568  return false;
2569  }
2570 
2571  if ( snapResults.size() < 1 )
2572  {
2573  return false;
2574  }
2575 
2577  point.setX( snap_it.value().snappedVertex.x() );
2578  point.setY( snap_it.value().snappedVertex.y() );
2579  return true;
2580 }
2581 
2582 
2583 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2584  QMultiMap<double, QgsSnappingResult>& snappingResults,
2585  QgsSnapper::SnappingType snap_to )
2586 {
2587  if ( !hasGeometryType() )
2588  return 1;
2589 
2590  if ( snappingTolerance <= 0 || !mDataProvider )
2591  {
2592  return 1;
2593  }
2594 
2595  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2596  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2597  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2598 
2599  int n = 0;
2600  QgsFeature f;
2601 
2602  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2603  {
2604  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2605  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2606  {
2607  QgsGeometry* g = &( it.value() );
2608  if ( g->boundingBox().intersects( searchRect ) )
2609  {
2610  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2611  ++n;
2612  }
2613  }
2614  }
2615  else
2616  {
2617  // snapping outside cached area
2618 
2620  .setFilterRect( searchRect )
2622  .setSubsetOfAttributes( QgsAttributeList() ) );
2623 
2624  while ( fit.nextFeature( f ) )
2625  {
2626  snapToGeometry( startPoint, f.id(), f.constGeometry(), sqrSnappingTolerance, snappingResults, snap_to );
2627  ++n;
2628  }
2629  }
2630 
2631  return n == 0 ? 2 : 0;
2632 }
2633 
2634 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2635  QgsFeatureId featureId,
2636  const QgsGeometry* geom,
2637  double sqrSnappingTolerance,
2638  QMultiMap<double, QgsSnappingResult>& snappingResults,
2639  QgsSnapper::SnappingType snap_to ) const
2640 {
2641  if ( !geom )
2642  {
2643  return;
2644  }
2645 
2646  int atVertex, beforeVertex, afterVertex;
2647  double sqrDistVertexSnap, sqrDistSegmentSnap;
2648  QgsPoint snappedPoint;
2649  QgsSnappingResult snappingResultVertex;
2650  QgsSnappingResult snappingResultSegment;
2651 
2652  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2653  {
2654  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2655  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2656  {
2657  snappingResultVertex.snappedVertex = snappedPoint;
2658  snappingResultVertex.snappedVertexNr = atVertex;
2659  snappingResultVertex.beforeVertexNr = beforeVertex;
2660  if ( beforeVertex != -1 ) // make sure the vertex is valid
2661  {
2662  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2663  }
2664  snappingResultVertex.afterVertexNr = afterVertex;
2665  if ( afterVertex != -1 ) // make sure the vertex is valid
2666  {
2667  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2668  }
2669  snappingResultVertex.snappedAtGeometry = featureId;
2670  snappingResultVertex.layer = this;
2671  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2672  return;
2673  }
2674  }
2675  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2676  {
2677  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2678  {
2679  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, nullptr, crs().geographicFlag() ? 1e-12 : 1e-8 );
2680 
2681  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2682  {
2683  snappingResultSegment.snappedVertex = snappedPoint;
2684  snappingResultSegment.snappedVertexNr = -1;
2685  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2686  snappingResultSegment.afterVertexNr = afterVertex;
2687  snappingResultSegment.snappedAtGeometry = featureId;
2688  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2689  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2690  snappingResultSegment.layer = this;
2691  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2692  }
2693  }
2694  }
2695 }
2696 
2698 {
2699  QgsVectorLayerEditUtils utils( this );
2700  return utils.insertSegmentVerticesForSnap( snapResults );
2701 }
2702 
2703 
2705 {
2706  QgsDebugMsg( "----- Computing Coordinate System" );
2707 
2708  //
2709  // Get the layers project info and set up the QgsCoordinateTransform
2710  // for this layer
2711  //
2712 
2713  if ( hasGeometryType() )
2714  {
2715  // get CRS directly from provider
2716  setCrs( mDataProvider->crs() );
2717  }
2718  else
2719  {
2721  }
2722 }
2723 
2724 
2726 {
2727  return mDisplayField;
2728 }
2729 
2731 {
2732  mDisplayExpression = displayExpression;
2733 }
2734 
2736 {
2737  return mDisplayExpression;
2738 }
2739 
2741 {
2742  return ( mEditBuffer && mDataProvider );
2743 }
2744 
2746 {
2747  return geometryType() != QGis::NoGeometry;
2748 }
2749 
2751 {
2752  return mReadOnly;
2753 }
2754 
2755 bool QgsVectorLayer::setReadOnly( bool readonly )
2756 {
2757  // exit if the layer is in editing mode
2758  if ( readonly && mEditBuffer )
2759  return false;
2760 
2761  mReadOnly = readonly;
2762  return true;
2763 }
2764 
2766 {
2767  emit beforeModifiedCheck();
2768  return mEditBuffer && mEditBuffer->isModified();
2769 }
2770 
2772 {
2773  if ( idx < 0 || idx >= mUpdatedFields.count() )
2774  return Hidden;
2775 
2777  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
2779 }
2780 
2782 {
2783  if ( idx < 0 || idx >= mUpdatedFields.count() )
2784  return;
2785 
2787 
2789  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
2790 
2791  setEditorWidgetV2( idx, widgetType );
2792  setEditorWidgetV2Config( idx, cfg );
2794 }
2795 
2797 {
2798  mAnnotationForm = ui;
2799 }
2800 
2802 {
2804  return editorWidgetV2Config( idx );
2806 }
2807 
2809 {
2811  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2812  return RangeData(
2813  cfg.value( "Min" ),
2814  cfg.value( "Max" ),
2815  cfg.value( "Step" )
2816  );
2818 }
2819 
2821 {
2823  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
2825 }
2826 
2828 {
2830  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2831  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
2833 }
2834 
2836 {
2837  if ( !hasGeometryType() )
2838  return;
2839 
2840  if ( r != mRendererV2 )
2841  {
2842  delete mRendererV2;
2843  mRendererV2 = r;
2844  mSymbolFeatureCounted = false;
2845  mSymbolFeatureCountMap.clear();
2846 
2847  emit rendererChanged();
2848  }
2849 }
2850 
2852 {
2853  if ( !mDataProvider )
2854  {
2855  return;
2856  }
2857  if ( !mDataProvider->transaction() )
2858  {
2859  undoStack()->beginMacro( text );
2860  mEditCommandActive = true;
2861  emit editCommandStarted( text );
2862  }
2863 }
2864 
2866 {
2867  if ( !mDataProvider )
2868  {
2869  return;
2870  }
2871  if ( !mDataProvider->transaction() )
2872  {
2873  undoStack()->endMacro();
2874  mEditCommandActive = false;
2875  if ( !mDeletedFids.isEmpty() )
2876  {
2877  emit featuresDeleted( mDeletedFids );
2878  mDeletedFids.clear();
2879  }
2880  emit editCommandEnded();
2881  }
2882 }
2883 
2885 {
2886  if ( !mDataProvider )
2887  {
2888  return;
2889  }
2890  if ( !mDataProvider->transaction() )
2891  {
2892  undoStack()->endMacro();
2893  undoStack()->undo();
2894  mEditCommandActive = false;
2895  mDeletedFids.clear();
2896  emit editCommandDestroyed();
2897  }
2898 }
2899 
2900 
2901 void QgsVectorLayer::setCheckedState( int idx, const QString& checked, const QString& unchecked )
2902 {
2905  cfg["CheckedState"] = checked;
2906  cfg["UncheckedState"] = unchecked;
2907  setEditorWidgetV2Config( idx, cfg );
2909 }
2910 
2911 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
2912 {
2913  return fields().fieldNameIndex( fieldName );
2914 }
2915 
2917 {
2918  return mJoinBuffer && mJoinBuffer->addJoin( joinInfo );
2919 }
2920 
2922 {
2923  removeJoin( theLayerId );
2924 }
2925 
2926 bool QgsVectorLayer::removeJoin( const QString& joinLayerId )
2927 {
2928  bool res = false;
2929  if ( mJoinBuffer )
2930  {
2931  res = mJoinBuffer->removeJoin( joinLayerId );
2932  }
2933  return res;
2934 }
2935 
2937 {
2938  if ( mJoinBuffer )
2939  return mJoinBuffer->vectorJoins();
2940  else
2941  return QList< QgsVectorJoinInfo >();
2942 }
2943 
2945 {
2946  emit beforeAddingExpressionField( fld.name() );
2947  mExpressionFieldBuffer->addExpression( exp, fld );
2948  updateFields();
2949  int idx = mUpdatedFields.indexFromName( fld.name() );
2950  emit attributeAdded( idx );
2951  return idx;
2952 }
2953 
2955 {
2956  emit beforeRemovingExpressionField( index );
2957  int oi = mUpdatedFields.fieldOriginIndex( index );
2958  mExpressionFieldBuffer->removeExpression( oi );
2959  updateFields();
2960  emit attributeDeleted( index );
2961 }
2962 
2964 {
2965  int oi = mUpdatedFields.fieldOriginIndex( index );
2966  return mExpressionFieldBuffer->expressions().value( oi ).expression;
2967 }
2968 
2970 {
2971  int oi = mUpdatedFields.fieldOriginIndex( index );
2972  mExpressionFieldBuffer->updateExpression( oi, exp );
2973 }
2974 
2976 {
2977  if ( !mDataProvider )
2978  return;
2979 
2980  QgsFields oldFields = mUpdatedFields;
2981 
2982  mUpdatedFields = mDataProvider->fields();
2983 
2984  // added / removed fields
2985  if ( mEditBuffer )
2986  mEditBuffer->updateFields( mUpdatedFields );
2987 
2988  // joined fields
2989  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
2990  mJoinBuffer->updateFields( mUpdatedFields );
2991 
2992  if ( mExpressionFieldBuffer )
2993  mExpressionFieldBuffer->updateFields( mUpdatedFields );
2994 
2995  if ( oldFields != mUpdatedFields )
2996  {
2997  emit updatedFields();
2998  mEditFormConfig->setFields( mUpdatedFields );
2999  }
3000 }
3001 
3002 
3004 {
3005  if ( mJoinBuffer->containsJoins() )
3006  {
3007  mJoinBuffer->createJoinCaches();
3008  }
3009 }
3010 
3012 {
3013  uniqueValues.clear();
3014  if ( !mDataProvider )
3015  {
3016  return;
3017  }
3018 
3019  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3020  if ( origin == QgsFields::OriginUnknown )
3021  {
3022  return;
3023  }
3024 
3025  if ( origin == QgsFields::OriginProvider ) //a provider field
3026  {
3027  mDataProvider->uniqueValues( index, uniqueValues, limit );
3028 
3029  if ( mEditBuffer )
3030  {
3031  QSet<QString> vals;
3032  Q_FOREACH ( const QVariant& v, uniqueValues )
3033  {
3034  vals << v.toString();
3035  }
3036 
3037  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
3038  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
3039  {
3040  it.next();
3041  QVariant v = it.value().value( index );
3042  if ( v.isValid() )
3043  {
3044  QString vs = v.toString();
3045  if ( !vals.contains( vs ) )
3046  {
3047  vals << vs;
3048  uniqueValues << v;
3049  }
3050  }
3051  }
3052  }
3053 
3054  return;
3055  }
3056  else if ( origin == QgsFields::OriginJoin )
3057  {
3058  int sourceLayerIndex;
3059  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
3060  Q_ASSERT( join );
3061 
3063 
3064  if ( vl )
3065  vl->dataProvider()->uniqueValues( sourceLayerIndex, uniqueValues, limit );
3066 
3067  return;
3068  }
3069  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
3070  {
3071  // the layer is editable, but in certain cases it can still be avoided going through all features
3072  if ( origin == QgsFields::OriginEdit && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mAddedFeatures.isEmpty() && !mEditBuffer->mDeletedAttributeIds.contains( index ) && mEditBuffer->mChangedAttributeValues.isEmpty() )
3073  {
3074  mDataProvider->uniqueValues( index, uniqueValues, limit );
3075  return;
3076  }
3077 
3078  // we need to go through each feature
3079  QgsAttributeList attList;
3080  attList << index;
3081 
3083  .setFlags( QgsFeatureRequest::NoGeometry )
3084  .setSubsetOfAttributes( attList ) );
3085 
3086  QgsFeature f;
3087  QVariant currentValue;
3089  while ( fit.nextFeature( f ) )
3090  {
3091  currentValue = f.attribute( index );
3092  val.insert( currentValue.toString(), currentValue );
3093  if ( limit >= 0 && val.size() >= limit )
3094  {
3095  break;
3096  }
3097  }
3098 
3099  uniqueValues = val.values();
3100  return;
3101  }
3102 
3103  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3104 }
3105 
3107 {
3108  if ( !mDataProvider )
3109  {
3110  return QVariant();
3111  }
3112 
3113  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3114  if ( origin == QgsFields::OriginUnknown )
3115  {
3116  return QVariant();
3117  }
3118 
3119  if ( origin == QgsFields::OriginProvider ) //a provider field
3120  {
3121  return mDataProvider->minimumValue( index );
3122  }
3123  else if ( origin == QgsFields::OriginJoin )
3124  {
3125  int sourceLayerIndex;
3126  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
3127  Q_ASSERT( join );
3128 
3130  Q_ASSERT( vl );
3131 
3132  return vl->minimumValue( sourceLayerIndex );
3133  }
3134  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
3135  {
3136  // the layer is editable, but in certain cases it can still be avoided going through all features
3137  if ( origin == QgsFields::OriginEdit &&
3138  mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3139  mEditBuffer->mAddedFeatures.isEmpty() && !
3140  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3141  mEditBuffer->mChangedAttributeValues.isEmpty() )
3142  {
3143  return mDataProvider->minimumValue( index );
3144  }
3145 
3146  // we need to go through each feature
3147  QgsAttributeList attList;
3148  attList << index;
3149 
3151  .setFlags( QgsFeatureRequest::NoGeometry )
3152  .setSubsetOfAttributes( attList ) );
3153 
3154  QgsFeature f;
3156  double currentValue = 0;
3157  while ( fit.nextFeature( f ) )
3158  {
3159  currentValue = f.attribute( index ).toDouble();
3160  if ( currentValue < minimumValue )
3161  {
3162  minimumValue = currentValue;
3163  }
3164  }
3165  return QVariant( minimumValue );
3166  }
3167 
3168  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3169  return QVariant();
3170 }
3171 
3173 {
3174  if ( !mDataProvider )
3175  {
3176  return QVariant();
3177  }
3178 
3179  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3180  if ( origin == QgsFields::OriginUnknown )
3181  {
3182  return QVariant();
3183  }
3184 
3185  if ( origin == QgsFields::OriginProvider ) //a provider field
3186  {
3187  return mDataProvider->maximumValue( index );
3188  }
3189  else if ( origin == QgsFields::OriginJoin )
3190  {
3191  int sourceLayerIndex;
3192  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
3193  Q_ASSERT( join );
3194 
3196  Q_ASSERT( vl );
3197 
3198  return vl->maximumValue( sourceLayerIndex );
3199  }
3200  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
3201  {
3202  // the layer is editable, but in certain cases it can still be avoided going through all features
3203  if ( origin == QgsFields::OriginEdit &&
3204  mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3205  mEditBuffer->mAddedFeatures.isEmpty() &&
3206  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3207  mEditBuffer->mChangedAttributeValues.isEmpty() )
3208  {
3209  return mDataProvider->maximumValue( index );
3210  }
3211 
3212  // we need to go through each feature
3213  QgsAttributeList attList;
3214  attList << index;
3215 
3217  .setFlags( QgsFeatureRequest::NoGeometry )
3218  .setSubsetOfAttributes( attList ) );
3219 
3220  QgsFeature f;
3222  double currentValue = 0;
3223  while ( fit.nextFeature( f ) )
3224  {
3225  currentValue = f.attribute( index ).toDouble();
3226  if ( currentValue > maximumValue )
3227  {
3228  maximumValue = currentValue;
3229  }
3230  }
3231  return QVariant( maximumValue );
3232  }
3233 
3234  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3235  return QVariant();
3236 }
3237 
3238 QList<QVariant> QgsVectorLayer::getValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly )
3239 {
3240  QList<QVariant> values;
3241 
3242  QScopedPointer<QgsExpression> expression;
3243  QgsExpressionContext context;
3244 
3245  int attrNum = fieldNameIndex( fieldOrExpression );
3246 
3247  if ( attrNum == -1 )
3248  {
3249  // try to use expression
3250  expression.reset( new QgsExpression( fieldOrExpression ) );
3254 
3255  if ( expression->hasParserError() || !expression->prepare( &context ) )
3256  {
3257  ok = false;
3258  return values;
3259  }
3260  }
3261 
3262  QgsFeature f;
3263  QStringList lst;
3264  if ( expression.isNull() )
3265  lst.append( fieldOrExpression );
3266  else
3267  lst = expression->referencedColumns();
3268 
3270  .setFlags(( expression && expression->needsGeometry() ) ?
3273  .setSubsetOfAttributes( lst, fields() );
3274 
3275  QgsFeatureIterator fit;
3276  if ( !selectedOnly )
3277  {
3278  fit = getFeatures( request );
3279  }
3280  else
3281  {
3282  fit = selectedFeaturesIterator( request );
3283  }
3284 
3285  // create list of non-null attribute values
3286  while ( fit.nextFeature( f ) )
3287  {
3288  if ( expression )
3289  {
3290  context.setFeature( f );
3291  QVariant v = expression->evaluate( &context );
3292  values << v;
3293  }
3294  else
3295  {
3296  values << f.attribute( attrNum );
3297  }
3298  }
3299  ok = true;
3300  return values;
3301 }
3302 
3303 QList<double> QgsVectorLayer::getDoubleValues( const QString &fieldOrExpression, bool& ok, bool selectedOnly, int* nullCount )
3304 {
3305  QList<double> values;
3306 
3307  if ( nullCount )
3308  *nullCount = 0;
3309 
3310  QList<QVariant> variantValues = getValues( fieldOrExpression, ok, selectedOnly );
3311  if ( !ok )
3312  return values;
3313 
3314  bool convertOk;
3315  Q_FOREACH ( const QVariant& value, variantValues )
3316  {
3317  double val = value.toDouble( &convertOk );
3318  if ( convertOk )
3319  values << val;
3320  else if ( value.isNull() )
3321  {
3322  if ( nullCount )
3323  *nullCount += 1;
3324  }
3325  }
3326  ok = true;
3327  return values;
3328 }
3329 
3330 
3333 {
3334  mFeatureBlendMode = featureBlendMode;
3335  emit featureBlendModeChanged( featureBlendMode );
3336 }
3337 
3339 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3340 {
3341  return mFeatureBlendMode;
3342 }
3343 
3346 {
3347  mLayerTransparency = layerTransparency;
3348  emit layerTransparencyChanged( layerTransparency );
3349 }
3350 
3353 {
3354  return mLayerTransparency;
3355 }
3356 
3357 
3358 
3359 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3360 {
3361  QDomElement element = node.toElement();
3362  if ( element.isNull() )
3363  return;
3364 
3365  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3366  if ( userStyleElem.isNull() )
3367  {
3368  QgsDebugMsg( "Info: UserStyle element not found." );
3369  return;
3370  }
3371 
3372  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3373  if ( featureTypeStyleElem.isNull() )
3374  {
3375  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3376  return;
3377  }
3378 
3379  // use last rule
3380  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3381  if ( ruleElem.isNull() )
3382  {
3383  QgsDebugMsg( "Info: Rule element not found." );
3384  return;
3385  }
3386 
3387  // use last text symbolizer
3388  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3389  if ( textSymbolizerElem.isNull() )
3390  {
3391  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3392  return;
3393  }
3394 
3395  // Label
3396  setCustomProperty( "labeling/enabled", false );
3397  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3398  if ( !labelElem.isNull() )
3399  {
3400  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3401  if ( !propertyNameElem.isNull() )
3402  {
3403  // enable labeling
3404  setCustomProperty( "labeling", "pal" );
3405  setCustomProperty( "labeling/enabled", true );
3406 
3407  // set labeling defaults
3408  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3409  setCustomProperty( "labeling/fontItalic", false );
3410  setCustomProperty( "labeling/fontSize", 10 );
3411  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3412  setCustomProperty( "labeling/fontBold", false );
3413  setCustomProperty( "labeling/fontUnderline", false );
3414  setCustomProperty( "labeling/textColorR", 0 );
3415  setCustomProperty( "labeling/textColorG", 0 );
3416  setCustomProperty( "labeling/textColorB", 0 );
3417  setCustomProperty( "labeling/textTransp", 0 );
3418  setCustomProperty( "labeling/bufferDraw", false );
3419  setCustomProperty( "labeling/bufferSize", 1 );
3420  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3421  setCustomProperty( "labeling/bufferColorR", 255 );
3422  setCustomProperty( "labeling/bufferColorG", 255 );
3423  setCustomProperty( "labeling/bufferColorB", 255 );
3424  setCustomProperty( "labeling/bufferTransp", 0 );
3425  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3426  setCustomProperty( "labeling/xOffset", 0 );
3427  setCustomProperty( "labeling/yOffset", 0 );
3428  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3429  setCustomProperty( "labeling/angleOffset", 0 );
3430 
3431  // label attribute
3432  QString labelAttribute = propertyNameElem.text();
3433  setCustomProperty( "labeling/fieldName", labelAttribute );
3434  setCustomProperty( "labeling/isExpression", false );
3435 
3436  int fieldIndex = fieldNameIndex( labelAttribute );
3437  if ( fieldIndex == -1 )
3438  {
3439  // label attribute is not in columns, check if it is an expression
3440  QgsExpression exp( labelAttribute );
3441  if ( !exp.hasEvalError() )
3442  {
3443  setCustomProperty( "labeling/isExpression", true );
3444  }
3445  else
3446  {
3447  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3448  }
3449  }
3450  }
3451  else
3452  {
3453  QgsDebugMsg( "Info: PropertyName element not found." );
3454  return;
3455  }
3456  }
3457  else
3458  {
3459  QgsDebugMsg( "Info: Label element not found." );
3460  return;
3461  }
3462 
3463  // Font
3464  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3465  if ( !fontElem.isNull() )
3466  {
3467  QString cssName;
3468  QString elemText;
3469  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3470  while ( !cssElem.isNull() )
3471  {
3472  cssName = cssElem.attribute( "name", "not_found" );
3473  if ( cssName != "not_found" )
3474  {
3475  elemText = cssElem.text();
3476  if ( cssName == "font-family" )
3477  {
3478  setCustomProperty( "labeling/fontFamily", elemText );
3479  }
3480  else if ( cssName == "font-style" )
3481  {
3482  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3483  }
3484  else if ( cssName == "font-size" )
3485  {
3486  bool ok;
3487  int fontSize = elemText.toInt( &ok );
3488  if ( ok )
3489  {
3490  setCustomProperty( "labeling/fontSize", fontSize );
3491  }
3492  }
3493  else if ( cssName == "font-weight" )
3494  {
3495  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3496  }
3497  else if ( cssName == "font-underline" )
3498  {
3499  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3500  }
3501  }
3502 
3503  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3504  }
3505  }
3506 
3507  // Fill
3508  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3509  if ( textColor.isValid() )
3510  {
3511  setCustomProperty( "labeling/textColorR", textColor.red() );
3512  setCustomProperty( "labeling/textColorG", textColor.green() );
3513  setCustomProperty( "labeling/textColorB", textColor.blue() );
3514  setCustomProperty( "labeling/textTransp", 100 - static_cast< int >( 100 * textColor.alphaF() ) );
3515  }
3516 
3517  // Halo
3518  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3519  if ( !haloElem.isNull() )
3520  {
3521  setCustomProperty( "labeling/bufferDraw", true );
3522  setCustomProperty( "labeling/bufferSize", 1 );
3523 
3524  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3525  if ( !radiusElem.isNull() )
3526  {
3527  bool ok;
3528  double bufferSize = radiusElem.text().toDouble( &ok );
3529  if ( ok )
3530  {
3531  setCustomProperty( "labeling/bufferSize", bufferSize );
3532  }
3533  }
3534 
3535  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3536  if ( bufferColor.isValid() )
3537  {
3538  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3539  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3540  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3541  setCustomProperty( "labeling/bufferTransp", 100 - static_cast< int >( 100 * bufferColor.alphaF() ) );
3542  }
3543  }
3544 
3545  // LabelPlacement
3546  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3547  if ( !labelPlacementElem.isNull() )
3548  {
3549  // PointPlacement
3550  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3551  if ( !pointPlacementElem.isNull() )
3552  {
3553  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3554 
3555  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3556  if ( !displacementElem.isNull() )
3557  {
3558  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3559  if ( !displacementXElem.isNull() )
3560  {
3561  bool ok;
3562  double xOffset = displacementXElem.text().toDouble( &ok );
3563  if ( ok )
3564  {
3565  setCustomProperty( "labeling/xOffset", xOffset );
3566  }
3567  }
3568  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3569  if ( !displacementYElem.isNull() )
3570  {
3571  bool ok;
3572  double yOffset = displacementYElem.text().toDouble( &ok );
3573  if ( ok )
3574  {
3575  setCustomProperty( "labeling/yOffset", yOffset );
3576  }
3577  }
3578  }
3579 
3580  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
3581  if ( !rotationElem.isNull() )
3582  {
3583  bool ok;
3584  double rotation = rotationElem.text().toDouble( &ok );
3585  if ( ok )
3586  {
3587  setCustomProperty( "labeling/angleOffset", rotation );
3588  }
3589  }
3590  }
3591  }
3592 }
3593 
3595 {
3596  if ( !mDiagramLayerSettings )
3597  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3598  *mDiagramLayerSettings = s;
3599 }
3600 
3602 {
3603  QString myMetadata = "<html><body>";
3604 
3605  //-------------
3606 
3607  myMetadata += "<p class=\"subheaderglossy\">";
3608  myMetadata += tr( "General" );
3609  myMetadata += "</p>\n";
3610 
3611  // data comment
3612  if ( !( dataComment().isEmpty() ) )
3613  {
3614  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
3615  myMetadata += "<p>";
3616  myMetadata += dataComment();
3617  myMetadata += "</p>\n";
3618  }
3619 
3620  //storage type
3621  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
3622  myMetadata += "<p>";
3623  myMetadata += storageType();
3624  myMetadata += "</p>\n";
3625 
3626  if ( dataProvider() )
3627  {
3628  //provider description
3629  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
3630  myMetadata += "<p>";
3631  myMetadata += dataProvider()->description().replace( '\n', "<br>" );
3632  myMetadata += "</p>\n";
3633  }
3634 
3635  // data source
3636  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
3637  myMetadata += "<p>";
3638  myMetadata += publicSource();
3639  myMetadata += "</p>\n";
3640 
3641  //geom type
3642 
3644 
3645  if ( type < 0 || type > QGis::NoGeometry )
3646  {
3647  QgsDebugMsg( "Invalid vector type" );
3648  }
3649  else
3650  {
3651  QString typeString( QGis::vectorGeometryType( geometryType() ) );
3652 
3653  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
3654  myMetadata += "<p>";
3655  myMetadata += typeString;
3656  myMetadata += "</p>\n";
3657  }
3658 
3659  QgsAttributeList pkAttrList = pkAttributeList();
3660  if ( !pkAttrList.isEmpty() )
3661  {
3662  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
3663  myMetadata += "<p>";
3664  Q_FOREACH ( int idx, pkAttrList )
3665  {
3666  myMetadata += fields().at( idx ).name() + ' ';
3667  }
3668  myMetadata += "</p>\n";
3669  }
3670 
3671 
3672  //feature count
3673  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
3674  myMetadata += "<p>";
3675  myMetadata += QString::number( featureCount() );
3676  myMetadata += "</p>\n";
3677  //capabilities
3678  myMetadata += "<p class=\"glossy\">" + tr( "Capabilities of this layer" ) + "</p>\n";
3679  myMetadata += "<p>";
3680  myMetadata += capabilitiesString();
3681  myMetadata += "</p>\n";
3682 
3683  //-------------
3684 
3685  QgsRectangle myExtent = extent();
3686  myMetadata += "<p class=\"subheaderglossy\">";
3687  myMetadata += tr( "Extents" );
3688  myMetadata += "</p>\n";
3689 
3690  //extents in layer cs TODO...maybe make a little nested table to improve layout...
3691  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
3692  myMetadata += "<p>";
3693  // Try to be a bit clever over what number format we use for the
3694  // extents. Some people don't like it using scientific notation when the
3695  // numbers get large, but for small numbers this is the more practical
3696  // option (so we can't force the format to 'f' for all values).
3697  // The scheme:
3698  // - for all numbers with more than 5 digits, force non-scientific notation
3699  // and 2 digits after the decimal point.
3700  // - for all smaller numbers let the OS decide which format to use (it will
3701  // generally use non-scientific unless the number gets much less than 1).
3702 
3703  if ( !myExtent.isEmpty() )
3704  {
3705  QString xMin, yMin, xMax, yMax;
3706  double changeoverValue = 99999; // The 'largest' 5 digit number
3707  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
3708  {
3709  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
3710  }
3711  else
3712  {
3713  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
3714  }
3715  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
3716  {
3717  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
3718  }
3719  else
3720  {
3721  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
3722  }
3723  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
3724  {
3725  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
3726  }
3727  else
3728  {
3729  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
3730  }
3731  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
3732  {
3733  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
3734  }
3735  else
3736  {
3737  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
3738  }
3739 
3740  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3741  .arg( xMin, yMin, xMax, yMax );
3742  }
3743  else
3744  {
3745  myMetadata += tr( "unknown extent" );
3746  }
3747 
3748  myMetadata += "</p>\n";
3749 
3750  //extents in project cs
3751 
3752  try
3753  {
3754 #if 0
3755  // TODO: currently disabled, will revisit later [MD]
3756  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
3757  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3758  myMetadata += "<p>";
3759  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3760  .arg( myProjectedExtent.xMinimum() )
3761  .arg( myProjectedExtent.yMinimum() )
3762  .arg( myProjectedExtent.xMaximum() )
3763  .arg( myProjectedExtent.yMaximum() );
3764  myMetadata += "</p>\n";
3765 #endif
3766 
3767  //
3768  // Display layer spatial ref system
3769  //
3770  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
3771  myMetadata += "<p>";
3772  myMetadata += crs().toProj4().replace( '"', " \"" );
3773  myMetadata += "</p>\n";
3774 
3775  //
3776  // Display project (output) spatial ref system
3777  //
3778 #if 0
3779  // TODO: disabled for now, will revisit later [MD]
3780  //myMetadata += "<tr><td bgcolor=\"gray\">";
3781  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
3782  myMetadata += "<p>";
3783  myMetadata += coordinateTransform->destCRS().toProj4().replace( '"', " \"" );
3784  myMetadata += "</p>\n";
3785 #endif
3786  }
3787  catch ( QgsCsException &cse )
3788  {
3789  Q_UNUSED( cse );
3790  QgsDebugMsg( cse.what() );
3791 
3792  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3793  myMetadata += "<p>";
3794  myMetadata += tr( "(Invalid transformation of layer extents)" );
3795  myMetadata += "</p>\n";
3796 
3797  }
3798 
3799 #if 0
3800  //
3801  // Add the info about each field in the attribute table
3802  //
3803  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
3804  myMetadata += "<p>";
3805 
3806  // Start a nested table in this trow
3807  myMetadata += "<table width=\"100%\">";
3808  myMetadata += "<tr><th>";
3809  myMetadata += tr( "Field" );
3810  myMetadata += "</th>";
3811  myMetadata += "<th>";
3812  myMetadata += tr( "Type" );
3813  myMetadata += "</th>";
3814  myMetadata += "<th>";
3815  myMetadata += tr( "Length" );
3816  myMetadata += "</th>";
3817  myMetadata += "<th>";
3818  myMetadata += tr( "Precision" );
3819  myMetadata += "</th>";
3820  myMetadata += "<th>";
3821  myMetadata += tr( "Comment" );
3822  myMetadata += "</th>";
3823 
3824  //get info for each field by looping through them
3825  const QgsFields& myFields = pendingFields();
3826  for ( int i = 0, n = myFields.size(); i < n; ++i )
3827  {
3828  const QgsField& myField = fields[i];
3829 
3830  myMetadata += "<tr><td>";
3831  myMetadata += myField.name();
3832  myMetadata += "</td>";
3833  myMetadata += "<td>";
3834  myMetadata += myField.typeName();
3835  myMetadata += "</td>";
3836  myMetadata += "<td>";
3837  myMetadata += QString( "%1" ).arg( myField.length() );
3838  myMetadata += "</td>";
3839  myMetadata += "<td>";
3840  myMetadata += QString( "%1" ).arg( myField.precision() );
3841  myMetadata += "</td>";
3842  myMetadata += "<td>";
3843  myMetadata += QString( "%1" ).arg( myField.comment() );
3844  myMetadata += "</td></tr>";
3845  }
3846 
3847  //close field list
3848  myMetadata += "</table>"; //end of nested table
3849 #endif
3850 
3851  myMetadata += "</body></html>";
3852  return myMetadata;
3853 }
3854 
3856 {
3857  mSymbolFeatureCounted = false;
3858 }
3859 
3860 void QgsVectorLayer::onJoinedFieldsChanged()
3861 {
3862  // some of the fields of joined layers have changed -> we need to update this layer's fields too
3863  updateFields();
3864 }
3865 
3866 void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
3867 {
3868  if ( mEditCommandActive )
3869  mDeletedFids << fid;
3870  else
3871  emit featuresDeleted( QgsFeatureIds() << fid );
3872 
3873  emit featureDeleted( fid );
3874 }
3875 
3877 {
3878  if ( mEditFormConfig->widgetType( idx ) == "ValueRelation" )
3879  {
3880  QgsEditorWidgetConfig cfg = mEditFormConfig->widgetConfig( idx );
3881 
3882  return ValueRelationData( cfg.value( "Layer" ).toString(),
3883  cfg.value( "Key" ).toString(),
3884  cfg.value( "Value" ).toString(),
3885  cfg.value( "AllowNull" ).toBool(),
3886  cfg.value( "OrderByValue" ).toBool(),
3887  cfg.value( "AllowMulti" ).toBool(),
3888  cfg.value( "FilterExpression" ).toString()
3889  );
3890  }
3891  else
3892  {
3893  return ValueRelationData();
3894  }
3895 }
3896 
3898 {
3899  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
3900 }
3901 
3903 {
3904  QDomElement elem = doc.createElement( "attributeEditorContainer" );
3905  elem.setAttribute( "name", mName );
3906  elem.setAttribute( "columnCount", mColumnCount );
3907 
3908  Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
3909  {
3910  elem.appendChild( child->toDomElement( doc ) );
3911  }
3912  return elem;
3913 }
3914 
3916 {
3917  mChildren.append( widget );
3918 }
3919 
3921 {
3922  mName = name;
3923 }
3924 
3926 {
3928 
3929  Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
3930  {
3931  if ( elem->type() == type )
3932  {
3933  results.append( elem );
3934  }
3935 
3936  if ( elem->type() == AeTypeContainer )
3937  {
3938  QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
3939  if ( cont )
3940  results += cont->findElements( type );
3941  }
3942  }
3943 
3944  return results;
3945 }
3946 
3948 {
3949  QDomElement elem = doc.createElement( "attributeEditorField" );
3950  elem.setAttribute( "name", mName );
3951  elem.setAttribute( "index", mIdx );
3952  return elem;
3953 }
3954 
3956 {
3958  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3959  if ( !myLib )
3960  {
3961  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3962  return -1;
3963  }
3964  listStyles_t* listStylesExternalMethod = reinterpret_cast< listStyles_t * >( cast_to_fptr( myLib->resolve( "listStyles" ) ) );
3965 
3966  if ( !listStylesExternalMethod )
3967  {
3968  delete myLib;
3969  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "listStyles" );
3970  return -1;
3971  }
3972 
3973  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
3974 }
3975 
3977 {
3979  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3980  if ( !myLib )
3981  {
3982  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3983  return QObject::tr( "" );
3984  }
3985  getStyleById_t* getStyleByIdMethod = reinterpret_cast< getStyleById_t * >( cast_to_fptr( myLib->resolve( "getStyleById" ) ) );
3986 
3987  if ( !getStyleByIdMethod )
3988  {
3989  delete myLib;
3990  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "getStyleById" );
3991  return QObject::tr( "" );
3992  }
3993 
3994  return getStyleByIdMethod( mDataSource, styleId, msgError );
3995 }
3996 
3997 
3998 void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& description,
3999  bool useAsDefault, const QString& uiFileContent, QString &msgError )
4000 {
4001 
4002  QString sldStyle, qmlStyle;
4004  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4005  if ( !myLib )
4006  {
4007  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4008  return;
4009  }
4010  saveStyle_t* saveStyleExternalMethod = reinterpret_cast< saveStyle_t * >( cast_to_fptr( myLib->resolve( "saveStyle" ) ) );
4011 
4012  if ( !saveStyleExternalMethod )
4013  {
4014  delete myLib;
4015  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, "saveStyle" );
4016  return;
4017  }
4018 
4019  QDomDocument qmlDocument, sldDocument;
4020  this->exportNamedStyle( qmlDocument, msgError );
4021  if ( !msgError.isNull() )
4022  {
4023  return;
4024  }
4025  qmlStyle = qmlDocument.toString();
4026 
4027  this->exportSldStyle( sldDocument, msgError );
4028  if ( !msgError.isNull() )
4029  {
4030  return;
4031  }
4032  sldStyle = sldDocument.toString();
4033 
4034  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
4035  description, uiFileContent, useAsDefault, msgError );
4036 }
4037 
4038 
4039 
4040 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
4041 {
4042  return loadNamedStyle( theURI, theResultFlag, false );
4043 }
4044 
4045 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
4046 {
4047  QgsDataSourceURI dsUri( theURI );
4048  if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
4049  {
4051  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4052  if ( myLib )
4053  {
4054  loadStyle_t* loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );
4055  if ( loadStyleExternalMethod )
4056  {
4057  QString qml, errorMsg;
4058  qml = loadStyleExternalMethod( mDataSource, errorMsg );
4059  if ( !qml.isEmpty() )
4060  {
4062  theResultFlag = applyNamedStyle( qml, errorMsg );
4064  return QObject::tr( "Loaded from Provider" );
4065  }
4066  }
4067  }
4068  }
4069 
4070  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
4071 }
4072 
4073 bool QgsVectorLayer::applyNamedStyle( const QString& namedStyle, QString& errorMsg )
4074 {
4075  QDomDocument myDocument( "qgis" );
4076  myDocument.setContent( namedStyle );
4077 
4078  return importNamedStyle( myDocument, errorMsg );
4079 }
4080 
4081 
4083 {
4084  QDomElement elem = doc.createElement( "attributeEditorRelation" );
4085  elem.setAttribute( "name", mName );
4086  elem.setAttribute( "relation", mRelation.id() );
4087  return elem;
4088 }
4089 
4091 {
4092  mRelation = relationManager->relation( mRelationId );
4093  return mRelation.isValid();
4094 }
4095 
4097 {
4098  if ( mDataProvider )
4099  {
4100  return mDataProvider->layerDependencies();
4101  }
4102  return QSet<QString>();
4103 }
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.
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:195
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.
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.
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:111
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.
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 beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
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.
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)
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:196
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:433
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
Storage and management of actions associated with Qgis layer attributes.
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.
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:474
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.
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
virtual void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Return unique values of an attribute.
Container of fields for a vector layer.
Definition: qgsfield.h:187
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:435
WkbType
Used for symbology operations.
Definition: qgis.h:57
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:36
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
bool addFeature(QgsFeature &f, bool alsoUpdateExtent=true)
Adds a feature.
virtual QList< QString > usedAttributes()=0
Returns a set of attributes required for this renderer.
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:194
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.
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.
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:707
void invertSelection()
Select not selected features and deselect selected ones.
double x() const
Get the x value of the point.
Definition: qgspoint.h:180
it has not been specified where the field comes from
Definition: qgsfield.h:193
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
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
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.
SnappingType
Snap to vertex, to segment or both.
Definition: qgssnapper.h:66
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...
void geometryChanged(QgsFeatureId fid, QgsGeometry &geom)
QString number(int n, int base)
int count(const T &value) const
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
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)
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.
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:84
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.
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 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 an empty 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:701
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:573
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:157
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.
void setY(double y)
Sets the y value of the point.
Definition: qgspoint.h:165
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 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
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:475
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.
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)
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:704
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())
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...
void setSelectedFeatures(const QgsFeatureIds &ids)
Change selection to the new set of features.
void endMacro()
bool isEmpty() const
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()
access to canonical QgsProject instance
Definition: qgsproject.cpp:388
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.
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:188
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
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:268
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)
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.
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.
virtual QgsRectangle extent()
Return the extent of the layer.
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void modifySelection(QgsFeatureIds selectIds, QgsFeatureIds deselectIds)
Modifies the current selection on this layer.
field is calculated from an expression
Definition: qgsfield.h:197
int selectedFeatureCount()
The number of features that are selected in this layer.
void updatedFields()
Is emitted, whenever the fields available from this layer have been changed.
QgsRelationManager * relationManager() const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
QString toString() const
void updateExpressionField(int index, const QString &exp)
Changes the expression used to define an expression based (virtual) field.
EditResult
Result of an edit operation.
const QgsVectorLayer * layer
Layer where the snap occurred.
Definition: qgssnapper.h:56
QString joinLayerId
Source layer.
void layerModified()
This signal is emitted when modifications has been done on layer.
QString evalErrorString() const
Returns evaluation error.
Q_DECL_DEPRECATED void drawLabels(QgsRenderContext &rendererContext) override
Draws the layer labels using the old labeling engine.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
iterator begin()
int size() const
int beforeVertexNr
The index of the vertex before snappedVertex or -1 if no such vertex.
Definition: qgssnapper.h:47
void createJoinCaches()
Caches joined attributes if required (and not already done)
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as SLD style in a QDomDocument.
int splitFeatures(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
Used by QgsVectorLayer::countSymbolFeatures() to provide an interruption checker. ...
virtual QList< QgsAttributeEditorElement * > findElements(AttributeEditorType type) const
Traverses the element tree to find any element of the specified type.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
bool isValid() const
QList< QgsRelation > referencingRelations(QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Get all relations where the specified layer (and field) is the referencing part (i.e.
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QDomNode at(int index) const
QString toProj4() const
Returns a Proj4 string representation of this CRS.
const T value(const Key &key) const
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError)
Save named and sld style of the layer to the style table in the db.
Q_DECL_DEPRECATED void enableLabels(bool on)
Set labels on.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
QgsRectangle boundingBoxOfSelected()
Returns the bounding box of the selected features.
bool saveStyle_t(const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
QByteArray toUtf8() const