QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
38 #include "qgsattributeaction.h"
39 
40 #include "qgis.h" //for globals
41 #include "qgsapplication.h"
42 #include "qgsclipper.h"
44 #include "qgscoordinatetransform.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 "qgsvectorlayerrenderer.h"
74 
75 #include "qgsrendererv2.h"
76 #include "qgssymbolv2.h"
77 #include "qgssymbollayerv2.h"
79 #include "qgsdiagramrendererv2.h"
80 #include "qgsstylev2.h"
82 #include "qgspallabeling.h"
83 #include "qgssimplifymethod.h"
84 
85 #include "diagram/qgsdiagram.h"
86 
87 #ifdef TESTPROVIDERLIB
88 #include <dlfcn.h>
89 #endif
90 
91 typedef bool saveStyle_t(
92  const QString& uri,
93  const QString& qmlStyle,
94  const QString& sldStyle,
95  const QString& styleName,
96  const QString& styleDescription,
97  const QString& uiFileContent,
98  bool useAsDefault,
99  QString& errCause
100 );
101 
102 typedef QString loadStyle_t(
103  const QString& uri,
104  QString& errCause
105 );
106 
107 typedef int listStyles_t(
108  const QString& uri,
109  QStringList &ids,
110  QStringList &names,
111  QStringList &descriptions,
112  QString& errCause
113 );
114 
115 typedef QString getStyleById_t(
116  const QString& uri,
117  QString styleID,
118  QString& errCause
119 );
120 
121 QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
122  QString baseName,
123  QString providerKey,
124  bool loadDefaultStyleFlag )
125  : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
126  , mDataProvider( NULL )
127  , mProviderKey( providerKey )
128  , mReadOnly( false )
129  , mWkbType( QGis::WKBUnknown )
130  , mRendererV2( NULL )
131  , mLabel( 0 )
132  , mLabelOn( false )
133  , mLabelFontNotFoundNotified( false )
134  , mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
135  , mLayerTransparency( 0 )
136  , mVertexMarkerOnlyForSelection( false )
137  , mEditorLayout( GeneratedLayout )
138  , mFeatureFormSuppress( SuppressDefault )
139  , mCache( new QgsGeometryCache() )
140  , mEditBuffer( 0 )
141  , mJoinBuffer( 0 )
142  , mExpressionFieldBuffer( 0 )
143  , mDiagramRenderer( 0 )
144  , mDiagramLayerSettings( 0 )
145  , mValidExtent( false )
146  , mLazyExtent( true )
147  , mSymbolFeatureCounted( false )
148 {
149  mActions = new QgsAttributeAction( this );
150 
151  // if we're given a provider type, try to create and bind one to this layer
152  if ( ! mProviderKey.isEmpty() )
153  {
154  setDataProvider( mProviderKey );
155  }
156  if ( mValid )
157  {
158  // Always set crs
160 
161  // check if there is a default style / propertysheet defined
162  // for this layer and if so apply it
163  bool defaultLoadedFlag = false;
164  if ( loadDefaultStyleFlag )
165  {
166  loadDefaultStyle( defaultLoadedFlag );
167  }
168 
169  // if the default style failed to load or was disabled use some very basic defaults
170  if ( !defaultLoadedFlag && hasGeometryType() )
171  {
172  // add single symbol renderer
174  }
175 
177 
178  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
179  }
180 
181  connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( selectionChanged() ) );
182  connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( repaintRequested() ) );
183  connect( QgsProject::instance()->relationManager(), SIGNAL( relationsLoaded() ), this, SLOT( onRelationsLoaded() ) );
184 
185  // Default simplify drawing settings
186  QSettings settings;
187  mSimplifyMethod.setSimplifyHints(( QgsVectorSimplifyMethod::SimplifyHints ) settings.value( "/qgis/simplifyDrawingHints", ( int ) mSimplifyMethod.simplifyHints() ).toInt() );
188  mSimplifyMethod.setThreshold( settings.value( "/qgis/simplifyDrawingTol", mSimplifyMethod.threshold() ).toFloat() );
189  mSimplifyMethod.setForceLocalOptimization( settings.value( "/qgis/simplifyLocal", mSimplifyMethod.forceLocalOptimization() ).toBool() );
190  mSimplifyMethod.setMaximumScale( settings.value( "/qgis/simplifyMaxScale", mSimplifyMethod.maximumScale() ).toFloat() );
191 } // QgsVectorLayer ctor
192 
193 
194 
196 {
197  QgsDebugMsg( "entered." );
198 
199  emit layerDeleted();
200 
201  mValid = false;
202 
203  delete mDataProvider;
204  delete mEditBuffer;
205  delete mJoinBuffer;
206  delete mExpressionFieldBuffer;
207  delete mCache;
208  delete mLabel;
209  delete mDiagramLayerSettings;
210 
211  delete mActions;
212 
213  delete mRendererV2;
214 }
215 
217 {
218  if ( mDataProvider )
219  {
220  return mDataProvider->storageType();
221  }
222  return 0;
223 }
224 
225 
227 {
228  if ( mDataProvider )
229  {
230  return mDataProvider->capabilitiesString();
231  }
232  return 0;
233 }
234 
236 {
237  if ( mDataProvider )
238  {
239  return mDataProvider->dataComment();
240  }
241  return QString();
242 }
243 
244 
246 {
247  return mProviderKey;
248 }
249 
253 void QgsVectorLayer::setDisplayField( QString fldName )
254 {
255  if ( !hasGeometryType() )
256  return;
257 
258  // If fldName is provided, use it as the display field, otherwise
259  // determine the field index for the feature column of the identify
260  // dialog. We look for fields containing "name" first and second for
261  // fields containing "id". If neither are found, the first field
262  // is used as the node.
263  QString idxName = "";
264  QString idxId = "";
265 
266  if ( !fldName.isEmpty() )
267  {
268  mDisplayField = fldName;
269  }
270  else
271  {
272  const QgsFields &fields = pendingFields();
273  int fieldsSize = fields.size();
274 
275  for ( int idx = 0; idx < fields.count(); ++idx )
276  {
277  QString fldName = fields[idx].name();
278  QgsDebugMsg( "Checking field " + fldName + " of " + QString::number( fieldsSize ) + " total" );
279 
280  // Check the fields and keep the first one that matches.
281  // We assume that the user has organized the data with the
282  // more "interesting" field names first. As such, name should
283  // be selected before oldname, othername, etc.
284  if ( fldName.indexOf( "name", 0, Qt::CaseInsensitive ) > -1 )
285  {
286  if ( idxName.isEmpty() )
287  {
288  idxName = fldName;
289  }
290  }
291  if ( fldName.indexOf( "descrip", 0, Qt::CaseInsensitive ) > -1 )
292  {
293  if ( idxName.isEmpty() )
294  {
295  idxName = fldName;
296  }
297  }
298  if ( fldName.indexOf( "id", 0, Qt::CaseInsensitive ) > -1 )
299  {
300  if ( idxId.isEmpty() )
301  {
302  idxId = fldName;
303  }
304  }
305  }
306 
307  //if there were no fields in the dbf just return - otherwise qgis segfaults!
308  if ( fieldsSize == 0 )
309  return;
310 
311  if ( idxName.length() > 0 )
312  {
313  mDisplayField = idxName;
314  }
315  else
316  {
317  if ( idxId.length() > 0 )
318  {
319  mDisplayField = idxId;
320  }
321  else
322  {
323  mDisplayField = fields[0].name();
324  }
325  }
326 
327  }
328 }
329 
330 // NOTE this is a temporary method added by Tim to prevent label clipping
331 // which was occurring when labeller was called in the main draw loop
332 // This method will probably be removed again in the near future!
334 {
335  if ( !hasGeometryType() )
336  return;
337 
338  QgsDebugMsg( "Starting draw of labels: " + id() );
339 
340  if ( mRendererV2 && mLabelOn && mLabel &&
341  ( !mLabel->scaleBasedVisibility() ||
342  ( mLabel->minScale() <= rendererContext.rendererScale() &&
343  rendererContext.rendererScale() <= mLabel->maxScale() ) ) )
344  {
345  QgsAttributeList attributes;
346  foreach ( QString attrName, mRendererV2->usedAttributes() )
347  {
348  int attrNum = fieldNameIndex( attrName );
349  attributes.append( attrNum );
350  }
351  // make sure the renderer is ready for classification ("symbolForFeature")
352  mRendererV2->startRender( rendererContext, pendingFields() );
353 
354  // Add fields required for labels
355  mLabel->addRequiredFields( attributes );
356 
357  QgsDebugMsg( "Selecting features based on view extent" );
358 
359  int featureCount = 0;
360 
361  try
362  {
363  // select the records in the extent. The provider sets a spatial filter
364  // and sets up the selection set for retrieval
366  .setFilterRect( rendererContext.extent() )
367  .setSubsetOfAttributes( attributes ) );
368 
369  QgsFeature fet;
370  while ( fit.nextFeature( fet ) )
371  {
372  if ( mRendererV2->willRenderFeature( fet ) )
373  {
374  bool sel = mSelectedFeatureIds.contains( fet.id() );
375  mLabel->renderLabel( rendererContext, fet, sel, 0 );
376  }
377  featureCount++;
378  }
379  }
380  catch ( QgsCsException &e )
381  {
382  Q_UNUSED( e );
383  QgsDebugMsg( "Error projecting label locations" );
384  }
385 
386  if ( mRendererV2 )
387  {
388  mRendererV2->stopRender( rendererContext );
389  }
390 
391  QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
392  }
393 }
394 
396 {
397  if ( mDataProvider )
398  {
399  mDataProvider->reloadData();
400  }
401 }
402 
404 {
405  return new QgsVectorLayerRenderer( this, rendererContext );
406 }
407 
408 bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
409 {
410  QgsVectorLayerRenderer renderer( this, rendererContext );
411  return renderer.render();
412 }
413 
414 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int m )
415 {
417  {
418  p.setPen( QColor( 50, 100, 120, 200 ) );
419  p.setBrush( QColor( 200, 200, 210, 120 ) );
420  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
421  }
422  else if ( type == QgsVectorLayer::Cross )
423  {
424  p.setPen( QColor( 255, 0, 0 ) );
425  p.drawLine( x - m, y + m, x + m, y - m );
426  p.drawLine( x - m, y - m, x + m, y + m );
427  }
428 }
429 
431 {
432  mSelectedFeatureIds.insert( fid );
433 
434  emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
435 }
436 
437 void QgsVectorLayer::select( const QgsFeatureIds& featureIds )
438 {
439  mSelectedFeatureIds.unite( featureIds );
440 
441  emit selectionChanged( featureIds, QgsFeatureIds(), false );
442 }
443 
445 {
446  mSelectedFeatureIds.remove( fid );
447 
448  emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
449 }
450 
451 void QgsVectorLayer::deselect( const QgsFeatureIds& featureIds )
452 {
453  mSelectedFeatureIds.subtract( featureIds );
454 
455  emit selectionChanged( QgsFeatureIds(), featureIds, false );
456 }
457 
458 void QgsVectorLayer::select( QgsRectangle & rect, bool addToSelection )
459 {
460  // normalize the rectangle
461  rect.normalize();
462 
463  //select all the elements
465  .setFilterRect( rect )
467  .setSubsetOfAttributes( QgsAttributeList() ) );
468 
469  QgsFeatureIds ids;
470 
471  QgsFeature f;
472  while ( fit.nextFeature( f ) )
473  {
474  ids << f.id();
475  }
476 
477  if ( !addToSelection )
478  {
479  setSelectedFeatures( mSelectedFeatureIds + ids );
480  }
481  else
482  {
483  select( ids );
484  }
485 }
486 
488 {
489  QgsFeatureIds intersectingIds = selectIds & deselectIds;
490  if ( intersectingIds.count() > 0 )
491  {
492  QgsDebugMsg( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." );
493  }
494 
495  mSelectedFeatureIds -= deselectIds;
496  mSelectedFeatureIds += selectIds;
497 
498  emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
499 }
500 
502 {
504  ids.subtract( mSelectedFeatureIds );
505  setSelectedFeatures( ids );
506 }
507 
509 {
511 }
512 
514 {
516  .setFlags( QgsFeatureRequest::NoGeometry )
517  .setSubsetOfAttributes( QgsAttributeList() ) );
518 
519  QgsFeatureIds ids;
520 
521  QgsFeature fet;
522  while ( fit.nextFeature( fet ) )
523  {
524  ids << fet.id();
525  }
526 
527  return ids;
528 }
529 
531 {
532  // normalize the rectangle
533  rect.normalize();
534 
536  .setFilterRect( rect )
538  .setSubsetOfAttributes( QgsAttributeList() ) );
539 
540  QgsFeatureIds selectIds;
541  QgsFeatureIds deselectIds;
542 
543  QgsFeature fet;
544  while ( fit.nextFeature( fet ) )
545  {
546  if ( mSelectedFeatureIds.contains( fet.id() ) )
547  {
548  deselectIds << fet.id();
549  }
550  else
551  {
552  selectIds << fet.id();
553  }
554  }
555 
556  modifySelection( selectIds, deselectIds );
557 }
558 
560 {
561  if ( mSelectedFeatureIds.size() == 0 )
562  return;
563 
565 }
566 
568 {
569  return mDataProvider;
570 }
571 
573 {
574  return mDataProvider;
575 }
576 
577 void QgsVectorLayer::setProviderEncoding( const QString& encoding )
578 {
579  if ( mDataProvider && mDataProvider->encoding() != encoding )
580  {
581  mDataProvider->setEncoding( encoding );
582  updateFields();
583  }
584 }
585 
587 {
588  delete mDiagramRenderer;
589  mDiagramRenderer = r;
590 }
591 
593 {
594  if ( mDataProvider )
595  {
596  QGis::WkbType type = mDataProvider->geometryType();
597  switch ( type )
598  {
599  case QGis::WKBPoint:
600  case QGis::WKBPoint25D:
601  return QGis::Point;
602 
603  case QGis::WKBLineString:
605  return QGis::Line;
606 
607  case QGis::WKBPolygon:
608  case QGis::WKBPolygon25D:
609  return QGis::Polygon;
610 
611  case QGis::WKBMultiPoint:
613  return QGis::Point;
614 
617  return QGis::Line;
618 
621  return QGis::Polygon;
622 
623  case QGis::WKBNoGeometry:
624  return QGis::NoGeometry;
625  }
626  QgsDebugMsg( QString( "Data Provider Geometry type is not recognised, is %1" ).arg( type ) );
627  }
628  else
629  {
630  QgsDebugMsg( "pointer to mDataProvider is null" );
631  }
632 
633  // We shouldn't get here, and if we have, other things are likely to
634  // go wrong. Code that uses the type() return value should be
635  // rewritten to cope with a value of QGis::Unknown. To make this
636  // need known, the following message is printed every time we get
637  // here.
638  QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
639 
640  return QGis::UnknownGeometry;
641 }
642 
644 {
646  return ( t != QGis::NoGeometry && t != QGis::UnknownGeometry );
647 }
648 
650 {
651  return mWkbType;
652 }
653 
655 {
656  if ( mSelectedFeatureIds.size() == 0 ) //no selected features
657  {
658  return QgsRectangle( 0, 0, 0, 0 );
659  }
660 
661  QgsRectangle r, retval;
662  retval.setMinimal();
663 
664  QgsFeature fet;
665  if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
666  {
667  foreach ( QgsFeatureId fid, mSelectedFeatureIds )
668  {
670  .setFilterFid( fid )
671  .setSubsetOfAttributes( QgsAttributeList() ) )
672  .nextFeature( fet ) &&
673  fet.geometry() )
674  {
675  r = fet.geometry()->boundingBox();
676  retval.combineExtentWith( &r );
677  }
678  }
679  }
680  else
681  {
683  .setSubsetOfAttributes( QgsAttributeList() ) );
684 
685  while ( fit.nextFeature( fet ) )
686  {
687  if ( mSelectedFeatureIds.contains( fet.id() ) )
688  {
689  if ( fet.geometry() )
690  {
691  r = fet.geometry()->boundingBox();
692  retval.combineExtentWith( &r );
693  }
694  }
695  }
696  }
697 
698  if ( retval.width() == 0.0 || retval.height() == 0.0 )
699  {
700  // If all of the features are at the one point, buffer the
701  // rectangle a bit. If they are all at zero, do something a bit
702  // more crude.
703 
704  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
705  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
706  {
707  retval.set( -1.0, -1.0, 1.0, 1.0 );
708  }
709  }
710 
711  return retval;
712 }
713 
715 {
716  return customProperty( "labeling/enabled", QVariant( false ) ).toBool();
717 }
718 
720 {
721  if ( !mDiagramRenderer || !mDiagramLayerSettings )
722  return false;
723 
724  QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
725  if ( settingList.size() > 0 )
726  {
727  return settingList.at( 0 ).enabled;
728  }
729  return false;
730 }
731 
733 {
734  if ( !mDataProvider )
735  {
736  QgsDebugMsg( "invoked with null mDataProvider" );
737  return 0;
738  }
739 
740  return mDataProvider->featureCount();
741 }
742 
744 {
745  if ( !mSymbolFeatureCounted ) return -1;
746  return mSymbolFeatureCountMap.value( symbol );
747 }
748 
749 bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
750 {
751  if ( mSymbolFeatureCounted ) return true;
752  mSymbolFeatureCountMap.clear();
753 
754  if ( !mDataProvider )
755  {
756  QgsDebugMsg( "invoked with null mDataProvider" );
757  return false;
758  }
759  if ( !mRendererV2 )
760  {
761  QgsDebugMsg( "invoked with null mRendererV2" );
762  return false;
763  }
764 
765  QgsLegendSymbolList symbolList = mRendererV2->legendSymbolItems();
766  QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
767 
768  for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
769  {
770  mSymbolFeatureCountMap.insert( symbolIt->second, 0 );
771  }
772 
773  long nFeatures = pendingFeatureCount();
774  QProgressDialog progressDialog( tr( "Updating feature count for layer %1" ).arg( name() ), tr( "Abort" ), 0, nFeatures );
775  progressDialog.setWindowModality( Qt::WindowModal );
776  int featuresCounted = 0;
777 
779 
780  // Renderer (rule based) may depend on context scale, with scale is ignored if 0
781  QgsRenderContext renderContext;
782  renderContext.setRendererScale( 0 );
783  mRendererV2->startRender( renderContext, pendingFields() );
784 
785  QgsFeature f;
786  while ( fit.nextFeature( f ) )
787  {
788  QgsSymbolV2List featureSymbolList = mRendererV2->originalSymbolsForFeature( f );
789  for ( QgsSymbolV2List::iterator symbolIt = featureSymbolList.begin(); symbolIt != featureSymbolList.end(); ++symbolIt )
790  {
791  mSymbolFeatureCountMap[*symbolIt] += 1;
792  }
793  ++featuresCounted;
794 
795  if ( showProgress )
796  {
797  if ( featuresCounted % 50 == 0 )
798  {
799  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
800  {
801  progressDialog.setMaximum( 0 );
802  }
803  progressDialog.setValue( featuresCounted );
804  if ( progressDialog.wasCanceled() )
805  {
806  mSymbolFeatureCountMap.clear();
807  mRendererV2->stopRender( renderContext );
808  return false;
809  }
810  }
811  }
812  }
813  mRendererV2->stopRender( renderContext );
814  progressDialog.setValue( nFeatures );
815  mSymbolFeatureCounted = true;
816  return true;
817 }
818 
820 {
821  mValidExtent = false;
822 }
823 
825 {
827  mValidExtent = true;
828 }
829 
831 {
832  QgsRectangle rect;
833  rect.setMinimal();
834 
835  if ( !hasGeometryType() )
836  return rect;
837 
838  if ( !mValidExtent && mLazyExtent && mDataProvider )
839  {
840  // get the extent
841  QgsRectangle mbr = mDataProvider->extent();
842 
843  // show the extent
844  QString s = mbr.toString();
845 
846  QgsDebugMsg( "Extent of layer: " + s );
847  // store the extent
848  setExtent( mbr );
849 
850  mLazyExtent = false;
851  }
852 
853  if ( mValidExtent )
854  return QgsMapLayer::extent();
855 
856  if ( !mDataProvider )
857  {
858  QgsDebugMsg( "invoked with null mDataProvider" );
859  }
860 
861  if ( mDataProvider && mEditBuffer && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() )
862  {
863  mDataProvider->updateExtents();
864 
865  // get the extent of the layer from the provider
866  // but only when there are some features already
867  if ( mDataProvider->featureCount() != 0 )
868  {
869  QgsRectangle r = mDataProvider->extent();
870  rect.combineExtentWith( &r );
871  }
872 
873  for ( QgsFeatureMap::iterator it = mEditBuffer->mAddedFeatures.begin(); it != mEditBuffer->mAddedFeatures.end(); ++it )
874  {
875  if ( it->geometry() )
876  {
877  QgsRectangle r = it->geometry()->boundingBox();
878  rect.combineExtentWith( &r );
879  }
880  }
881  }
882  else
883  {
885  .setSubsetOfAttributes( QgsAttributeList() ) );
886 
887  QgsFeature fet;
888  while ( fit.nextFeature( fet ) )
889  {
890  if ( fet.geometry() && fet.geometry()->type() != QGis::UnknownGeometry )
891  {
892  QgsRectangle bb = fet.geometry()->boundingBox();
893  rect.combineExtentWith( &bb );
894  }
895  }
896  }
897 
898  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
899  {
900  // special case when there are no features in provider nor any added
901  rect = QgsRectangle(); // use rectangle with zero coordinates
902  }
903 
904  setExtent( rect );
905 
906  // Send this (hopefully) up the chain to the map canvas
907  emit recalculateExtents();
908 
909  return rect;
910 }
911 
913 {
914  if ( ! mDataProvider )
915  {
916  QgsDebugMsg( "invoked with null mDataProvider" );
917  return 0;
918  }
919  return mDataProvider->subsetString();
920 }
921 
922 bool QgsVectorLayer::setSubsetString( QString subset )
923 {
924  if ( ! mDataProvider )
925  {
926  QgsDebugMsg( "invoked with null mDataProvider" );
927  return false;
928  }
929 
930  bool res = mDataProvider->setSubsetString( subset );
931 
932  // get the updated data source string from the provider
933  mDataSource = mDataProvider->dataSourceUri();
934  updateExtents();
935 
936  if ( res )
937  emit repaintRequested();
938 
939  return res;
940 }
941 
943 {
944  if ( mDataProvider && !mEditBuffer && ( hasGeometryType() && geometryType() != QGis::Point ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
945  {
946  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
947 
948  // check maximum scale at which generalisation should be carried out
949  if ( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale )
950  return false;
951 
952  return true;
953  }
954  return false;
955 }
956 
958 {
959  if ( !mDataProvider )
960  return QgsFeatureIterator();
961 
962  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
963 }
964 
965 
966 bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
967 {
968  Q_UNUSED( alsoUpdateExtent ); // TODO[MD]
969  if ( !mEditBuffer || !mDataProvider )
970  return false;
971 
972  bool success = mEditBuffer->addFeature( f );
973 
974  if ( success )
975  updateExtents();
976 
977  return success;
978 }
979 
981 {
982  QgsFeatureRequest req;
983  req.setFilterFid( f.id() );
984  if ( !f.geometry() )
986  if ( f.attributes().isEmpty() )
988 
989  QgsFeature current;
990  if ( !getFeatures( req ).nextFeature( current ) )
991  {
992  QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( f.id() ) );
993  return false;
994  }
995 
996  if ( f.geometry() && current.geometry() && f.geometry() != current.geometry() && !f.geometry()->isGeosEqual( *current.geometry() ) )
997  {
998  if ( !changeGeometry( f.id(), f.geometry() ) )
999  {
1000  QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( f.id() ) );
1001  return false;
1002  }
1003  }
1004 
1005  const QgsAttributes &fa = f.attributes();
1006  const QgsAttributes &ca = current.attributes();
1007 
1008  for ( int attr = 0; attr < fa.count(); ++attr )
1009  {
1010  if ( fa[attr] != ca[attr] )
1011  {
1012  if ( !changeAttributeValue( f.id(), attr, fa[attr], ca[attr] ) )
1013  {
1014  QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( f.id() ) );
1015  return false;
1016  }
1017  }
1018  }
1019 
1020  return true;
1021 }
1022 
1023 
1024 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1025 {
1026  if ( !mEditBuffer || !mDataProvider )
1027  return false;
1028 
1029  QgsVectorLayerEditUtils utils( this );
1030  return utils.insertVertex( x, y, atFeatureId, beforeVertex );
1031 }
1032 
1033 
1034 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1035 {
1036  if ( !mEditBuffer || !mDataProvider )
1037  return false;
1038 
1039  QgsVectorLayerEditUtils utils( this );
1040  return utils.moveVertex( x, y, atFeatureId, atVertex );
1041 }
1042 
1043 
1044 bool QgsVectorLayer::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
1045 {
1046  if ( !mEditBuffer || !mDataProvider )
1047  return false;
1048 
1049  QgsVectorLayerEditUtils utils( this );
1050  return utils.deleteVertex( atFeatureId, atVertex );
1051 }
1052 
1053 
1055 {
1056  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1057  {
1058  return false;
1059  }
1060 
1061  if ( !isEditable() )
1062  {
1063  return false;
1064  }
1065 
1066  int deleted = 0;
1067  int count = mSelectedFeatureIds.size();
1068  // Make a copy since deleteFeature modifies mSelectedFeatureIds
1069  QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1070  foreach ( QgsFeatureId fid, selectedFeatures )
1071  {
1072  deleted += deleteFeature( fid ); // removes from selection
1073  }
1074 
1075  triggerRepaint();
1076  updateExtents();
1077 
1078  if ( deletedCount )
1079  {
1080  *deletedCount = deleted;
1081  }
1082 
1083  return deleted == count;
1084 }
1085 
1086 int QgsVectorLayer::addRing( const QList<QgsPoint>& ring )
1087 {
1088  if ( !mEditBuffer || !mDataProvider )
1089  return 6;
1090 
1091  QgsVectorLayerEditUtils utils( this );
1092  return utils.addRing( ring );
1093 }
1094 
1095 int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
1096 {
1097  if ( !mEditBuffer || !mDataProvider )
1098  return 7;
1099 
1100  //number of selected features must be 1
1101 
1102  if ( mSelectedFeatureIds.size() < 1 )
1103  {
1104  QgsDebugMsg( "Number of selected features <1" );
1105  return 4;
1106  }
1107  else if ( mSelectedFeatureIds.size() > 1 )
1108  {
1109  QgsDebugMsg( "Number of selected features >1" );
1110  return 5;
1111  }
1112 
1113  QgsVectorLayerEditUtils utils( this );
1114  return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1115 }
1116 
1117 
1118 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1119 {
1120  if ( !mEditBuffer || !mDataProvider )
1121  return -1;
1122 
1123  QgsVectorLayerEditUtils utils( this );
1124  return utils.translateFeature( featureId, dx, dy );
1125 }
1126 
1127 int QgsVectorLayer::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1128 {
1129  if ( !mEditBuffer || !mDataProvider )
1130  return -1;
1131 
1132  QgsVectorLayerEditUtils utils( this );
1133  return utils.splitParts( splitLine, topologicalEditing );
1134 }
1135 
1136 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1137 {
1138  if ( !mEditBuffer || !mDataProvider )
1139  return -1;
1140 
1141  QgsVectorLayerEditUtils utils( this );
1142  return utils.splitFeatures( splitLine, topologicalEditing );
1143 }
1144 
1146 {
1147  if ( !hasGeometryType() )
1148  return 1;
1149 
1150  int returnValue = 0;
1151 
1152  //first test if geom really has type polygon or multipolygon
1153  if ( geom->type() != QGis::Polygon )
1154  {
1155  return 1;
1156  }
1157 
1158  //get bounding box of geom
1159  QgsRectangle geomBBox = geom->boundingBox();
1160 
1161  //get list of features that intersect this bounding box
1163  .setFilterRect( geomBBox )
1165  .setSubsetOfAttributes( QgsAttributeList() ) );
1166 
1167  QgsFeature f;
1168  while ( fit.nextFeature( f ) )
1169  {
1170  if ( ignoreFeatures.contains( f.id() ) )
1171  {
1172  continue;
1173  }
1174 
1175  //call geometry->makeDifference for each feature
1176  QgsGeometry *currentGeom = f.geometry();
1177  if ( currentGeom )
1178  {
1179  if ( geom->makeDifference( currentGeom ) != 0 )
1180  {
1181  returnValue = 2;
1182  }
1183  }
1184  }
1185 
1186  return returnValue;
1187 }
1188 
1190 {
1191  if ( !mEditBuffer || !mDataProvider )
1192  return -1;
1193 
1194  QgsVectorLayerEditUtils utils( this );
1195  return utils.addTopologicalPoints( geom );
1196 }
1197 
1199 {
1200  if ( !mEditBuffer || !mDataProvider )
1201  return -1;
1202 
1203  QgsVectorLayerEditUtils utils( this );
1204  return utils.addTopologicalPoints( p );
1205 }
1206 
1208 {
1209  return mLabel;
1210 }
1211 
1213 {
1214  return mLabel;
1215 }
1216 
1218 {
1219  mLabelOn = on;
1220 }
1221 
1223 {
1224  return mLabelOn;
1225 }
1226 
1228 {
1229  if ( !mDataProvider )
1230  {
1231  return false;
1232  }
1233 
1234  // allow editing if provider supports any of the capabilities
1235  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1236  {
1237  return false;
1238  }
1239 
1240  if ( mReadOnly )
1241  {
1242  return false;
1243  }
1244 
1245  if ( mEditBuffer )
1246  {
1247  // editing already underway
1248  return false;
1249  }
1250 
1251  if ( mDataProvider->transaction() )
1252  {
1253  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1254  }
1255  else
1256  {
1257  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1258  }
1259  // forward signals
1260  connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( invalidateSymbolCountedFlag() ) );
1261  connect( mEditBuffer, SIGNAL( layerModified() ), this, SIGNAL( layerModified() ) ); // TODO[MD]: necessary?
1262  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1263  connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( featureAdded( QgsFeatureId ) ) );
1264  connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SIGNAL( featureDeleted( QgsFeatureId ) ) );
1265  connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
1266  connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
1267  connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), this, SIGNAL( attributeAdded( int ) ) );
1268  connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), this, SIGNAL( attributeDeleted( int ) ) );
1269 
1270  connect( mEditBuffer, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ),
1271  this, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ) );
1272 
1273  connect( mEditBuffer, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ),
1274  this, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ) );
1275 
1276  connect( mEditBuffer, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ), this, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ) );
1277  connect( mEditBuffer, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ), this, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ) );
1278 
1279  connect( mEditBuffer, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ),
1280  this, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ) );
1281 
1282  connect( mEditBuffer, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ),
1283  this, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ) );
1284 
1285  updateFields();
1286 
1287  emit editingStarted();
1288 
1289  return true;
1290 }
1291 
1292 bool QgsVectorLayer::readXml( const QDomNode& layer_node )
1293 {
1294  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
1295 
1296  //process provider key
1297  QDomNode pkeyNode = layer_node.namedItem( "provider" );
1298 
1299  if ( pkeyNode.isNull() )
1300  {
1301  mProviderKey = "";
1302  }
1303  else
1304  {
1305  QDomElement pkeyElt = pkeyNode.toElement();
1306  mProviderKey = pkeyElt.text();
1307  }
1308 
1309  // determine type of vector layer
1310  if ( ! mProviderKey.isNull() )
1311  {
1312  // if the provider string isn't empty, then we successfully
1313  // got the stored provider
1314  }
1315  else if ( mDataSource.contains( "dbname=" ) )
1316  {
1317  mProviderKey = "postgres";
1318  }
1319  else
1320  {
1321  mProviderKey = "ogr";
1322  }
1323 
1324  if ( ! setDataProvider( mProviderKey ) )
1325  {
1326  return false;
1327  }
1328 
1329  QDomElement pkeyElem = pkeyNode.toElement();
1330  if ( !pkeyElem.isNull() )
1331  {
1332  QString encodingString = pkeyElem.attribute( "encoding" );
1333  if ( !encodingString.isEmpty() )
1334  {
1335  mDataProvider->setEncoding( encodingString );
1336  }
1337  }
1338 
1339  //load vector joins
1340  if ( !mJoinBuffer )
1341  {
1342  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1343  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1344  }
1345  mJoinBuffer->readXml( layer_node );
1346 
1347  if ( !mExpressionFieldBuffer )
1348  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1349  mExpressionFieldBuffer->readXml( layer_node );
1350 
1351  updateFields();
1352  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1353 
1354  QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );
1355 
1356  if ( prevExpNode.isNull() )
1357  {
1358  mDisplayExpression = "";
1359  }
1360  else
1361  {
1362  QDomElement prevExpElem = prevExpNode.toElement();
1363  mDisplayExpression = prevExpElem.text();
1364  }
1365 
1366  QString errorMsg;
1367  if ( !readSymbology( layer_node, errorMsg ) )
1368  {
1369  return false;
1370  }
1371 
1372  readStyleManager( layer_node );
1373 
1375 
1376  return mValid; // should be true if read successfully
1377 
1378 } // void QgsVectorLayer::readXml
1379 
1380 
1381 bool QgsVectorLayer::setDataProvider( QString const & provider )
1382 {
1383  // XXX should I check for and possibly delete any pre-existing providers?
1384  // XXX How often will that scenario occur?
1385 
1386  mProviderKey = provider; // XXX is this necessary? Usually already set
1387  // XXX when execution gets here.
1388 
1389  //XXX - This was a dynamic cast but that kills the Windows
1390  // version big-time with an abnormal termination error
1391  mDataProvider =
1393 
1394  if ( mDataProvider )
1395  {
1396  QgsDebugMsg( "Instantiated the data provider plugin" );
1397 
1398  mValid = mDataProvider->isValid();
1399  if ( mValid )
1400  {
1401  // TODO: Check if the provider has the capability to send fullExtentCalculated
1402  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
1403 
1404  // get and store the feature type
1405  mWkbType = mDataProvider->geometryType();
1406 
1407  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1408  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1409  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1410  updateFields();
1411 
1412  // look at the fields in the layer and set the primary
1413  // display field using some real fuzzy logic
1414  setDisplayField();
1415 
1416  if ( mProviderKey == "postgres" )
1417  {
1418  QgsDebugMsg( "Beautifying layer name " + name() );
1419 
1420  // adjust the display name for postgres layers
1421  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1422  if ( reg.indexIn( name() ) >= 0 )
1423  {
1424  QStringList stuff = reg.capturedTexts();
1425  QString lName = stuff[1];
1426 
1427  const QMap<QString, QgsMapLayer*> &layers = QgsMapLayerRegistry::instance()->mapLayers();
1428 
1429  QMap<QString, QgsMapLayer*>::const_iterator it;
1430  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1431  ;
1432 
1433  if ( it != layers.constEnd() && stuff.size() > 2 )
1434  {
1435  lName += "." + stuff[2].mid( 2, stuff[2].length() - 3 );
1436  }
1437 
1438  if ( !lName.isEmpty() )
1439  setLayerName( lName );
1440  }
1441 
1442  QgsDebugMsg( "Beautified layer name " + name() );
1443 
1444  // deal with unnecessary schema qualification to make v.in.ogr happy
1445  mDataSource = mDataProvider->dataSourceUri();
1446  }
1447  else if ( mProviderKey == "osm" )
1448  {
1449  // make sure that the "observer" has been removed from URI to avoid crashes
1450  mDataSource = mDataProvider->dataSourceUri();
1451  }
1452  else if ( provider == "ogr" )
1453  {
1454  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1455  mDataSource = mDataProvider->dataSourceUri();
1456  if ( mDataSource.right( 10 ) == "|layerid=0" )
1457  mDataSource.chop( 10 );
1458  }
1459 
1460  // label
1461  mLabel = new QgsLabel( mDataProvider->fields() );
1462  mLabelOn = false;
1463  }
1464  else
1465  {
1466  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1467  return false;
1468  }
1469  }
1470  else
1471  {
1472  QgsDebugMsg( " unable to get data provider" );
1473  return false;
1474  }
1475 
1476  return true;
1477 
1478 } // QgsVectorLayer:: setDataProvider
1479 
1480 
1481 
1482 
1483 /* virtual */
1484 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
1485  QDomDocument & document )
1486 {
1487  // first get the layer element so that we can append the type attribute
1488 
1489  QDomElement mapLayerNode = layer_node.toElement();
1490 
1491  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1492  {
1493  QgsDebugMsg( "can't find <maplayer>" );
1494  return false;
1495  }
1496 
1497  mapLayerNode.setAttribute( "type", "vector" );
1498 
1499  // set the geometry type
1500  mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
1501 
1502  // add provider node
1503  if ( mDataProvider )
1504  {
1505  QDomElement provider = document.createElement( "provider" );
1506  provider.setAttribute( "encoding", mDataProvider->encoding() );
1507  QDomText providerText = document.createTextNode( providerType() );
1508  provider.appendChild( providerText );
1509  layer_node.appendChild( provider );
1510  }
1511 
1512  // save preview expression
1513  QDomElement prevExpElem = document.createElement( "previewExpression" );
1514  QDomText prevExpText = document.createTextNode( mDisplayExpression );
1515  prevExpElem.appendChild( prevExpText );
1516  layer_node.appendChild( prevExpElem );
1517 
1518  //save joins
1519  mJoinBuffer->writeXml( layer_node, document );
1520 
1521  // save expression fields
1522  mExpressionFieldBuffer->writeXml( layer_node, document );
1523 
1524  writeStyleManager( layer_node, document );
1525 
1526  // renderer specific settings
1527  QString errorMsg;
1528  return writeSymbology( layer_node, document, errorMsg );
1529 } // bool QgsVectorLayer::writeXml
1530 
1531 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
1532 {
1533  emit readCustomSymbology( node.toElement(), errorMessage );
1534 
1535  if ( hasGeometryType() )
1536  {
1537  // try renderer v2 first
1538  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1539  if ( !rendererElement.isNull() )
1540  {
1541  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
1542  if ( !r )
1543  return false;
1544 
1545  setRendererV2( r );
1546  }
1547  else
1548  {
1550  if ( !r )
1552 
1553  setRendererV2( r );
1554  }
1555 
1556  // get and set the display field if it exists.
1557  QDomNode displayFieldNode = node.namedItem( "displayfield" );
1558  if ( !displayFieldNode.isNull() )
1559  {
1560  QDomElement e = displayFieldNode.toElement();
1561  setDisplayField( e.text() );
1562  }
1563 
1564  // get and set the blend mode if it exists
1565  QDomNode blendModeNode = node.namedItem( "blendMode" );
1566  if ( !blendModeNode.isNull() )
1567  {
1568  QDomElement e = blendModeNode.toElement();
1570  }
1571 
1572  // get and set the feature blend mode if it exists
1573  QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
1574  if ( !featureBlendModeNode.isNull() )
1575  {
1576  QDomElement e = featureBlendModeNode.toElement();
1578  }
1579 
1580  // get and set the layer transparency if it exists
1581  QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
1582  if ( !layerTransparencyNode.isNull() )
1583  {
1584  QDomElement e = layerTransparencyNode.toElement();
1585  setLayerTransparency( e.text().toInt() );
1586  }
1587 
1588  // use scale dependent visibility flag
1589  QDomElement e = node.toElement();
1590  if ( mLabel )
1591  {
1592  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
1593  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
1594  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
1595  }
1596 
1597  // get the simplification drawing settings
1598  mSimplifyMethod.setSimplifyHints(( QgsVectorSimplifyMethod::SimplifyHints ) e.attribute( "simplifyDrawingHints", "1" ).toInt() );
1599  mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
1600  mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
1601  mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
1602 
1603  //also restore custom properties (for labeling-ng)
1604  readCustomProperties( node, "labeling" );
1605 
1606  // Test if labeling is on or off
1607  QDomNode labelnode = node.namedItem( "label" );
1608  QDomElement element = labelnode.toElement();
1609  int hasLabelsEnabled = element.text().toInt();
1611  if ( hasLabelsEnabled < 1 )
1612  {
1613  enableLabels( false );
1614  }
1615  else
1616  {
1617  enableLabels( true );
1618  }
1620 
1621  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
1622 
1623  if ( !labelattributesnode.isNull() && mLabel )
1624  {
1625  QgsDebugMsg( "calling readXML" );
1626  mLabel->readXML( labelattributesnode );
1627  }
1628 
1629  //diagram renderer and diagram layer settings
1630  delete mDiagramRenderer; mDiagramRenderer = 0;
1631  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
1632  if ( !singleCatDiagramElem.isNull() )
1633  {
1634  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1635  mDiagramRenderer->readXML( singleCatDiagramElem, this );
1636  }
1637  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
1638  if ( !linearDiagramElem.isNull() )
1639  {
1640  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
1641  mDiagramRenderer->readXML( linearDiagramElem, this );
1642  }
1643 
1644  if ( mDiagramRenderer )
1645  {
1646  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
1647  if ( !diagramSettingsElem.isNull() )
1648  {
1649  mDiagramLayerSettings = new QgsDiagramLayerSettings();
1650  mDiagramLayerSettings->readXML( diagramSettingsElem, this );
1651  }
1652  }
1653  }
1654 
1655  // process the attribute actions
1656  mActions->readXML( node );
1657 
1658 
1659  QDomNode editFormNode = node.namedItem( "editform" );
1660  if ( !editFormNode.isNull() )
1661  {
1662  QDomElement e = editFormNode.toElement();
1663  mEditForm = QgsProject::instance()->readPath( e.text() );
1664  }
1665 
1666  QDomNode editFormInitNode = node.namedItem( "editforminit" );
1667  if ( !editFormInitNode.isNull() )
1668  {
1669  mEditFormInit = editFormInitNode.toElement().text();
1670  }
1671 
1672  QDomNode fFSuppNode = node.namedItem( "featformsuppress" );
1673  if ( fFSuppNode.isNull() )
1674  {
1675  mFeatureFormSuppress = SuppressDefault;
1676  }
1677  else
1678  {
1679  QDomElement e = fFSuppNode.toElement();
1680  mFeatureFormSuppress = ( QgsVectorLayer::FeatureFormSuppress )e.text().toInt();
1681  }
1682 
1683  QDomNode annotationFormNode = node.namedItem( "annotationform" );
1684  if ( !annotationFormNode.isNull() )
1685  {
1686  QDomElement e = annotationFormNode.toElement();
1687  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1688  }
1689 
1690  mAttributeAliasMap.clear();
1691  QDomNode aliasesNode = node.namedItem( "aliases" );
1692  if ( !aliasesNode.isNull() )
1693  {
1694  QDomElement aliasElem;
1695 
1696  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
1697  for ( int i = 0; i < aliasNodeList.size(); ++i )
1698  {
1699  aliasElem = aliasNodeList.at( i ).toElement();
1700 
1701  QString field;
1702  if ( aliasElem.hasAttribute( "field" ) )
1703  {
1704  field = aliasElem.attribute( "field" );
1705  }
1706  else
1707  {
1708  int index = aliasElem.attribute( "index" ).toInt();
1709 
1710  if ( index >= 0 && index < pendingFields().count() )
1711  field = pendingFields()[ index ].name();
1712  }
1713 
1714  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
1715  }
1716  }
1717 
1718  // tab display
1719  QDomNode editorLayoutNode = node.namedItem( "editorlayout" );
1720  if ( editorLayoutNode.isNull() )
1721  {
1722  mEditorLayout = GeneratedLayout;
1723  }
1724  else
1725  {
1726  if ( editorLayoutNode.toElement().text() == "uifilelayout" )
1727  {
1728  mEditorLayout = UiFileLayout;
1729  }
1730  else if ( editorLayoutNode.toElement().text() == "tablayout" )
1731  {
1732  mEditorLayout = TabLayout;
1733  }
1734  else
1735  {
1736  mEditorLayout = GeneratedLayout;
1737  }
1738  }
1739 
1740  //Attributes excluded from WMS and WFS
1741  mExcludeAttributesWMS.clear();
1742  QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
1743  if ( !excludeWMSNode.isNull() )
1744  {
1745  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
1746  for ( int i = 0; i < attributeNodeList.size(); ++i )
1747  {
1748  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1749  }
1750  }
1751 
1752  mExcludeAttributesWFS.clear();
1753  QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
1754  if ( !excludeWFSNode.isNull() )
1755  {
1756  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
1757  for ( int i = 0; i < attributeNodeList.size(); ++i )
1758  {
1759  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1760  }
1761  }
1762 
1763  // tabs and groups display info
1764  mAttributeEditorElements.clear();
1765  QDomNode attributeEditorFormNode = node.namedItem( "attributeEditorForm" );
1766  QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
1767 
1768  for ( int i = 0; i < attributeEditorFormNodeList.size(); i++ )
1769  {
1770  QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
1771 
1772  QgsAttributeEditorElement *attributeEditorWidget = attributeEditorElementFromDomElement( elem, this );
1773  mAttributeEditorElements.append( attributeEditorWidget );
1774  }
1775 
1776  return true;
1777 }
1778 
1780 {
1781  QgsAttributeEditorElement* newElement = NULL;
1782 
1783  if ( elem.tagName() == "attributeEditorContainer" )
1784  {
1785  QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( elem.attribute( "name" ), parent );
1786 
1787  QDomNodeList childNodeList = elem.childNodes();
1788 
1789  for ( int i = 0; i < childNodeList.size(); i++ )
1790  {
1791  QDomElement childElem = childNodeList.at( i ).toElement();
1792  QgsAttributeEditorElement *myElem = attributeEditorElementFromDomElement( childElem, container );
1793  if ( myElem )
1794  container->addChildElement( myElem );
1795  }
1796 
1797  newElement = container;
1798  }
1799  else if ( elem.tagName() == "attributeEditorField" )
1800  {
1801  QString name = elem.attribute( "name" );
1802  int idx = fieldNameIndex( name );
1803  newElement = new QgsAttributeEditorField( name, idx, parent );
1804  }
1805  else if ( elem.tagName() == "attributeEditorRelation" )
1806  {
1807  // At this time, the relations are not loaded
1808  // So we only grab the id and delegate the rest to onRelationsLoaded()
1809  QString name = elem.attribute( "name" );
1810  newElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
1811  }
1812  return newElement;
1813 }
1814 
1815 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1816 {
1817  QDomElement mapLayerNode = node.toElement();
1818 
1819  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
1820 
1821  if ( hasGeometryType() )
1822  {
1823  QDomElement rendererElement = mRendererV2->save( doc );
1824  node.appendChild( rendererElement );
1825 
1826  // use scale dependent visibility flag
1827  if ( mLabel )
1828  {
1829  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
1830  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
1831  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
1832  }
1833 
1834  // save the simplification drawing settings
1835  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
1836  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
1837  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
1838  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
1839 
1840  //save customproperties (for labeling ng)
1841  writeCustomProperties( node, doc );
1842 
1843  // add the blend mode field
1844  QDomElement blendModeElem = doc.createElement( "blendMode" );
1845  QDomText blendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( blendMode() ) ) );
1846  blendModeElem.appendChild( blendModeText );
1847  node.appendChild( blendModeElem );
1848 
1849  // add the feature blend mode field
1850  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
1851  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( featureBlendMode() ) ) );
1852  featureBlendModeElem.appendChild( featureBlendModeText );
1853  node.appendChild( featureBlendModeElem );
1854 
1855  // add the layer transparency
1856  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
1857  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
1858  layerTransparencyElem.appendChild( layerTransparencyText );
1859  node.appendChild( layerTransparencyElem );
1860 
1861  // add the display field
1862  QDomElement dField = doc.createElement( "displayfield" );
1863  QDomText dFieldText = doc.createTextNode( displayField() );
1864  dField.appendChild( dFieldText );
1865  node.appendChild( dField );
1866 
1867  // add label node
1868  QDomElement labelElem = doc.createElement( "label" );
1869  QDomText labelText = doc.createTextNode( "" );
1870 
1872  if ( hasLabelsEnabled() )
1873  {
1874  labelText.setData( "1" );
1875  }
1876  else
1877  {
1878  labelText.setData( "0" );
1879  }
1881  labelElem.appendChild( labelText );
1882 
1883  node.appendChild( labelElem );
1884 
1885  // Now we get to do all that all over again for QgsLabel
1886 
1887  if ( mLabel )
1888  {
1889  QString fieldname = mLabel->labelField( QgsLabel::Text );
1890  if ( fieldname != "" )
1891  {
1892  dField = doc.createElement( "labelfield" );
1893  dFieldText = doc.createTextNode( fieldname );
1894  dField.appendChild( dFieldText );
1895  node.appendChild( dField );
1896  }
1897 
1898  mLabel->writeXML( node, doc );
1899  }
1900 
1901  if ( mDiagramRenderer )
1902  {
1903  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
1904  if ( mDiagramLayerSettings )
1905  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
1906  }
1907  }
1908 
1909  // FIXME
1910  // edittypes are written to the layerNode
1911  // by slot QgsEditorWidgetRegistry::writeMapLayer()
1912  // triggered by signal QgsProject::writeMapLayer()
1913  // still other editing settings are written here,
1914  // although they are not part of symbology either
1915 
1916  QDomElement efField = doc.createElement( "editform" );
1917  QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( mEditForm ) );
1918  efField.appendChild( efText );
1919  node.appendChild( efField );
1920 
1921  QDomElement efiField = doc.createElement( "editforminit" );
1922  if ( !mEditFormInit.isEmpty() )
1923  efiField.appendChild( doc.createTextNode( mEditFormInit ) );
1924  node.appendChild( efiField );
1925 
1926  QDomElement fFSuppElem = doc.createElement( "featformsuppress" );
1927  QDomText fFSuppText = doc.createTextNode( QString::number( featureFormSuppress() ) );
1928  fFSuppElem.appendChild( fFSuppText );
1929  node.appendChild( fFSuppElem );
1930 
1931  QDomElement afField = doc.createElement( "annotationform" );
1932  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
1933  afField.appendChild( afText );
1934  node.appendChild( afField );
1935 
1936  // tab display
1937  QDomElement editorLayoutElem = doc.createElement( "editorlayout" );
1938  switch ( mEditorLayout )
1939  {
1940  case UiFileLayout:
1941  editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
1942  break;
1943 
1944  case TabLayout:
1945  editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
1946  break;
1947 
1948  case GeneratedLayout:
1949  default:
1950  editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
1951  break;
1952  }
1953 
1954  node.appendChild( editorLayoutElem );
1955 
1956  //attribute aliases
1957  if ( mAttributeAliasMap.size() > 0 )
1958  {
1959  QDomElement aliasElem = doc.createElement( "aliases" );
1960  QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
1961  for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
1962  {
1963  int idx = fieldNameIndex( a_it.key() );
1964  if ( idx < 0 )
1965  continue;
1966 
1967  QDomElement aliasEntryElem = doc.createElement( "alias" );
1968  aliasEntryElem.setAttribute( "field", a_it.key() );
1969  aliasEntryElem.setAttribute( "index", idx );
1970  aliasEntryElem.setAttribute( "name", a_it.value() );
1971  aliasElem.appendChild( aliasEntryElem );
1972  }
1973  node.appendChild( aliasElem );
1974  }
1975 
1976  //exclude attributes WMS
1977  QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
1978  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
1979  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
1980  {
1981  QDomElement attrElem = doc.createElement( "attribute" );
1982  QDomText attrText = doc.createTextNode( *attWMSIt );
1983  attrElem.appendChild( attrText );
1984  excludeWMSElem.appendChild( attrElem );
1985  }
1986  node.appendChild( excludeWMSElem );
1987 
1988  //exclude attributes WFS
1989  QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
1990  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
1991  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
1992  {
1993  QDomElement attrElem = doc.createElement( "attribute" );
1994  QDomText attrText = doc.createTextNode( *attWFSIt );
1995  attrElem.appendChild( attrText );
1996  excludeWFSElem.appendChild( attrElem );
1997  }
1998  node.appendChild( excludeWFSElem );
1999 
2000  // tabs and groups of edit form
2001  if ( mAttributeEditorElements.size() > 0 )
2002  {
2003  QDomElement tabsElem = doc.createElement( "attributeEditorForm" );
2004 
2005  for ( QList< QgsAttributeEditorElement* >::const_iterator it = mAttributeEditorElements.begin(); it != mAttributeEditorElements.end(); ++it )
2006  {
2007  QDomElement attributeEditorWidgetElem = ( *it )->toDomElement( doc );
2008  tabsElem.appendChild( attributeEditorWidgetElem );
2009  }
2010 
2011  node.appendChild( tabsElem );
2012  }
2013 
2014  // add attribute actions
2015  mActions->writeXML( node, doc );
2016 
2017  return true;
2018 }
2019 
2020 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2021 {
2022  // get the Name element
2023  QDomElement nameElem = node.firstChildElement( "Name" );
2024  if ( nameElem.isNull() )
2025  {
2026  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
2027  }
2028 
2029  if ( hasGeometryType() )
2030  {
2031  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
2032  if ( !r )
2033  return false;
2034 
2035  setRendererV2( r );
2036 
2037  // labeling
2038  readSldLabeling( node );
2039  }
2040  return true;
2041 }
2042 
2043 
2044 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2045 {
2046  Q_UNUSED( errorMessage );
2047 
2048  // store the Name element
2049  QDomElement nameNode = doc.createElement( "se:Name" );
2050  nameNode.appendChild( doc.createTextNode( name() ) );
2051  node.appendChild( nameNode );
2052 
2053  if ( hasGeometryType() )
2054  {
2055  node.appendChild( mRendererV2->writeSld( doc, name() ) );
2056  }
2057  return true;
2058 }
2059 
2060 
2062 {
2063  if ( !mEditBuffer || !mDataProvider )
2064  {
2065  return false;
2066  }
2067 
2068  updateExtents();
2069 
2070  return mEditBuffer->changeGeometry( fid, geom );
2071 }
2072 
2073 
2074 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, QVariant value, bool emitSignal )
2075 {
2076  Q_UNUSED( emitSignal );
2077  return changeAttributeValue( fid, field, value );
2078 }
2079 
2080 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2081 {
2082  if ( !mEditBuffer || !mDataProvider )
2083  return false;
2084 
2085  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2086 }
2087 
2089 {
2090  if ( !mEditBuffer || !mDataProvider )
2091  return false;
2092 
2093  return mEditBuffer->addAttribute( field );
2094 }
2095 
2097 {
2098  if ( attIndex < 0 || attIndex >= pendingFields().count() )
2099  return;
2100 
2101  QString name = pendingFields()[ attIndex ].name();
2102  if ( mAttributeAliasMap.contains( name ) )
2103  {
2104  mAttributeAliasMap.remove( name );
2105  emit layerModified();
2106  }
2107 }
2108 
2109 void QgsVectorLayer::addAttributeAlias( int attIndex, QString aliasString )
2110 {
2111  if ( attIndex < 0 || attIndex >= pendingFields().count() )
2112  return;
2113 
2114  QString name = pendingFields()[ attIndex ].name();
2115 
2116  mAttributeAliasMap.insert( name, aliasString );
2117  emit layerModified(); // TODO[MD]: should have a different signal?
2118 }
2119 
2121 {
2122  mAttributeEditorElements.append( data );
2123 }
2124 
2125 const QString QgsVectorLayer::editorWidgetV2( int fieldIdx ) const
2126 {
2127  if ( fieldIdx < 0 || fieldIdx >= mUpdatedFields.count() )
2128  return "TextEdit";
2129 
2130  return mEditorWidgetV2Types.value( mUpdatedFields[fieldIdx].name(), "TextEdit" );
2131 }
2132 
2133 const QString QgsVectorLayer::editorWidgetV2( const QString& fieldName ) const
2134 {
2135  return mEditorWidgetV2Types.value( fieldName, "TextEdit" );
2136 }
2137 
2139 {
2140  return mEditorWidgetV2Configs.value( mUpdatedFields[fieldIdx].name() );
2141 }
2142 
2143 const QgsEditorWidgetConfig QgsVectorLayer::editorWidgetV2Config( const QString& fieldName ) const
2144 {
2145  return mEditorWidgetV2Configs.value( fieldName );
2146 }
2147 
2148 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2149 {
2150  if ( attributeIndex < 0 || attributeIndex >= pendingFields().count() )
2151  return "";
2152 
2153  QString name = pendingFields()[ attributeIndex ].name();
2154 
2155  return mAttributeAliasMap.value( name, "" );
2156 }
2157 
2158 QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
2159 {
2160  QString displayName = attributeAlias( attributeIndex );
2161  if ( displayName.isEmpty() )
2162  {
2163  const QgsFields& fields = pendingFields();
2164  if ( attributeIndex >= 0 && attributeIndex < fields.count() )
2165  {
2166  displayName = fields[attributeIndex].name();
2167  }
2168  }
2169  return displayName;
2170 }
2171 
2173 {
2174  if ( index < 0 || index >= pendingFields().count() )
2175  return false;
2176 
2177  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2178  {
2179  removeExpressionField( index );
2180  return true;
2181  }
2182 
2183  if ( !mEditBuffer || !mDataProvider )
2184  return false;
2185 
2186  return mEditBuffer->deleteAttribute( index );
2187 }
2188 
2189 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
2190 {
2191  bool deleted = false;
2192 
2193  // Remove multiple occurences of same attribute
2194  attrs = attrs.toSet().toList();
2195 
2196  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2197 
2198  Q_FOREACH ( int attr, attrs )
2199  {
2200  if ( deleteAttribute( attr ) )
2201  {
2202  deleted = true;
2203  }
2204  }
2205 
2206  return deleted;
2207 }
2208 
2210 {
2211  if ( !mEditBuffer )
2212  return false;
2213 
2214  bool res = mEditBuffer->deleteFeature( fid );
2215  if ( res )
2216  mSelectedFeatureIds.remove( fid ); // remove it from selection
2217 
2218  updateExtents();
2219 
2220  return res;
2221 }
2222 
2224 {
2225  return mUpdatedFields;
2226 }
2227 
2229 {
2230  return mUpdatedFields.allAttributesList();
2231 }
2232 
2234 {
2235  QgsAttributeList pkAttributesList;
2236 
2237  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2238  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2239  {
2240  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2241  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2242  pkAttributesList << i;
2243  }
2244 
2245  return pkAttributesList;
2246 }
2247 
2249 {
2250  return mDataProvider->featureCount() +
2251  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2252 }
2253 
2255 {
2256  mCommitErrors.clear();
2257 
2258  if ( !mDataProvider )
2259  {
2260  mCommitErrors << tr( "ERROR: no provider" );
2261  return false;
2262  }
2263 
2264  if ( !mEditBuffer )
2265  {
2266  mCommitErrors << tr( "ERROR: layer not editable" );
2267  return false;
2268  }
2269 
2270  emit beforeCommitChanges();
2271 
2272  bool success = mEditBuffer->commitChanges( mCommitErrors );
2273 
2274  if ( success )
2275  {
2276  delete mEditBuffer;
2277  mEditBuffer = 0;
2278  undoStack()->clear();
2279  emit editingStopped();
2280  }
2281  else
2282  {
2283  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2284  }
2285 
2286  if ( mCache )
2287  {
2288  mCache->deleteCachedGeometries();
2289  }
2290 
2291  updateFields();
2292  mDataProvider->updateExtents();
2293 
2294  emit repaintRequested();
2295 
2296  return success;
2297 }
2298 
2299 const QStringList &QgsVectorLayer::commitErrors()
2300 {
2301  return mCommitErrors;
2302 }
2303 
2304 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2305 {
2306  if ( !mEditBuffer )
2307  {
2308  return false;
2309  }
2310 
2311  emit beforeRollBack();
2312 
2313  mEditBuffer->rollBack();
2314 
2315  if ( isModified() )
2316  {
2317  // new undo stack roll back method
2318  // old method of calling every undo could cause many canvas refreshes
2319  undoStack()->setIndex( 0 );
2320  }
2321 
2322  updateFields();
2323 
2324  if ( deleteBuffer )
2325  {
2326  delete mEditBuffer;
2327  mEditBuffer = 0;
2328  undoStack()->clear();
2329  }
2330  emit editingStopped();
2331 
2332  if ( mCache )
2333  {
2334  mCache->deleteCachedGeometries();
2335  }
2336 
2337  emit repaintRequested();
2338  return true;
2339 }
2340 
2342 {
2343  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - ids;
2344 
2345  mSelectedFeatureIds = ids;
2346 
2347  emit selectionChanged( ids, deselectedFeatures, true );
2348 }
2349 
2351 {
2352  return mSelectedFeatureIds.size();
2353 }
2354 
2356 {
2357  return mSelectedFeatureIds;
2358 }
2359 
2361 {
2362  QgsFeatureList features;
2363  QgsFeature f;
2364 
2365  if ( mSelectedFeatureIds.count() <= 8 )
2366  {
2367  // for small amount of selected features, fetch them directly
2368  // because request with FilterFids would go iterate over the whole layer
2369  foreach ( int fid, mSelectedFeatureIds )
2370  {
2371  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2372  features << f;
2373  }
2374  }
2375  else
2376  {
2378 
2379  while ( it.nextFeature( f ) )
2380  {
2381  features.push_back( f );
2382  }
2383  }
2384 
2385  return features;
2386 }
2387 
2389 {
2390  if ( mSelectedFeatureIds.count() == 0 )
2391  return QgsFeatureIterator();
2392 
2393  if ( geometryType() == QGis::NoGeometry )
2395 
2396  if ( mSelectedFeatureIds.count() == 1 )
2397  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2398  else
2399  request.setFilterFids( mSelectedFeatureIds );
2400 
2401  return getFeatures( request );
2402 }
2403 
2404 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2405 {
2406  if ( !mEditBuffer || !mDataProvider )
2407  return false;
2408 
2409  bool res = mEditBuffer->addFeatures( features );
2410 
2411  if ( makeSelected )
2412  {
2413  QgsFeatureIds ids;
2414 
2415  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2416  ids << iter->id();
2417 
2418  setSelectedFeatures( ids );
2419  }
2420 
2421  updateExtents();
2422 
2423  return res;
2424 }
2425 
2426 
2427 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2428 {
2429  if ( !hasGeometryType() )
2430  return false;
2431 
2432  QMultiMap<double, QgsSnappingResult> snapResults;
2433  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2434 
2435  if ( result != 0 )
2436  {
2437  return false;
2438  }
2439 
2440  if ( snapResults.size() < 1 )
2441  {
2442  return false;
2443  }
2444 
2445  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
2446  point.setX( snap_it.value().snappedVertex.x() );
2447  point.setY( snap_it.value().snappedVertex.y() );
2448  return true;
2449 }
2450 
2451 
2452 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2453  QMultiMap<double, QgsSnappingResult>& snappingResults,
2454  QgsSnapper::SnappingType snap_to )
2455 {
2456  if ( !hasGeometryType() )
2457  return 1;
2458 
2459  if ( snappingTolerance <= 0 || !mDataProvider )
2460  {
2461  return 1;
2462  }
2463 
2464  QList<QgsFeature> featureList;
2465  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2466  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2467  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2468 
2469  int n = 0;
2470  QgsFeature f;
2471 
2472  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2473  {
2474  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2475  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2476  {
2477  QgsGeometry* g = &( it.value() );
2478  if ( g->boundingBox().intersects( searchRect ) )
2479  {
2480  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2481  ++n;
2482  }
2483  }
2484  }
2485  else
2486  {
2487  // snapping outside cached area
2488 
2490  .setFilterRect( searchRect )
2492  .setSubsetOfAttributes( QgsAttributeList() ) );
2493 
2494  while ( fit.nextFeature( f ) )
2495  {
2496  snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
2497  ++n;
2498  }
2499  }
2500 
2501  return n == 0 ? 2 : 0;
2502 }
2503 
2504 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2505  QgsFeatureId featureId,
2506  QgsGeometry* geom,
2507  double sqrSnappingTolerance,
2508  QMultiMap<double, QgsSnappingResult>& snappingResults,
2509  QgsSnapper::SnappingType snap_to ) const
2510 {
2511  if ( !geom )
2512  {
2513  return;
2514  }
2515 
2516  int atVertex, beforeVertex, afterVertex;
2517  double sqrDistVertexSnap, sqrDistSegmentSnap;
2518  QgsPoint snappedPoint;
2519  QgsSnappingResult snappingResultVertex;
2520  QgsSnappingResult snappingResultSegment;
2521 
2522  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2523  {
2524  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2525  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2526  {
2527  snappingResultVertex.snappedVertex = snappedPoint;
2528  snappingResultVertex.snappedVertexNr = atVertex;
2529  snappingResultVertex.beforeVertexNr = beforeVertex;
2530  if ( beforeVertex != -1 ) // make sure the vertex is valid
2531  {
2532  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2533  }
2534  snappingResultVertex.afterVertexNr = afterVertex;
2535  if ( afterVertex != -1 ) // make sure the vertex is valid
2536  {
2537  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2538  }
2539  snappingResultVertex.snappedAtGeometry = featureId;
2540  snappingResultVertex.layer = this;
2541  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2542  return;
2543  }
2544  }
2545  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2546  {
2547  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2548  {
2549  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, NULL, crs().geographicFlag() ? 1e-12 : 1e-8 );
2550 
2551  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2552  {
2553  snappingResultSegment.snappedVertex = snappedPoint;
2554  snappingResultSegment.snappedVertexNr = -1;
2555  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2556  snappingResultSegment.afterVertexNr = afterVertex;
2557  snappingResultSegment.snappedAtGeometry = featureId;
2558  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2559  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2560  snappingResultSegment.layer = this;
2561  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2562  }
2563  }
2564  }
2565 }
2566 
2567 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
2568 {
2569  QgsVectorLayerEditUtils utils( this );
2570  return utils.insertSegmentVerticesForSnap( snapResults );
2571 }
2572 
2573 
2575 {
2576  QgsDebugMsg( "----- Computing Coordinate System" );
2577 
2578  //
2579  // Get the layers project info and set up the QgsCoordinateTransform
2580  // for this layer
2581  //
2582 
2583  if ( hasGeometryType() )
2584  {
2585  // get CRS directly from provider
2586  setCrs( mDataProvider->crs() );
2587  }
2588  else
2589  {
2591  }
2592 }
2593 
2594 
2595 const QString QgsVectorLayer::displayField() const
2596 {
2597  return mDisplayField;
2598 }
2599 
2600 void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
2601 {
2602  mDisplayExpression = displayExpression;
2603 }
2604 
2606 {
2607  return mDisplayExpression;
2608 }
2609 
2611 {
2612  return ( mEditBuffer && mDataProvider );
2613 }
2614 
2616 {
2617  return mReadOnly;
2618 }
2619 
2620 bool QgsVectorLayer::setReadOnly( bool readonly )
2621 {
2622  // exit if the layer is in editing mode
2623  if ( readonly && mEditBuffer )
2624  return false;
2625 
2626  mReadOnly = readonly;
2627  return true;
2628 }
2629 
2631 {
2632  emit beforeModifiedCheck();
2633  return mEditBuffer && mEditBuffer->isModified();
2634 }
2635 
2637 {
2639  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
2641 }
2642 
2644 {
2646 
2648  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
2650 
2651  setEditorWidgetV2( idx, widgetType );
2652  setEditorWidgetV2Config( idx, cfg );
2653 }
2654 
2656 {
2657  return mEditorLayout;
2658 }
2659 
2661 {
2662  mEditorLayout = editorLayout;
2663 }
2664 
2665 void QgsVectorLayer::setEditorWidgetV2( int attrIdx, const QString& widgetType )
2666 {
2667  mEditorWidgetV2Types[ mUpdatedFields[ attrIdx ].name()] = widgetType;
2668 }
2669 
2671 {
2672  mEditorWidgetV2Configs[ mUpdatedFields[ attrIdx ].name()] = config;
2673 }
2674 
2676 {
2677  return mEditForm;
2678 }
2679 
2681 {
2682  if ( ui.isEmpty() || ui.isNull() )
2683  {
2685  }
2686  else
2687  {
2689  }
2690  mEditForm = ui;
2691 }
2692 
2693 void QgsVectorLayer::setAnnotationForm( const QString& ui )
2694 {
2695  mAnnotationForm = ui;
2696 }
2697 
2699 {
2700  return mEditFormInit;
2701 }
2702 
2703 void QgsVectorLayer::setEditFormInit( QString function )
2704 {
2705  mEditFormInit = function;
2706 }
2707 
2708 QMap< QString, QVariant > QgsVectorLayer::valueMap( int idx )
2709 {
2710  return editorWidgetV2Config( idx );
2711 }
2712 
2714 {
2715  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2716  return RangeData(
2717  cfg.value( "Min" ),
2718  cfg.value( "Max" ),
2719  cfg.value( "Step" )
2720  );
2721 }
2722 
2723 QString QgsVectorLayer::dateFormat( int idx )
2724 {
2725  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
2726 }
2727 
2729 {
2730  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2731  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
2732 }
2733 
2735 {
2736  const QgsFields &fields = pendingFields();
2737  if ( idx >= 0 && idx < fields.count() )
2738  {
2739  if ( mUpdatedFields.fieldOrigin( idx ) == QgsFields::OriginJoin
2740  || mUpdatedFields.fieldOrigin( idx ) == QgsFields::OriginExpression )
2741  return false;
2742  return mFieldEditables.value( fields[idx].name(), true );
2743  }
2744  else
2745  return true;
2746 }
2747 
2749 {
2750  const QgsFields &fields = pendingFields();
2751  if ( idx >= 0 && idx < fields.count() )
2752  return mLabelOnTop.value( fields[idx].name(), false );
2753  else
2754  return false;
2755 }
2756 
2757 void QgsVectorLayer::setFieldEditable( int idx, bool editable )
2758 {
2759  const QgsFields &fields = pendingFields();
2760  if ( idx >= 0 && idx < fields.count() )
2761  mFieldEditables[ fields[idx].name()] = editable;
2762 }
2763 
2764 void QgsVectorLayer::setLabelOnTop( int idx, bool onTop )
2765 {
2766  const QgsFields &fields = pendingFields();
2767  if ( idx >= 0 && idx < fields.count() )
2768  mLabelOnTop[ fields[idx].name()] = onTop;
2769 }
2770 
2772 {
2773  return mRendererV2;
2774 }
2775 
2777 {
2778  if ( !hasGeometryType() )
2779  return;
2780 
2781  if ( r != mRendererV2 )
2782  {
2783  delete mRendererV2;
2784  mRendererV2 = r;
2785  mSymbolFeatureCounted = false;
2786  mSymbolFeatureCountMap.clear();
2787 
2788  emit rendererChanged();
2789  }
2790 }
2791 
2792 
2793 
2795 {
2796  if ( !mDataProvider )
2797  {
2798  return;
2799  }
2800  if ( !mDataProvider->transaction() )
2801  {
2802  undoStack()->beginMacro( text );
2803  emit editCommandStarted( text );
2804  }
2805 }
2806 
2808 {
2809  if ( !mDataProvider )
2810  {
2811  return;
2812  }
2813  if ( !mDataProvider->transaction() )
2814  {
2815  undoStack()->endMacro();
2816  emit editCommandEnded();
2817  }
2818 }
2819 
2821 {
2822  if ( !mDataProvider )
2823  {
2824  return;
2825  }
2826  if ( !mDataProvider->transaction() )
2827  {
2828  undoStack()->endMacro();
2829  undoStack()->undo();
2830  emit editCommandDestroyed();
2831  }
2832 }
2833 
2834 
2835 void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
2836 {
2838  cfg["CheckedState"] = checked;
2839  cfg["UncheckedState"] = unchecked;
2840  setEditorWidgetV2Config( idx, cfg );
2841 }
2842 
2843 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
2844 {
2845  return pendingFields().fieldNameIndex( fieldName );
2846 }
2847 
2849 {
2850  return mJoinBuffer->addJoin( joinInfo );
2851 }
2852 
2853 void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
2854 {
2855  removeJoin( theLayerId );
2856 }
2857 
2858 void QgsVectorLayer::removeJoin( const QString& joinLayerId )
2859 {
2860  mJoinBuffer->removeJoin( joinLayerId );
2861 }
2862 
2863 const QList< QgsVectorJoinInfo >& QgsVectorLayer::vectorJoins() const
2864 {
2865  return mJoinBuffer->vectorJoins();
2866 }
2867 
2868 int QgsVectorLayer::addExpressionField( const QString& exp, const QgsField& fld )
2869 {
2870  mExpressionFieldBuffer->addExpression( exp, fld );
2871  updateFields();
2872  int idx = mUpdatedFields.indexFromName( fld.name() );
2873  emit attributeAdded( idx );
2874  return idx;
2875 }
2876 
2878 {
2879  int oi = mUpdatedFields.fieldOriginIndex( index );
2880  mExpressionFieldBuffer->removeExpression( oi );
2881  updateFields();
2882  emit attributeDeleted( index );
2883 }
2884 
2886 {
2887  int oi = mUpdatedFields.fieldOriginIndex( index );
2888  return mExpressionFieldBuffer->expressions().value( oi ).expression;
2889 }
2890 
2891 void QgsVectorLayer::updateExpressionField( int index, const QString& exp )
2892 {
2893  int oi = mUpdatedFields.fieldOriginIndex( index );
2894  mExpressionFieldBuffer->updateExpression( oi, exp );
2895 }
2896 
2898 {
2899  if ( !mDataProvider )
2900  return;
2901 
2902  QgsFields oldFields = mUpdatedFields;
2903 
2904  mUpdatedFields = mDataProvider->fields();
2905 
2906  // added / removed fields
2907  if ( mEditBuffer )
2908  mEditBuffer->updateFields( mUpdatedFields );
2909 
2910  // joined fields
2911  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
2912  mJoinBuffer->updateFields( mUpdatedFields );
2913 
2914  if ( mExpressionFieldBuffer )
2915  mExpressionFieldBuffer->updateFields( mUpdatedFields );
2916 
2917  if ( oldFields != mUpdatedFields )
2918  emit updatedFields();
2919 }
2920 
2921 
2923 {
2924  if ( mJoinBuffer->containsJoins() )
2925  {
2926  mJoinBuffer->createJoinCaches();
2927  }
2928 }
2929 
2930 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
2931 {
2932  uniqueValues.clear();
2933  if ( !mDataProvider )
2934  {
2935  return;
2936  }
2937 
2938  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
2939 
2940  if ( origin == QgsFields::OriginProvider ) //a provider field
2941  {
2942  mDataProvider->uniqueValues( index, uniqueValues, limit );
2943 
2944  if ( mEditBuffer )
2945  {
2946  QSet<QString> vals;
2947  Q_FOREACH ( const QVariant& v, uniqueValues )
2948  {
2949  vals << v.toString();
2950  }
2951 
2952  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
2953  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
2954  {
2955  it.next();
2956  QVariant v = it.value().value( index );
2957  if ( v.isValid() )
2958  {
2959  QString vs = v.toString();
2960  if ( !vals.contains( vs ) )
2961  {
2962  vals << vs;
2963  uniqueValues << v;
2964  }
2965  }
2966  }
2967  }
2968 
2969  return;
2970  }
2971  else if ( origin == QgsFields::OriginJoin )
2972  {
2973  int sourceLayerIndex;
2974  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
2975  Q_ASSERT( join );
2976 
2978 
2979  if ( vl )
2980  vl->dataProvider()->uniqueValues( sourceLayerIndex, uniqueValues, limit );
2981 
2982  return;
2983  }
2984  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
2985  {
2986  // the layer is editable, but in certain cases it can still be avoided going through all features
2987  if ( origin == QgsFields::OriginEdit && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mAddedFeatures.isEmpty() && !mEditBuffer->mDeletedAttributeIds.contains( index ) && mEditBuffer->mChangedAttributeValues.isEmpty() )
2988  {
2989  mDataProvider->uniqueValues( index, uniqueValues, limit );
2990  return;
2991  }
2992 
2993  // we need to go through each feature
2994  QgsAttributeList attList;
2995  attList << index;
2996 
2998  .setFlags( QgsFeatureRequest::NoGeometry )
2999  .setSubsetOfAttributes( attList ) );
3000 
3001  QgsFeature f;
3002  QVariant currentValue;
3003  QHash<QString, QVariant> val;
3004  while ( fit.nextFeature( f ) )
3005  {
3006  currentValue = f.attribute( index );
3007  val.insert( currentValue.toString(), currentValue );
3008  if ( limit >= 0 && val.size() >= limit )
3009  {
3010  break;
3011  }
3012  }
3013 
3014  uniqueValues = val.values();
3015  return;
3016  }
3017 
3018  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3019 }
3020 
3022 {
3023  if ( !mDataProvider )
3024  {
3025  return QVariant();
3026  }
3027 
3028  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3029 
3030  if ( origin == QgsFields::OriginProvider ) //a provider field
3031  {
3032  return mDataProvider->minimumValue( index );
3033  }
3034  else if ( origin == QgsFields::OriginJoin )
3035  {
3036  int sourceLayerIndex;
3037  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
3038  Q_ASSERT( join );
3039 
3041  Q_ASSERT( vl );
3042 
3043  return vl->minimumValue( sourceLayerIndex );
3044  }
3045  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
3046  {
3047  // the layer is editable, but in certain cases it can still be avoided going through all features
3048  if ( origin == QgsFields::OriginEdit &&
3049  mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3050  mEditBuffer->mAddedFeatures.isEmpty() && !
3051  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3052  mEditBuffer->mChangedAttributeValues.isEmpty() )
3053  {
3054  return mDataProvider->minimumValue( index );
3055  }
3056 
3057  // we need to go through each feature
3058  QgsAttributeList attList;
3059  attList << index;
3060 
3062  .setFlags( QgsFeatureRequest::NoGeometry )
3063  .setSubsetOfAttributes( attList ) );
3064 
3065  QgsFeature f;
3067  double currentValue = 0;
3068  while ( fit.nextFeature( f ) )
3069  {
3070  currentValue = f.attribute( index ).toDouble();
3071  if ( currentValue < minimumValue )
3072  {
3073  minimumValue = currentValue;
3074  }
3075  }
3076  return QVariant( minimumValue );
3077  }
3078 
3079  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
3080  return QVariant();
3081 }
3082 
3084 {
3085  if ( !mDataProvider )
3086  {
3087  return QVariant();
3088  }
3089 
3090  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3091 
3092  if ( origin == QgsFields::OriginProvider ) //a provider field
3093  {
3094  return mDataProvider->maximumValue( index );
3095  }
3096  else if ( origin == QgsFields::OriginJoin )
3097  {
3098  int sourceLayerIndex;
3099  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
3100  Q_ASSERT( join );
3101 
3103  Q_ASSERT( vl );
3104 
3105  return vl->maximumValue( sourceLayerIndex );
3106  }
3107  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
3108  {
3109  // the layer is editable, but in certain cases it can still be avoided going through all features
3110  if ( origin == QgsFields::OriginEdit &&
3111  mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3112  mEditBuffer->mAddedFeatures.isEmpty() &&
3113  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3114  mEditBuffer->mChangedAttributeValues.isEmpty() )
3115  {
3116  return mDataProvider->maximumValue( index );
3117  }
3118 
3119  // we need to go through each feature
3120  QgsAttributeList attList;
3121  attList << index;
3122 
3124  .setFlags( QgsFeatureRequest::NoGeometry )
3125  .setSubsetOfAttributes( attList ) );
3126 
3127  QgsFeature f;
3129  double currentValue = 0;
3130  while ( fit.nextFeature( f ) )
3131  {
3132  currentValue = f.attribute( index ).toDouble();
3133  if ( currentValue > maximumValue )
3134  {
3135  maximumValue = currentValue;
3136  }
3137  }
3138  return QVariant( maximumValue );
3139  }
3140 
3141  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3142  return QVariant();
3143 }
3144 
3146 void QgsVectorLayer::setFeatureBlendMode( const QPainter::CompositionMode &featureBlendMode )
3147 {
3148  mFeatureBlendMode = featureBlendMode;
3149  emit featureBlendModeChanged( featureBlendMode );
3150 }
3151 
3153 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3154 {
3155  return mFeatureBlendMode;
3156 }
3157 
3159 void QgsVectorLayer::setLayerTransparency( int layerTransparency )
3160 {
3161  mLayerTransparency = layerTransparency;
3162  emit layerTransparencyChanged( layerTransparency );
3163 }
3164 
3167 {
3168  return mLayerTransparency;
3169 }
3170 
3171 
3172 
3173 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3174 {
3175  QDomElement element = node.toElement();
3176  if ( element.isNull() )
3177  return;
3178 
3179  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3180  if ( userStyleElem.isNull() )
3181  {
3182  QgsDebugMsg( "Info: UserStyle element not found." );
3183  return;
3184  }
3185 
3186  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3187  if ( featureTypeStyleElem.isNull() )
3188  {
3189  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3190  return;
3191  }
3192 
3193  // use last rule
3194  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3195  if ( ruleElem.isNull() )
3196  {
3197  QgsDebugMsg( "Info: Rule element not found." );
3198  return;
3199  }
3200 
3201  // use last text symbolizer
3202  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3203  if ( textSymbolizerElem.isNull() )
3204  {
3205  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3206  return;
3207  }
3208 
3209  // Label
3210  setCustomProperty( "labeling/enabled", false );
3211  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3212  if ( !labelElem.isNull() )
3213  {
3214  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3215  if ( !propertyNameElem.isNull() )
3216  {
3217  // enable labeling
3218  setCustomProperty( "labeling", "pal" );
3219  setCustomProperty( "labeling/enabled", true );
3220 
3221  // set labeling defaults
3222  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3223  setCustomProperty( "labeling/fontItalic", false );
3224  setCustomProperty( "labeling/fontSize", 10 );
3225  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3226  setCustomProperty( "labeling/fontBold", false );
3227  setCustomProperty( "labeling/fontUnderline", false );
3228  setCustomProperty( "labeling/textColorR", 0 );
3229  setCustomProperty( "labeling/textColorG", 0 );
3230  setCustomProperty( "labeling/textColorB", 0 );
3231  setCustomProperty( "labeling/textTransp", 0 );
3232  setCustomProperty( "labeling/bufferDraw", false );
3233  setCustomProperty( "labeling/bufferSize", 1 );
3234  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3235  setCustomProperty( "labeling/bufferColorR", 255 );
3236  setCustomProperty( "labeling/bufferColorG", 255 );
3237  setCustomProperty( "labeling/bufferColorB", 255 );
3238  setCustomProperty( "labeling/bufferTransp", 0 );
3239  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3240  setCustomProperty( "labeling/xOffset", 0 );
3241  setCustomProperty( "labeling/yOffset", 0 );
3242  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3243  setCustomProperty( "labeling/angleOffset", 0 );
3244 
3245  // label attribute
3246  QString labelAttribute = propertyNameElem.text();
3247  setCustomProperty( "labeling/fieldName", labelAttribute );
3248  setCustomProperty( "labeling/isExpression", false );
3249 
3250  int fieldIndex = fieldNameIndex( labelAttribute );
3251  if ( fieldIndex == -1 )
3252  {
3253  // label attribute is not in columns, check if it is an expression
3254  QgsExpression exp( labelAttribute );
3255  if ( !exp.hasEvalError() )
3256  {
3257  setCustomProperty( "labeling/isExpression", true );
3258  }
3259  else
3260  {
3261  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3262  }
3263  }
3264  }
3265  else
3266  {
3267  QgsDebugMsg( "Info: PropertyName element not found." );
3268  return;
3269  }
3270  }
3271  else
3272  {
3273  QgsDebugMsg( "Info: Label element not found." );
3274  return;
3275  }
3276 
3277  // Font
3278  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3279  if ( !fontElem.isNull() )
3280  {
3281  QString cssName;
3282  QString elemText;
3283  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3284  while ( !cssElem.isNull() )
3285  {
3286  cssName = cssElem.attribute( "name", "not_found" );
3287  if ( cssName != "not_found" )
3288  {
3289  elemText = cssElem.text();
3290  if ( cssName == "font-family" )
3291  {
3292  setCustomProperty( "labeling/fontFamily", elemText );
3293  }
3294  else if ( cssName == "font-style" )
3295  {
3296  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3297  }
3298  else if ( cssName == "font-size" )
3299  {
3300  bool ok;
3301  int fontSize = elemText.toInt( &ok );
3302  if ( ok )
3303  {
3304  setCustomProperty( "labeling/fontSize", fontSize );
3305  }
3306  }
3307  else if ( cssName == "font-weight" )
3308  {
3309  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3310  }
3311  else if ( cssName == "font-underline" )
3312  {
3313  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3314  }
3315  }
3316 
3317  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3318  }
3319  }
3320 
3321  // Fill
3322  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3323  if ( textColor.isValid() )
3324  {
3325  setCustomProperty( "labeling/textColorR", textColor.red() );
3326  setCustomProperty( "labeling/textColorG", textColor.green() );
3327  setCustomProperty( "labeling/textColorB", textColor.blue() );
3328  setCustomProperty( "labeling/textTransp", 100 - ( int )( 100 * textColor.alphaF() ) );
3329  }
3330 
3331  // Halo
3332  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3333  if ( !haloElem.isNull() )
3334  {
3335  setCustomProperty( "labeling/bufferDraw", true );
3336  setCustomProperty( "labeling/bufferSize", 1 );
3337 
3338  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3339  if ( !radiusElem.isNull() )
3340  {
3341  bool ok;
3342  double bufferSize = radiusElem.text().toDouble( &ok );
3343  if ( ok )
3344  {
3345  setCustomProperty( "labeling/bufferSize", bufferSize );
3346  }
3347  }
3348 
3349  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3350  if ( bufferColor.isValid() )
3351  {
3352  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3353  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3354  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3355  setCustomProperty( "labeling/bufferTransp", 100 - ( int )( 100 * bufferColor.alphaF() ) );
3356  }
3357  }
3358 
3359  // LabelPlacement
3360  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3361  if ( !labelPlacementElem.isNull() )
3362  {
3363  // PointPlacement
3364  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3365  if ( !pointPlacementElem.isNull() )
3366  {
3367  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3368 
3369  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3370  if ( !displacementElem.isNull() )
3371  {
3372  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3373  if ( !displacementXElem.isNull() )
3374  {
3375  bool ok;
3376  double xOffset = displacementXElem.text().toDouble( &ok );
3377  if ( ok )
3378  {
3379  setCustomProperty( "labeling/xOffset", xOffset );
3380  }
3381  }
3382  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3383  if ( !displacementYElem.isNull() )
3384  {
3385  bool ok;
3386  double yOffset = displacementYElem.text().toDouble( &ok );
3387  if ( ok )
3388  {
3389  setCustomProperty( "labeling/yOffset", yOffset );
3390  }
3391  }
3392  }
3393 
3394  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
3395  if ( !rotationElem.isNull() )
3396  {
3397  bool ok;
3398  double rotation = rotationElem.text().toDouble( &ok );
3399  if ( ok )
3400  {
3401  setCustomProperty( "labeling/angleOffset", rotation );
3402  }
3403  }
3404  }
3405  }
3406 }
3407 
3409 {
3410  if ( !mDiagramLayerSettings )
3411  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3412  *mDiagramLayerSettings = s;
3413 }
3414 
3416 {
3417  QString myMetadata = "<html><body>";
3418 
3419  //-------------
3420 
3421  myMetadata += "<p class=\"subheaderglossy\">";
3422  myMetadata += tr( "General" );
3423  myMetadata += "</p>\n";
3424 
3425  // data comment
3426  if ( !( dataComment().isEmpty() ) )
3427  {
3428  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
3429  myMetadata += "<p>";
3430  myMetadata += dataComment();
3431  myMetadata += "</p>\n";
3432  }
3433 
3434  //storage type
3435  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
3436  myMetadata += "<p>";
3437  myMetadata += storageType();
3438  myMetadata += "</p>\n";
3439 
3440  if ( dataProvider() )
3441  {
3442  //provider description
3443  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
3444  myMetadata += "<p>";
3445  myMetadata += dataProvider()->description().replace( "\n", "<br>" );
3446  myMetadata += "</p>\n";
3447  }
3448 
3449  // data source
3450  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
3451  myMetadata += "<p>";
3452  myMetadata += publicSource();
3453  myMetadata += "</p>\n";
3454 
3455  //geom type
3456 
3458 
3459  if ( type < 0 || type > QGis::NoGeometry )
3460  {
3461  QgsDebugMsg( "Invalid vector type" );
3462  }
3463  else
3464  {
3465  QString typeString( QGis::vectorGeometryType( geometryType() ) );
3466 
3467  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
3468  myMetadata += "<p>";
3469  myMetadata += typeString;
3470  myMetadata += "</p>\n";
3471  }
3472 
3474  if ( !pkAttrList.isEmpty() )
3475  {
3476  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
3477  myMetadata += "<p>";
3478  foreach ( int idx, pkAttrList )
3479  {
3480  myMetadata += pendingFields()[ idx ].name() + " ";
3481  }
3482  myMetadata += "</p>\n";
3483  }
3484 
3485 
3486  //feature count
3487  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
3488  myMetadata += "<p>";
3489  myMetadata += QString::number( featureCount() );
3490  myMetadata += "</p>\n";
3491  //capabilities
3492  myMetadata += "<p class=\"glossy\">" + tr( "Editing capabilities of this layer" ) + "</p>\n";
3493  myMetadata += "<p>";
3494  myMetadata += capabilitiesString();
3495  myMetadata += "</p>\n";
3496 
3497  //-------------
3498 
3499  QgsRectangle myExtent = extent();
3500  myMetadata += "<p class=\"subheaderglossy\">";
3501  myMetadata += tr( "Extents" );
3502  myMetadata += "</p>\n";
3503 
3504  //extents in layer cs TODO...maybe make a little nested table to improve layout...
3505  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
3506  myMetadata += "<p>";
3507  // Try to be a bit clever over what number format we use for the
3508  // extents. Some people don't like it using scientific notation when the
3509  // numbers get large, but for small numbers this is the more practical
3510  // option (so we can't force the format to 'f' for all values).
3511  // The scheme:
3512  // - for all numbers with more than 5 digits, force non-scientific notation
3513  // and 2 digits after the decimal point.
3514  // - for all smaller numbers let the OS decide which format to use (it will
3515  // generally use non-scientific unless the number gets much less than 1).
3516 
3517  if ( !myExtent.isEmpty() )
3518  {
3519  QString xMin, yMin, xMax, yMax;
3520  double changeoverValue = 99999; // The 'largest' 5 digit number
3521  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
3522  {
3523  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
3524  }
3525  else
3526  {
3527  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
3528  }
3529  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
3530  {
3531  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
3532  }
3533  else
3534  {
3535  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
3536  }
3537  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
3538  {
3539  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
3540  }
3541  else
3542  {
3543  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
3544  }
3545  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
3546  {
3547  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
3548  }
3549  else
3550  {
3551  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
3552  }
3553 
3554  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3555  .arg( xMin ).arg( yMin ).arg( xMax ).arg( yMax );
3556  }
3557  else
3558  {
3559  myMetadata += tr( "unknown extent" );
3560  }
3561 
3562  myMetadata += "</p>\n";
3563 
3564  //extents in project cs
3565 
3566  try
3567  {
3568 #if 0
3569  // TODO: currently disabled, will revisit later [MD]
3570  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
3571  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3572  myMetadata += "<p>";
3573  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3574  .arg( myProjectedExtent.xMinimum() )
3575  .arg( myProjectedExtent.yMinimum() )
3576  .arg( myProjectedExtent.xMaximum() )
3577  .arg( myProjectedExtent.yMaximum() );
3578  myMetadata += "</p>\n";
3579 #endif
3580 
3581  //
3582  // Display layer spatial ref system
3583  //
3584  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
3585  myMetadata += "<p>";
3586  myMetadata += crs().toProj4().replace( QRegExp( "\"" ), " \"" );
3587  myMetadata += "</p>\n";
3588 
3589  //
3590  // Display project (output) spatial ref system
3591  //
3592 #if 0
3593  // TODO: disabled for now, will revisit later [MD]
3594  //myMetadata += "<tr><td bgcolor=\"gray\">";
3595  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
3596  myMetadata += "<p>";
3597  myMetadata += coordinateTransform->destCRS().toProj4().replace( QRegExp( "\"" ), " \"" );
3598  myMetadata += "</p>\n";
3599 #endif
3600  }
3601  catch ( QgsCsException &cse )
3602  {
3603  Q_UNUSED( cse );
3604  QgsDebugMsg( cse.what() );
3605 
3606  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3607  myMetadata += "<p>";
3608  myMetadata += tr( "(Invalid transformation of layer extents)" );
3609  myMetadata += "</p>\n";
3610 
3611  }
3612 
3613 #if 0
3614  //
3615  // Add the info about each field in the attribute table
3616  //
3617  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
3618  myMetadata += "<p>";
3619 
3620  // Start a nested table in this trow
3621  myMetadata += "<table width=\"100%\">";
3622  myMetadata += "<tr><th>";
3623  myMetadata += tr( "Field" );
3624  myMetadata += "</th>";
3625  myMetadata += "<th>";
3626  myMetadata += tr( "Type" );
3627  myMetadata += "</th>";
3628  myMetadata += "<th>";
3629  myMetadata += tr( "Length" );
3630  myMetadata += "</th>";
3631  myMetadata += "<th>";
3632  myMetadata += tr( "Precision" );
3633  myMetadata += "</th>";
3634  myMetadata += "<th>";
3635  myMetadata += tr( "Comment" );
3636  myMetadata += "</th>";
3637 
3638  //get info for each field by looping through them
3639  const QgsFields& myFields = pendingFields();
3640  for ( int i = 0, n = myFields.size(); i < n; ++i )
3641  {
3642  const QgsField& myField = fields[i];
3643 
3644  myMetadata += "<tr><td>";
3645  myMetadata += myField.name();
3646  myMetadata += "</td>";
3647  myMetadata += "<td>";
3648  myMetadata += myField.typeName();
3649  myMetadata += "</td>";
3650  myMetadata += "<td>";
3651  myMetadata += QString( "%1" ).arg( myField.length() );
3652  myMetadata += "</td>";
3653  myMetadata += "<td>";
3654  myMetadata += QString( "%1" ).arg( myField.precision() );
3655  myMetadata += "</td>";
3656  myMetadata += "<td>";
3657  myMetadata += QString( "%1" ).arg( myField.comment() );
3658  myMetadata += "</td></tr>";
3659  }
3660 
3661  //close field list
3662  myMetadata += "</table>"; //end of nested table
3663 #endif
3664 
3665  myMetadata += "</body></html>";
3666  return myMetadata;
3667 }
3668 
3670 {
3671  mSymbolFeatureCounted = false;
3672 }
3673 
3674 void QgsVectorLayer::onRelationsLoaded()
3675 {
3676  Q_FOREACH ( QgsAttributeEditorElement* elem, mAttributeEditorElements )
3677  {
3679  {
3680  QgsAttributeEditorContainer* cont = dynamic_cast< QgsAttributeEditorContainer* >( elem );
3681  if ( !cont )
3682  continue;
3683 
3684  QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
3685  Q_FOREACH ( QgsAttributeEditorElement* relElem, relations )
3686  {
3687  QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
3688  if ( !rel )
3689  continue;
3690 
3691  rel->init( QgsProject::instance()->relationManager() );
3692  }
3693  }
3694  }
3695 }
3696 
3697 void QgsVectorLayer::onJoinedFieldsChanged()
3698 {
3699  // some of the fields of joined layers have changed -> we need to update this layer's fields too
3700  updateFields();
3701 }
3702 
3704 {
3705  if ( editorWidgetV2( idx ) == "ValueRelation" )
3706  {
3708 
3709  return ValueRelationData( cfg.value( "Layer" ).toString(),
3710  cfg.value( "Key" ).toString(),
3711  cfg.value( "Value" ).toString(),
3712  cfg.value( "AllowNull" ).toBool(),
3713  cfg.value( "OrderByValue" ).toBool(),
3714  cfg.value( "AllowMulti" ).toBool(),
3715  cfg.value( "FilterExpression" ).toString()
3716  );
3717  }
3718  else
3719  {
3720  return ValueRelationData();
3721  }
3722 }
3723 
3724 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx )
3725 {
3726  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
3727 }
3728 
3729 QList<QgsAttributeEditorElement*> &QgsVectorLayer::attributeEditorElements()
3730 {
3731  return mAttributeEditorElements;
3732 }
3733 
3735 {
3736  mAttributeEditorElements.clear();
3737 }
3738 
3739 QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
3740 {
3741  QDomElement elem = doc.createElement( "attributeEditorContainer" );
3742  elem.setAttribute( "name", mName );
3743 
3744  Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
3745  {
3746  elem.appendChild( child->toDomElement( doc ) );
3747  }
3748  return elem;
3749 }
3750 
3752 {
3753  mChildren.append( widget );
3754 }
3755 
3757 {
3758  QList<QgsAttributeEditorElement*> results;
3759 
3760  Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
3761  {
3762  if ( elem->type() == type )
3763  {
3764  results.append( elem );
3765  }
3766 
3767  if ( elem->type() == AeTypeContainer )
3768  {
3769  QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
3770  if ( cont )
3771  results += cont->findElements( type );
3772  }
3773  }
3774 
3775  return results;
3776 }
3777 
3778 QDomElement QgsAttributeEditorField::toDomElement( QDomDocument& doc ) const
3779 {
3780  QDomElement elem = doc.createElement( "attributeEditorField" );
3781  elem.setAttribute( "name", mName );
3782  elem.setAttribute( "index", mIdx );
3783  return elem;
3784 }
3785 
3786 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
3787 {
3789  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3790  if ( !myLib )
3791  {
3792  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3793  return -1;
3794  }
3795  listStyles_t* listStylesExternalMethod = ( listStyles_t * ) cast_to_fptr( myLib->resolve( "listStyles" ) );
3796 
3797  if ( !listStylesExternalMethod )
3798  {
3799  delete myLib;
3800  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "listStyles" );
3801  return -1;
3802  }
3803 
3804  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
3805 }
3806 
3807 QString QgsVectorLayer::getStyleFromDatabase( QString styleId, QString &msgError )
3808 {
3810  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3811  if ( !myLib )
3812  {
3813  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3814  return QObject::tr( "" );
3815  }
3816  getStyleById_t* getStyleByIdMethod = ( getStyleById_t * ) cast_to_fptr( myLib->resolve( "getStyleById" ) );
3817 
3818  if ( !getStyleByIdMethod )
3819  {
3820  delete myLib;
3821  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "getStyleById" );
3822  return QObject::tr( "" );
3823  }
3824 
3825  return getStyleByIdMethod( mDataSource, styleId, msgError );
3826 }
3827 
3828 
3829 void QgsVectorLayer::saveStyleToDatabase( QString name, QString description,
3830  bool useAsDefault, QString uiFileContent, QString &msgError )
3831 {
3832 
3833  QString sldStyle, qmlStyle;
3835  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3836  if ( !myLib )
3837  {
3838  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3839  return;
3840  }
3841  saveStyle_t* saveStyleExternalMethod = ( saveStyle_t * ) cast_to_fptr( myLib->resolve( "saveStyle" ) );
3842 
3843  if ( !saveStyleExternalMethod )
3844  {
3845  delete myLib;
3846  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "saveStyle" );
3847  return;
3848  }
3849 
3850  QDomDocument qmlDocument, sldDocument;
3851  this->exportNamedStyle( qmlDocument, msgError );
3852  if ( !msgError.isNull() )
3853  {
3854  return;
3855  }
3856  qmlStyle = qmlDocument.toString();
3857 
3858  this->exportSldStyle( sldDocument, msgError );
3859  if ( !msgError.isNull() )
3860  {
3861  return;
3862  }
3863  sldStyle = sldDocument.toString();
3864 
3865  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
3866  description, uiFileContent, useAsDefault, msgError );
3867 }
3868 
3869 
3870 
3871 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
3872 {
3873  return loadNamedStyle( theURI, theResultFlag, false );
3874 }
3875 
3876 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
3877 {
3878  QgsDataSourceURI dsUri( theURI );
3879  if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
3880  {
3882  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3883  if ( myLib )
3884  {
3885  loadStyle_t* loadStyleExternalMethod = ( loadStyle_t * ) cast_to_fptr( myLib->resolve( "loadStyle" ) );
3886  if ( loadStyleExternalMethod )
3887  {
3888  QString qml, errorMsg;
3889  qml = loadStyleExternalMethod( mDataSource, errorMsg );
3890  if ( !qml.isEmpty() )
3891  {
3892  theResultFlag = this->applyNamedStyle( qml, errorMsg );
3893  return QObject::tr( "Loaded from Provider" );
3894  }
3895  }
3896  }
3897  }
3898 
3899  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
3900 }
3901 
3902 bool QgsVectorLayer::applyNamedStyle( QString namedStyle, QString& errorMsg )
3903 {
3904  QDomDocument myDocument( "qgis" );
3905  myDocument.setContent( namedStyle );
3906 
3907  return importNamedStyle( myDocument, errorMsg );
3908 }
3909 
3910 
3911 QDomElement QgsAttributeEditorRelation::toDomElement( QDomDocument& doc ) const
3912 {
3913  QDomElement elem = doc.createElement( "attributeEditorRelation" );
3914  elem.setAttribute( "name", mName );
3915  elem.setAttribute( "relation", mRelation.id() );
3916  return elem;
3917 }
3918 
3920 {
3921  mRelation = relationManager->relation( mRelationId );
3922  return mRelation.isValid();
3923 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
bool deleteVertex(QgsFeatureId atFeatureId, int atVertex)
Deletes a vertex from a feature.
void setExtent(const QgsRectangle &rect) override
Set the extent.
bool draw(QgsRenderContext &rendererContext) override
Draws the layer.
virtual QString subsetString()
Get the string (typically sql) used to define a subset of the layer.
const QgsEditorWidgetConfig editorWidgetV2Config(int fieldIdx) const
Get the configuration for the editor widget used to represent the field at the given index...
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:86
void updateFields()
Assembles mUpdatedFields considering provider fields, joined fields and added fields.
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:59
const QList< QgsVectorJoinInfo > & vectorJoins() const
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:315
bool isValid() const
Returns the validity of this relation.
void selectAll()
Select all the features.
QString database() const
bool intersects(const QgsRectangle &rect) const
returns true when rectangle intersects with other rectangle
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
#define RENDERER_TAG_NAME
Definition: qgsrendererv2.h:48
static unsigned index
virtual QString subsetString()
Returns the subset definition string (typically sql) currently in use by the layer and used by the pr...
bool fieldEditable(int idx)
is edit widget editable
bool addJoin(const QgsVectorJoinInfo &joinInfo)
Joins another vector layer to this layer.
virtual QString getStyleFromDatabase(QString styleId, QString &msgError)
Will return the named style corresponding to style id provided.
virtual bool willRenderFeature(QgsFeature &feat)
return whether the renderer will render a feature or not.
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.
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
bool isEmpty() const
test if rectangle is empty.
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.
float threshold() const
Gets the simplification threshold of the vector layer managed.
void clearAttributeEditorWidgets()
Clears all the tabs for the attribute editor form.
QgsFeatureList selectedFeatures()
Get a copy of the user-selected features.
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:92
virtual bool addAttribute(const QgsField &field)
add an attribute field (but does not commit it) returns true if the field was added ...
virtual bool writeXml(QDomNode &layer_node, QDomDocument &doc) override
write vector layer specific state to project file Dom node.
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.
int makeDifference(QgsGeometry *other)
Changes this geometry such that it does not intersect the other geometry.
EditorLayout editorLayout()
get the active layout for the attribute editor for this layer
virtual void saveStyleToDatabase(QString name, QString description, bool useAsDefault, QString uiFileContent, QString &msgError)
Save named and sld style of the layer to the style table in the db.
void createJoinCaches()
Calls cacheJoinLayer() for all vector joins.
virtual void updateExtents()
Update the extents of the layer.
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith="")
Read custom properties from project file.
void addExpression(const QString &exp, const QgsField &fld)
Add an expression to the buffer.
QList< QgsSymbolV2 * > QgsSymbolV2List
Definition: qgsrendererv2.h:39
void removeJoin(const QString &joinLayerId)
Removes a vector layer join.
QString publicSource() const
void beforeRollBack()
Is emitted, before changes are rolled back.
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
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 setEditFormInit(QString function)
set python function for edit form initialization
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 int removePolygonIntersections(QgsGeometry *geom, QgsFeatureIds ignoreFeatures=QgsFeatureIds())
Changes the specified geometry such that it has no intersections with other polygon (or multipolygon)...
virtual bool addFeature(QgsFeature &f)
Adds a feature.
static QgsProviderRegistry * instance(QString pluginPath=QString::null)
means of accessing canonical single instance
void layerTransparencyChanged(int layerTransparency)
Signal emitted when setLayerTransparency() is called.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:188
bool deleteFeature(QgsFeatureId fid)
delete a feature from the layer (but does not commit it)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual QgsCoordinateReferenceSystem crs()=0
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:317
float maxScale() const
Definition: qgslabel.cpp:1399
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
EditorLayout
The different types to layout the attribute editor.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:322
void beginEditCommand(QString text)
Create edit command for undo/redo operations.
const QgsVectorJoinList & vectorJoins() const
int fieldNameIndex(const QString &fieldName) const
Look up field's index from name - case insensitive TODO: sort out case sensitive (indexFromName()) vs...
Definition: qgsfield.cpp:234
double rendererScale() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
virtual QDomElement save(QDomDocument &doc)
store renderer info to XML element
friend class QgsVectorLayerFeatureSource
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported...
virtual bool applyNamedStyle(QString namedStyle, QString &errorMsg)
Will load a named style from a provided QML string.
void invertSelectionInRectangle(QgsRectangle &rect)
Invert selection of features found within the search rectangle (in layer's coordinates) ...
bool commitChanges()
Attempts to commit any changes to disk.
void setRendererV2(QgsFeatureRendererV2 *r)
Set renderer V2.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
void deleteCachedGeometries()
Deletes the geometries in mCachedGeometries.
Storage and management of actions associated with Qgis layer attributes.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
bool startEditing()
Make layer editable.
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
void setRendererScale(double scale)
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
void removeExpressionField(int index)
Remove an expression field.
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
const QgsChangedAttributesMap & changedAttributeValues()
Changed attributes values which are not commited.
double closestSegmentWithContext(const QgsPoint &point, QgsPoint &minDistPoint, int &afterVertex, double *leftOf=0, double epsilon=DEFAULT_SEGMENT_EPSILON)
Searches for the closest segment of geometry to the given point.
void select(QgsRectangle &rect, bool addToSelection)
Select features found within the search rectangle (in layer's coordinates)
QgsVectorLayer::FeatureFormSuppress featureFormSuppress() const
Type of feature form pop-up suppression after feature creation (overrides app setting) ...
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:461
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:79
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0)
render label
Definition: qgslabel.cpp:72
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
FeatureFormSuppress
Types of feature form suppression after feature creation.
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="")
return a list of item text / symbol
QGis::GeometryType type() const
Returns type of the vector.
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 readCustomSymbology(const QDomElement &element, QString &errorMessage)
Signal emitted whenever the symbology (QML-file) for this layer is being read.
void addAttributeAlias(int attIndex, QString aliasString)
Sets an alias (a display name) for attributes to display in dialogs.
static const char * vectorGeometryType(GeometryType type)
description strings for geometry types
Definition: qgis.h:165
int insertSegmentVerticesForSnap(const QList< QgsSnappingResult > &snapResults)
Inserts vertices to the snapped segments.
Q_DECL_DEPRECATED QMap< QString, QVariant > valueMap(int idx)
Access value map.
void readXml(const QDomNode &layer_node)
Reads joins from project file.
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:172
virtual void rollBack()
Stop editing and discard the edits.
const QgsRectangle & cachedGeometriesRect()
void setDiagramRenderer(QgsDiagramRendererV2 *r)
Sets diagram rendering object (takes ownership)
void setLayerTransparency(int layerTransparency)
Write transparency for layer.
ValueRelationData valueRelation(int idx)
Access value relation widget data.
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not commited.
GeometryType
Definition: qgis.h:155
const QgsRectangle & extent() const
void remAttributeAlias(int attIndex)
Removes an alias (a display name) for attributes to display in dialogs.
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:34
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
WkbType
Used for symbology operations.
Definition: qgis.h:53
int addPart(const QList< QgsPoint > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
QList< QgsRelation > referencingRelations(int idx)
Get relations, where the foreign key is on this layer.
static const int EditingCapabilities
bitmask of all provider's editing capabilities
virtual ~QgsVectorLayer()
Destructor.
virtual QgsAttributeList pkAttributeIndexes()
Return list of indexes of fields that make up the primary key.
const QString displayExpression()
Get the preview expression, used to create a human readable preview string.
bool deleteVertex(QgsFeatureId atFeatureId, int atVertex)
Deletes a vertex from a feature.
void beforeCommitChanges()
Is emitted, before changes are commited to the data provider.
QgsPoint closestVertex(const QgsPoint &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist)
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
QgsPoint vertexAt(int atVertex)
Returns coordinates of a vertex.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
float minScale() const
Definition: qgslabel.cpp:1389
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
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 featureDeleted(QgsFeatureId fid)
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 setBlendMode(const QPainter::CompositionMode &blendMode)
Write blend mode for layer.
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written. ...
void invertSelection()
Select not selected features and deselect selected ones.
double x() const
Definition: qgspoint.h:126
int splitFeatures(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
virtual void updateExtents()
Update the extents for the layer.
Returns diagram settings for a 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.
const QgsVectorJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
QString editForm()
get edit form
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
virtual void stopRender(QgsRenderContext &context)=0
void setEditorLayout(EditorLayout editorLayout)
set the active layout for the attribute editor for this layer
bool writeXML(QDomNode &layer_node, QDomDocument &doc) const
Writes the actions out in XML format.
QgsGeometryMap & cachedGeometries()
virtual QDomElement toDomElement(QDomDocument &doc) const override
bool containsJoins() const
Quick way to test if there is any join at all.
const QString & name() const
Get the display name of the layer.
void checkJoinLayerRemove(QString theLayerId)
Check if there is a join with a layer that will be removed.
virtual QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat)
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfield.h:179
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 void writeXML(QDomElement &layerElem, QDomDocument &doc, const QgsVectorLayer *layer) const =0
virtual QVariant maximumValue(int index)
Returns the maximum value of an attribute.
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.
virtual QDomElement toDomElement(QDomDocument &doc) const override
void geometryChanged(QgsFeatureId fid, QgsGeometry &geom)
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
bool addJoin(const QgsVectorJoinInfo &joinInfo)
Joins another vector layer to this layer.
QPainter::CompositionMode blendMode() const
Read blend mode for layer.
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
void deselect(const QgsFeatureId featureId)
Deselect feature by its ID.
void layerDeleted()
QPainter::CompositionMode featureBlendMode() const
Read blend mode for layer.
QgsFeatureRequest & setFilterFids(QgsFeatureIds fids)
Set feature ID that should be fetched.
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
QgsRectangle extent() override
Return the extent of the layer as a QRect.
fast access to features using their ID
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any).
bool rollBack(bool deleteBuffer=true)
Stop editing and discard the edits.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
virtual bool setSubsetString(QString subset, bool updateFeatureCount=true)
Set the subset string used to create a subset of features in the layer.
QgsDataProvider * provider(const QString &providerKey, const QString &dataSource)
Create an instance of the provider.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
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.
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
void readXML(const QDomElement &elem, const QgsVectorLayer *layer)
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Q_DECL_DEPRECATED EditType editType(int idx)
Get edit type.
VertexMarkerType
Editing vertex markers.
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'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.
const QString & id() const
The id.
const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
int addTopologicalPoints(QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
void setScaleBasedVisibility(bool theVisibilityFlag)
Accessor and mutator for the scale based visilibility flag.
Definition: qgslabel.cpp:1374
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
int addPart(const QList< QgsPoint > &ring)
Adds a new part polygon to a multipart feature.
int fieldOriginIndex(int fieldIdx) const
Get field's origin index (its meaning is specific to each type of origin)
Definition: qgsfield.h:236
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 writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves expressions to xml under the layer node.
QgsGeometryMap mChangedGeometries
Changed geometries which are not commited.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0)...
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
void triggerRepaint()
Will advice the map canvas (and any other interested party) that this layer requires to be repainted...
virtual long featureCount() const =0
Number of features in the layer.
QgsVectorLayer(QString path=QString::null, QString baseName=QString::null, QString providerLib=QString::null, bool loadDefaultStyleFlag=true)
Constructor - creates a vector layer.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
int pendingFeatureCount()
returns feature count after commit
QList< int > QgsAttributeList
AttributeEditorType type() const
void destroyEditCommand()
Destroy active command and reverts all changes in it.
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, QVariant value, bool emitSignal)
Changes an attribute value (but does not commit it)
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
bool scaleBasedVisibility() const
Definition: qgslabel.cpp:1379
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:181
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
const QString displayField() const
Returns the primary display field name used in the identify results dialog.
int count() const
Return number of items.
Definition: qgsfield.h:214
bool setReadOnly(bool readonly=true)
Make layer read-only (editing disabled) or not.
field is calculated from an expression
Definition: qgsfield.h:182
bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
change feature'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.
QString labelField(int attr) const
label field
Definition: qgslabel.cpp:499
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not commited.
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:33
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg)
Import the properties of this layer from a QDomDocument.
void featureAdded(QgsFeatureId fid)
static QgsFeatureRendererV2 * defaultRenderer(QGis::GeometryType geomType)
return a new renderer - used by default in vector layers
const QString expressionField(int index)
Returns the expressoin used for a given expression field.
void setFeatureBlendMode(const QPainter::CompositionMode &blendMode)
Write blend mode for features.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
void rendererChanged()
Signal emitted when renderer is changed.
void updateFields(QgsFields &flds)
Adds fields with the expressions buffered in this object to a QgsFields object.
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.
void readXML(const QDomNode &node)
Reads the renderer configuration from an XML file.
Definition: qgslabel.cpp:731
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:571
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
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:63
QList< QgsRelation > referencingRelations(QgsVectorLayer *layer=0, int fieldIdx=-2) const
Get all relations where the specified layer (and field) is the referencing part (i.e.
void writeXML(QDomNode &label_node, QDomDocument &document) const
Writes the contents of the renderer to a configuration file.
Definition: qgslabel.cpp:1024
void removeJoin(const QString &joinLayerId)
Removes a vector layer join.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
virtual bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
int addRing(const QList< QgsPoint > &ring)
Adds a ring to polygon/multipolygon features.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
virtual bool deleteAttribute(int attr)
delete an attribute field (but does not commit it)
const QStringList & commitErrors()
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
Definition: qgsfield.h:239
bool labelOnTop(int idx)
label widget on top
void invalidateSymbolCountedFlag()
bool deleteSelectedFeatures(int *deletedCount=0)
Deletes the selected features.
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
int addTopologicalPoints(QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
void editCommandDestroyed()
Signal emitted, whan an edit command is destroyed.
void setX(double x)
Definition: qgspoint.h:103
bool isGeosEqual(QgsGeometry &)
compare geometries using GEOS
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)
Definition: qgspoint.h:111
virtual void reload() override
Synchronises with changes in the datasource.
void setEditorWidgetV2Config(int attrIdx, const QgsEditorWidgetConfig &config)
Set the editor widget config for a field.
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.
virtual bool isReadOnly() const
Returns true if the provider is in read-only mode.
virtual QString loadNamedStyle(const QString &theURI, bool &theResultFlag, bool loadFromLocalDb)
Load a named style from file/local db/datasource db.
QgsAttributeEditorElement * attributeEditorElementFromDomElement(QDomElement &elem, QObject *parent)
convert a saved attribute editor element into a AttributeEditor structure as it's used internally...
Implementation of threaded rendering for vector layers.
int layerTransparency() const
Read transparency for layer.
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode &blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
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:462
bool snapPoint(QgsPoint &point, double tolerance)
Snaps a point to the closest vertex if there is one within the snapping tolerance.
void setEditorWidgetV2(int attrIdx, const QString &widgetType)
Set the editor widget type for a field.
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)
Get edit type.
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.
void featureBlendModeChanged(const QPainter::CompositionMode &blendMode)
Signal emitted when setFeatureBlendMode() is called.
QgsRectangle boundingBox()
Returns the bounding box of this feature.
QString what() const
Definition: qgsexception.h:35
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
virtual long featureCount() const
Number of features in the layer.
Q_DECL_DEPRECATED QSize widgetSize(int idx)
Access widget size for photo and webview widget.
Contains information about the context of a rendering operation.
void setMaxScale(float theMaxScale)
Accessor and mutator for the maximum scale member.
Definition: qgslabel.cpp:1394
int addRing(const QList< QgsPoint > &ring)
Adds a ring to polygon/multipolygon features.
Buffers information about expression fields for a vector layer.
QString getStyleById_t(const QString &uri, QString styleID, QString &errCause)
virtual QDomElement toDomElement(QDomDocument &doc) const =0
virtual const QgsFields & fields() const =0
Return a map of indexes with field names for this layer.
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
QString loadStyle_t(const QString &uri, QString &errCause)
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
QgsAttributeList pendingAllAttributesList()
returns list of attributes
virtual QgsRectangle extent()=0
Get the extent of the layer.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:312
void setAnnotationForm(const QString &ui)
set annotation form for layer
QString mDataSource
data source description string, varies by layer type
Definition: qgsmaplayer.h:574
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...
static Q_DECL_DEPRECATED const QString convertEditType(QgsVectorLayer::EditType editType, QgsEditorWidgetConfig &cfg, QgsVectorLayer *vl, const QString &name, const QDomElement &editTypeElement=QDomElement())
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
void setSelectedFeatures(const QgsFeatureIds &ids)
Change selection to the new set of features.
void updateExpression(int index, const QString &exp)
Changes the expression at a given index.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves mVectorJoins to xml under the layer node.
This class manages a set of relations between layers.
static QgsFeatureRendererV2 * load(QDomElement &symbologyElem)
create a renderer from XML element
const QString & typeName() const
Gets the field type.
Definition: qgsfield.cpp:69
virtual bool setSubsetString(QString subset)
Set the string (typically sql) used to define a subset of the layer.
virtual void reloadData()
Reloads the data from the source.
void beforeModifiedCheck() const
Is emitted, when layer is checked for modifications.
virtual QVariant minimumValue(int index)
Returns the minimum value of an attribute.
void setEditForm(QString ui)
set edit form
Q_DECL_DEPRECATED RangeData range(int idx)
Access range widget config data.
virtual bool isValid()=0
Returns true if this is a valid 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 updateFields(QgsFields &fields)
Updates field map with joined attributes.
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)
void readXml(const QDomNode &layer_node)
Reads expressions from project file.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:351
QgsPoint snappedVertex
The coordinates of the snapping result.
Definition: qgssnapper.h:39
Q_DECL_DEPRECATED void setCheckedState(int idx, QString checked, QString notChecked)
Set string representing 'true' for a checkbox.
void removeExpression(int index)
Remove an expression from the buffer.
Class for storing a coordinate reference system (CRS)
void writeXML(QDomElement &layerElem, QDomDocument &doc, const QgsVectorLayer *layer) const
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:74
friend class QgsVectorLayerEditBuffer
QgsLabel * label()
Get the label object associated with this layer.
int size() const
Return number of items.
Definition: qgsfield.h:216
virtual QString description() const =0
return description
Q_DECL_DEPRECATED bool hasLabelsEnabled() const
Label is on.
QList< QgsAttributeEditorElement * > & attributeEditorElements()
Returns a list of tabs holding groups and fields.
virtual Q_DECL_DEPRECATED QDomElement writeSld(QDomDocument &doc, const QgsVectorLayer &layer) const
create the SLD UserStyle element following the SLD v1.1 specs
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
Definition: qgsfield.cpp:218
virtual void readXML(const QDomElement &elem, const QgsVectorLayer *layer)=0
const QMap< QString, QgsMapLayer * > & mapLayers()
Retrieve the mapLayers collection (mainly intended for use by projection)
void recalculateExtents()
This is used to send a request that any mapcanvas using this layer update its extents.
virtual QDomElement toDomElement(QDomDocument &doc) const override
const QString & comment() const
Returns the field comment.
Definition: qgsfield.cpp:84
void setFieldEditable(int idx, bool editable)
set edit widget editable
virtual bool deleteFeature(QgsFeatureId fid)
delete a feature from the layer (but does not commit it)
bool readSld(const QDomNode &node, QString &errorMessage) override
QMap< QString, QVariant > QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
qint64 QgsFeatureId
Definition: qgsfeature.h:30
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
virtual bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
changed an attribute value (but does not commit it)
double y() const
Definition: qgspoint.h:134
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's spatial reference system.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
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 ...
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage) const override
Write the symbology for the layer into the docment provided.
void(*)() cast_to_fptr(void *p)
Definition: qgis.h:323
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode &blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
QString dataComment() const
Returns a comment for the data in the layer.
void setMinScale(float theMinScale)
Accessor and mutator for the minimum scale member.
Definition: qgslabel.cpp:1384
Custom exception class for Coordinate Reference System related exceptions.
QUndoStack * undoStack()
Return pointer to layer's undo stack.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void setLabelOnTop(int idx, bool onTop)
label widget on top
QString metadata() override
Obtain Metadata for this layer.
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:180
QgsVectorDataProvider * dataProvider()
Returns the data provider.
virtual void addChildElement(QgsAttributeEditorElement *widget)
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void normalize()
Normalize the rectangle so it has non-negative width/height.
QString editFormInit()
get python function for edit form initialization
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
bool nextFeature(QgsFeature &f)
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.
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.
QgsFeatureMap mAddedFeatures
New features which are not commited.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
const QList< ExpressionField > & expressions() const
QgsFeatureIds allFeatureIds()
Get all feature Ids.
QgsAttributeList pendingPkAttributesList()
returns list of attribute making up the primary key
static QgsFeatureRendererV2 * readOldRenderer(const QDomNode &layerNode, QGis::GeometryType geomType)
Read old renderer definition from XML and create matching new renderer.
void updateFields(QgsFields &fields)
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 ...
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
QList< QPair< QString, QgsSymbolV2 * > > QgsLegendSymbolList
Definition: qgsrendererv2.h:43
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.
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.
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
QgsRelationManager * relationManager() const
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:183
void updateExpressionField(int index, const QString &exp)
Changes the expression used to define an expression based (virtual) field.
int max(int a, int b)
Definition: util.h:87
const QgsVectorLayer * layer
Layer where the snap occured.
Definition: qgssnapper.h:56
QString joinLayerId
Source layer.
void layerModified()
This signal is emitted when modifications has been done on layer.
QgsAttributeList mDeletedAttributeIds
deleted attributes fields which are not commited.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:246
Q_DECL_DEPRECATED void drawLabels(QgsRenderContext &rendererContext) override
Draws the layer labels using the old labeling engine.
bool readXML(const QDomNode &layer_node)
Reads the actions in in XML format.
virtual bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
change feature's geometry
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.
virtual QString dataSourceUri() const
Get the data source specification.
int splitFeatures(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
void setDisplayField(QString fldName="")
Set the primary display field to be used in the identify results dialog.
const CORE_EXPORT QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:72
virtual QList< QgsAttributeEditorElement * > findElements(AttributeEditorType type) const
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:203
QString toProj4() const
Get the Proj Proj4 string representation of this srs.
Q_DECL_DEPRECATED void enableLabels(bool on)
Set labels on.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void addAttributeEditorWidget(QgsAttributeEditorElement *data)
Adds a tab (for the attribute editor form) holding groups and fields.
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.
#define tr(sourceText)
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)