QGIS API Documentation  2.8.6-Wien
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  int 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  if ( !mDataProvider )
717  {
718  QgsDebugMsg( "invoked with null mDataProvider" );
719  return 0;
720  }
721 
722  return mDataProvider->featureCount();
723 }
724 
726 {
727  if ( !mSymbolFeatureCounted ) return -1;
728  return mSymbolFeatureCountMap.value( symbol );
729 }
730 
731 bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
732 {
733  if ( mSymbolFeatureCounted ) return true;
734  mSymbolFeatureCountMap.clear();
735 
736  if ( !mDataProvider )
737  {
738  QgsDebugMsg( "invoked with null mDataProvider" );
739  return false;
740  }
741  if ( !mRendererV2 )
742  {
743  QgsDebugMsg( "invoked with null mRendererV2" );
744  return false;
745  }
746 
747  QgsLegendSymbolList symbolList = mRendererV2->legendSymbolItems();
748  QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
749 
750  for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
751  {
752  mSymbolFeatureCountMap.insert( symbolIt->second, 0 );
753  }
754 
755  long nFeatures = pendingFeatureCount();
756  QProgressDialog progressDialog( tr( "Updating feature count for layer %1" ).arg( name() ), tr( "Abort" ), 0, nFeatures );
757  progressDialog.setWindowModality( Qt::WindowModal );
758  int featuresCounted = 0;
759 
761 
762  // Renderer (rule based) may depend on context scale, with scale is ignored if 0
763  QgsRenderContext renderContext;
764  renderContext.setRendererScale( 0 );
765  mRendererV2->startRender( renderContext, pendingFields() );
766 
767  QgsFeature f;
768  while ( fit.nextFeature( f ) )
769  {
770  QgsSymbolV2List featureSymbolList = mRendererV2->originalSymbolsForFeature( f );
771  for ( QgsSymbolV2List::iterator symbolIt = featureSymbolList.begin(); symbolIt != featureSymbolList.end(); ++symbolIt )
772  {
773  mSymbolFeatureCountMap[*symbolIt] += 1;
774  }
775  ++featuresCounted;
776 
777  if ( showProgress )
778  {
779  if ( featuresCounted % 50 == 0 )
780  {
781  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
782  {
783  progressDialog.setMaximum( 0 );
784  }
785  progressDialog.setValue( featuresCounted );
786  if ( progressDialog.wasCanceled() )
787  {
788  mSymbolFeatureCountMap.clear();
789  mRendererV2->stopRender( renderContext );
790  return false;
791  }
792  }
793  }
794  }
795  mRendererV2->stopRender( renderContext );
796  progressDialog.setValue( nFeatures );
797  mSymbolFeatureCounted = true;
798  return true;
799 }
800 
802 {
803  mValidExtent = false;
804 }
805 
807 {
809  mValidExtent = true;
810 }
811 
813 {
814  QgsRectangle rect;
815  rect.setMinimal();
816 
817  if ( !hasGeometryType() )
818  return rect;
819 
820  if ( !mValidExtent && mLazyExtent && mDataProvider )
821  {
822  // get the extent
823  QgsRectangle mbr = mDataProvider->extent();
824 
825  // show the extent
826  QString s = mbr.toString();
827 
828  QgsDebugMsg( "Extent of layer: " + s );
829  // store the extent
830  setExtent( mbr );
831 
832  mLazyExtent = false;
833  }
834 
835  if ( mValidExtent )
836  return QgsMapLayer::extent();
837 
838  if ( !mDataProvider )
839  {
840  QgsDebugMsg( "invoked with null mDataProvider" );
841  }
842 
843  if ( mDataProvider && mEditBuffer && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() )
844  {
845  mDataProvider->updateExtents();
846 
847  // get the extent of the layer from the provider
848  // but only when there are some features already
849  if ( mDataProvider->featureCount() != 0 )
850  {
851  QgsRectangle r = mDataProvider->extent();
852  rect.combineExtentWith( &r );
853  }
854 
855  for ( QgsFeatureMap::iterator it = mEditBuffer->mAddedFeatures.begin(); it != mEditBuffer->mAddedFeatures.end(); ++it )
856  {
857  if ( it->geometry() )
858  {
859  QgsRectangle r = it->geometry()->boundingBox();
860  rect.combineExtentWith( &r );
861  }
862  }
863  }
864  else
865  {
867  .setSubsetOfAttributes( QgsAttributeList() ) );
868 
869  QgsFeature fet;
870  while ( fit.nextFeature( fet ) )
871  {
872  if ( fet.geometry() && fet.geometry()->type() != QGis::UnknownGeometry )
873  {
874  QgsRectangle bb = fet.geometry()->boundingBox();
875  rect.combineExtentWith( &bb );
876  }
877  }
878  }
879 
880  if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
881  {
882  // special case when there are no features in provider nor any added
883  rect = QgsRectangle(); // use rectangle with zero coordinates
884  }
885 
886  setExtent( rect );
887 
888  // Send this (hopefully) up the chain to the map canvas
889  emit recalculateExtents();
890 
891  return rect;
892 }
893 
895 {
896  if ( ! mDataProvider )
897  {
898  QgsDebugMsg( "invoked with null mDataProvider" );
899  return 0;
900  }
901  return mDataProvider->subsetString();
902 }
903 
904 bool QgsVectorLayer::setSubsetString( QString subset )
905 {
906  if ( ! mDataProvider )
907  {
908  QgsDebugMsg( "invoked with null mDataProvider" );
909  return false;
910  }
911 
912  bool res = mDataProvider->setSubsetString( subset );
913 
914  // get the updated data source string from the provider
915  mDataSource = mDataProvider->dataSourceUri();
916  updateExtents();
917 
918  if ( res )
919  emit repaintRequested();
920 
921  return res;
922 }
923 
925 {
926  if ( mDataProvider && !mEditBuffer && ( hasGeometryType() && geometryType() != QGis::Point ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
927  {
928  double maximumSimplificationScale = mSimplifyMethod.maximumScale();
929 
930  // check maximum scale at which generalisation should be carried out
931  if ( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale )
932  return false;
933 
934  return true;
935  }
936  return false;
937 }
938 
940 {
941  if ( !mDataProvider )
942  return QgsFeatureIterator();
943 
944  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
945 }
946 
947 
948 bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
949 {
950  Q_UNUSED( alsoUpdateExtent ); // TODO[MD]
951  if ( !mEditBuffer || !mDataProvider )
952  return false;
953 
954  bool success = mEditBuffer->addFeature( f );
955 
956  if ( success )
957  updateExtents();
958 
959  return success;
960 }
961 
963 {
964  QgsFeatureRequest req;
965  req.setFilterFid( f.id() );
966  if ( !f.geometry() )
968  if ( f.attributes().isEmpty() )
970 
971  QgsFeature current;
972  if ( !getFeatures( req ).nextFeature( current ) )
973  {
974  QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( f.id() ) );
975  return false;
976  }
977 
978  if ( f.geometry() && current.geometry() && f.geometry() != current.geometry() && !f.geometry()->isGeosEqual( *current.geometry() ) )
979  {
980  if ( !changeGeometry( f.id(), f.geometry() ) )
981  {
982  QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( f.id() ) );
983  return false;
984  }
985  }
986 
987  const QgsAttributes &fa = f.attributes();
988  const QgsAttributes &ca = current.attributes();
989 
990  for ( int attr = 0; attr < fa.count(); ++attr )
991  {
992  if ( fa[attr] != ca[attr] )
993  {
994  if ( !changeAttributeValue( f.id(), attr, fa[attr], ca[attr] ) )
995  {
996  QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( f.id() ) );
997  return false;
998  }
999  }
1000  }
1001 
1002  return true;
1003 }
1004 
1005 
1006 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1007 {
1008  if ( !mEditBuffer || !mDataProvider )
1009  return false;
1010 
1011  QgsVectorLayerEditUtils utils( this );
1012  return utils.insertVertex( x, y, atFeatureId, beforeVertex );
1013 }
1014 
1015 
1016 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1017 {
1018  if ( !mEditBuffer || !mDataProvider )
1019  return false;
1020 
1021  QgsVectorLayerEditUtils utils( this );
1022  return utils.moveVertex( x, y, atFeatureId, atVertex );
1023 }
1024 
1025 
1026 bool QgsVectorLayer::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
1027 {
1028  if ( !mEditBuffer || !mDataProvider )
1029  return false;
1030 
1031  QgsVectorLayerEditUtils utils( this );
1032  return utils.deleteVertex( atFeatureId, atVertex );
1033 }
1034 
1035 
1037 {
1038  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1039  {
1040  return false;
1041  }
1042 
1043  if ( !isEditable() )
1044  {
1045  return false;
1046  }
1047 
1048  int deleted = 0;
1049  int count = mSelectedFeatureIds.size();
1050  // Make a copy since deleteFeature modifies mSelectedFeatureIds
1051  QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1052  foreach ( QgsFeatureId fid, selectedFeatures )
1053  {
1054  deleted += deleteFeature( fid ); // removes from selection
1055  }
1056 
1057  triggerRepaint();
1058  updateExtents();
1059 
1060  if ( deletedCount )
1061  {
1062  *deletedCount = deleted;
1063  }
1064 
1065  return deleted == count;
1066 }
1067 
1068 int QgsVectorLayer::addRing( const QList<QgsPoint>& ring, QgsFeatureId* featureId )
1069 {
1070  if ( !mEditBuffer || !mDataProvider )
1071  return 6;
1072 
1073  QgsVectorLayerEditUtils utils( this );
1074  return utils.addRing( ring, featureId );
1075 }
1076 
1077 int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
1078 {
1079  if ( !mEditBuffer || !mDataProvider )
1080  return 7;
1081 
1082  //number of selected features must be 1
1083 
1084  if ( mSelectedFeatureIds.size() < 1 )
1085  {
1086  QgsDebugMsg( "Number of selected features <1" );
1087  return 4;
1088  }
1089  else if ( mSelectedFeatureIds.size() > 1 )
1090  {
1091  QgsDebugMsg( "Number of selected features >1" );
1092  return 5;
1093  }
1094 
1095  QgsVectorLayerEditUtils utils( this );
1096  return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1097 }
1098 
1099 
1100 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1101 {
1102  if ( !mEditBuffer || !mDataProvider )
1103  return -1;
1104 
1105  QgsVectorLayerEditUtils utils( this );
1106  return utils.translateFeature( featureId, dx, dy );
1107 }
1108 
1109 int QgsVectorLayer::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1110 {
1111  if ( !mEditBuffer || !mDataProvider )
1112  return -1;
1113 
1114  QgsVectorLayerEditUtils utils( this );
1115  return utils.splitParts( splitLine, topologicalEditing );
1116 }
1117 
1118 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1119 {
1120  if ( !mEditBuffer || !mDataProvider )
1121  return -1;
1122 
1123  QgsVectorLayerEditUtils utils( this );
1124  return utils.splitFeatures( splitLine, topologicalEditing );
1125 }
1126 
1128 {
1129  if ( !hasGeometryType() )
1130  return 1;
1131 
1132  int returnValue = 0;
1133 
1134  //first test if geom really has type polygon or multipolygon
1135  if ( geom->type() != QGis::Polygon )
1136  {
1137  return 1;
1138  }
1139 
1140  //get bounding box of geom
1141  QgsRectangle geomBBox = geom->boundingBox();
1142 
1143  //get list of features that intersect this bounding box
1145  .setFilterRect( geomBBox )
1147  .setSubsetOfAttributes( QgsAttributeList() ) );
1148 
1149  QgsFeature f;
1150  while ( fit.nextFeature( f ) )
1151  {
1152  if ( ignoreFeatures.contains( f.id() ) )
1153  {
1154  continue;
1155  }
1156 
1157  //call geometry->makeDifference for each feature
1158  QgsGeometry *currentGeom = f.geometry();
1159  if ( currentGeom )
1160  {
1161  if ( geom->makeDifference( currentGeom ) != 0 )
1162  {
1163  returnValue = 2;
1164  }
1165  }
1166  }
1167 
1168  return returnValue;
1169 }
1170 
1172 {
1173  if ( !mEditBuffer || !mDataProvider )
1174  return -1;
1175 
1176  QgsVectorLayerEditUtils utils( this );
1177  return utils.addTopologicalPoints( geom );
1178 }
1179 
1181 {
1182  if ( !mEditBuffer || !mDataProvider )
1183  return -1;
1184 
1185  QgsVectorLayerEditUtils utils( this );
1186  return utils.addTopologicalPoints( p );
1187 }
1188 
1190 {
1191  return mLabel;
1192 }
1193 
1195 {
1196  return mLabel;
1197 }
1198 
1200 {
1201  mLabelOn = on;
1202 }
1203 
1205 {
1206  return mLabelOn;
1207 }
1208 
1210 {
1211  if ( !mDataProvider )
1212  {
1213  return false;
1214  }
1215 
1216  // allow editing if provider supports any of the capabilities
1217  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1218  {
1219  return false;
1220  }
1221 
1222  if ( mReadOnly )
1223  {
1224  return false;
1225  }
1226 
1227  if ( mEditBuffer )
1228  {
1229  // editing already underway
1230  return false;
1231  }
1232 
1233  if ( mDataProvider->transaction() )
1234  {
1235  mEditBuffer = new QgsVectorLayerEditPassthrough( this );
1236  }
1237  else
1238  {
1239  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1240  }
1241  // forward signals
1242  connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( invalidateSymbolCountedFlag() ) );
1243  connect( mEditBuffer, SIGNAL( layerModified() ), this, SIGNAL( layerModified() ) ); // TODO[MD]: necessary?
1244  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1245  connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( featureAdded( QgsFeatureId ) ) );
1246  connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SIGNAL( featureDeleted( QgsFeatureId ) ) );
1247  connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
1248  connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
1249  connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), this, SIGNAL( attributeAdded( int ) ) );
1250  connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), this, SIGNAL( attributeDeleted( int ) ) );
1251 
1252  connect( mEditBuffer, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ),
1253  this, SIGNAL( committedAttributesDeleted( const QString &, const QgsAttributeList & ) ) );
1254 
1255  connect( mEditBuffer, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ),
1256  this, SIGNAL( committedAttributesAdded( const QString &, const QList<QgsField> & ) ) );
1257 
1258  connect( mEditBuffer, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ), this, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ) );
1259  connect( mEditBuffer, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ), this, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ) );
1260 
1261  connect( mEditBuffer, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ),
1262  this, SIGNAL( committedAttributeValuesChanges( const QString &, const QgsChangedAttributesMap & ) ) );
1263 
1264  connect( mEditBuffer, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ),
1265  this, SIGNAL( committedGeometriesChanges( const QString &, const QgsGeometryMap & ) ) );
1266 
1267  updateFields();
1268 
1269  emit editingStarted();
1270 
1271  return true;
1272 }
1273 
1274 bool QgsVectorLayer::readXml( const QDomNode& layer_node )
1275 {
1276  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
1277 
1278  //process provider key
1279  QDomNode pkeyNode = layer_node.namedItem( "provider" );
1280 
1281  if ( pkeyNode.isNull() )
1282  {
1283  mProviderKey = "";
1284  }
1285  else
1286  {
1287  QDomElement pkeyElt = pkeyNode.toElement();
1288  mProviderKey = pkeyElt.text();
1289  }
1290 
1291  // determine type of vector layer
1292  if ( ! mProviderKey.isNull() )
1293  {
1294  // if the provider string isn't empty, then we successfully
1295  // got the stored provider
1296  }
1297  else if ( mDataSource.contains( "dbname=" ) )
1298  {
1299  mProviderKey = "postgres";
1300  }
1301  else
1302  {
1303  mProviderKey = "ogr";
1304  }
1305 
1306  if ( ! setDataProvider( mProviderKey ) )
1307  {
1308  return false;
1309  }
1310 
1311  QDomElement pkeyElem = pkeyNode.toElement();
1312  if ( !pkeyElem.isNull() )
1313  {
1314  QString encodingString = pkeyElem.attribute( "encoding" );
1315  if ( !encodingString.isEmpty() )
1316  {
1317  mDataProvider->setEncoding( encodingString );
1318  }
1319  }
1320 
1321  //load vector joins
1322  if ( !mJoinBuffer )
1323  {
1324  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1325  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1326  }
1327  mJoinBuffer->readXml( layer_node );
1328 
1329  if ( !mExpressionFieldBuffer )
1330  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1331  mExpressionFieldBuffer->readXml( layer_node );
1332 
1333  updateFields();
1334  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1335 
1336  QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );
1337 
1338  if ( prevExpNode.isNull() )
1339  {
1340  mDisplayExpression = "";
1341  }
1342  else
1343  {
1344  QDomElement prevExpElem = prevExpNode.toElement();
1345  mDisplayExpression = prevExpElem.text();
1346  }
1347 
1348  QString errorMsg;
1349  if ( !readSymbology( layer_node, errorMsg ) )
1350  {
1351  return false;
1352  }
1353 
1354  readStyleManager( layer_node );
1355 
1357 
1358  return mValid; // should be true if read successfully
1359 
1360 } // void QgsVectorLayer::readXml
1361 
1362 
1363 bool QgsVectorLayer::setDataProvider( QString const & provider )
1364 {
1365  // XXX should I check for and possibly delete any pre-existing providers?
1366  // XXX How often will that scenario occur?
1367 
1368  mProviderKey = provider; // XXX is this necessary? Usually already set
1369  // XXX when execution gets here.
1370 
1371  //XXX - This was a dynamic cast but that kills the Windows
1372  // version big-time with an abnormal termination error
1373  mDataProvider =
1375 
1376  if ( mDataProvider )
1377  {
1378  QgsDebugMsg( "Instantiated the data provider plugin" );
1379 
1380  mValid = mDataProvider->isValid();
1381  if ( mValid )
1382  {
1383  // TODO: Check if the provider has the capability to send fullExtentCalculated
1384  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
1385 
1386  // get and store the feature type
1387  mWkbType = mDataProvider->geometryType();
1388 
1389  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1390  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1391  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1392  updateFields();
1393 
1394  // look at the fields in the layer and set the primary
1395  // display field using some real fuzzy logic
1396  setDisplayField();
1397 
1398  if ( mProviderKey == "postgres" )
1399  {
1400  QgsDebugMsg( "Beautifying layer name " + name() );
1401 
1402  // adjust the display name for postgres layers
1403  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1404  if ( reg.indexIn( name() ) >= 0 )
1405  {
1406  QStringList stuff = reg.capturedTexts();
1407  QString lName = stuff[1];
1408 
1409  const QMap<QString, QgsMapLayer*> &layers = QgsMapLayerRegistry::instance()->mapLayers();
1410 
1411  QMap<QString, QgsMapLayer*>::const_iterator it;
1412  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1413  ;
1414 
1415  if ( it != layers.constEnd() && stuff.size() > 2 )
1416  {
1417  lName += "." + stuff[2].mid( 2, stuff[2].length() - 3 );
1418  }
1419 
1420  if ( !lName.isEmpty() )
1421  setLayerName( lName );
1422  }
1423 
1424  QgsDebugMsg( "Beautified layer name " + name() );
1425 
1426  // deal with unnecessary schema qualification to make v.in.ogr happy
1427  mDataSource = mDataProvider->dataSourceUri();
1428  }
1429  else if ( mProviderKey == "osm" )
1430  {
1431  // make sure that the "observer" has been removed from URI to avoid crashes
1432  mDataSource = mDataProvider->dataSourceUri();
1433  }
1434  else if ( provider == "ogr" )
1435  {
1436  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1437  mDataSource = mDataProvider->dataSourceUri();
1438  if ( mDataSource.right( 10 ) == "|layerid=0" )
1439  mDataSource.chop( 10 );
1440  }
1441 
1442  // label
1443  mLabel = new QgsLabel( mDataProvider->fields() );
1444  mLabelOn = false;
1445  }
1446  else
1447  {
1448  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1449  return false;
1450  }
1451  }
1452  else
1453  {
1454  QgsDebugMsg( " unable to get data provider" );
1455  return false;
1456  }
1457 
1458  return true;
1459 
1460 } // QgsVectorLayer:: setDataProvider
1461 
1462 
1463 
1464 
1465 /* virtual */
1466 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
1467  QDomDocument & document )
1468 {
1469  // first get the layer element so that we can append the type attribute
1470 
1471  QDomElement mapLayerNode = layer_node.toElement();
1472 
1473  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1474  {
1475  QgsDebugMsg( "can't find <maplayer>" );
1476  return false;
1477  }
1478 
1479  mapLayerNode.setAttribute( "type", "vector" );
1480 
1481  // set the geometry type
1482  mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
1483 
1484  // add provider node
1485  if ( mDataProvider )
1486  {
1487  QDomElement provider = document.createElement( "provider" );
1488  provider.setAttribute( "encoding", mDataProvider->encoding() );
1489  QDomText providerText = document.createTextNode( providerType() );
1490  provider.appendChild( providerText );
1491  layer_node.appendChild( provider );
1492  }
1493 
1494  // save preview expression
1495  QDomElement prevExpElem = document.createElement( "previewExpression" );
1496  QDomText prevExpText = document.createTextNode( mDisplayExpression );
1497  prevExpElem.appendChild( prevExpText );
1498  layer_node.appendChild( prevExpElem );
1499 
1500  //save joins
1501  mJoinBuffer->writeXml( layer_node, document );
1502 
1503  // save expression fields
1504  mExpressionFieldBuffer->writeXml( layer_node, document );
1505 
1506  writeStyleManager( layer_node, document );
1507 
1508  // renderer specific settings
1509  QString errorMsg;
1510  return writeSymbology( layer_node, document, errorMsg );
1511 } // bool QgsVectorLayer::writeXml
1512 
1513 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
1514 {
1515  emit readCustomSymbology( node.toElement(), errorMessage );
1516 
1517  if ( hasGeometryType() )
1518  {
1519  // try renderer v2 first
1520  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1521  if ( !rendererElement.isNull() )
1522  {
1523  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
1524  if ( !r )
1525  return false;
1526 
1527  setRendererV2( r );
1528  }
1529  else
1530  {
1532  if ( !r )
1534 
1535  setRendererV2( r );
1536  }
1537 
1538  // get and set the display field if it exists.
1539  QDomNode displayFieldNode = node.namedItem( "displayfield" );
1540  if ( !displayFieldNode.isNull() )
1541  {
1542  QDomElement e = displayFieldNode.toElement();
1543  setDisplayField( e.text() );
1544  }
1545 
1546  // get and set the blend mode if it exists
1547  QDomNode blendModeNode = node.namedItem( "blendMode" );
1548  if ( !blendModeNode.isNull() )
1549  {
1550  QDomElement e = blendModeNode.toElement();
1552  }
1553 
1554  // get and set the feature blend mode if it exists
1555  QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
1556  if ( !featureBlendModeNode.isNull() )
1557  {
1558  QDomElement e = featureBlendModeNode.toElement();
1560  }
1561 
1562  // get and set the layer transparency if it exists
1563  QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
1564  if ( !layerTransparencyNode.isNull() )
1565  {
1566  QDomElement e = layerTransparencyNode.toElement();
1567  setLayerTransparency( e.text().toInt() );
1568  }
1569 
1570  // use scale dependent visibility flag
1571  QDomElement e = node.toElement();
1572  if ( mLabel )
1573  {
1574  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
1575  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
1576  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
1577  }
1578 
1579  // get the simplification drawing settings
1580  mSimplifyMethod.setSimplifyHints(( QgsVectorSimplifyMethod::SimplifyHints ) e.attribute( "simplifyDrawingHints", "1" ).toInt() );
1581  mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
1582  mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
1583  mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
1584 
1585  //also restore custom properties (for labeling-ng)
1586  readCustomProperties( node, "labeling" );
1587 
1588  // Test if labeling is on or off
1589  QDomNode labelnode = node.namedItem( "label" );
1590  QDomElement element = labelnode.toElement();
1591  int hasLabelsEnabled = element.text().toInt();
1592  if ( hasLabelsEnabled < 1 )
1593  {
1594  enableLabels( false );
1595  }
1596  else
1597  {
1598  enableLabels( true );
1599  }
1600 
1601  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
1602 
1603  if ( !labelattributesnode.isNull() && mLabel )
1604  {
1605  QgsDebugMsg( "calling readXML" );
1606  mLabel->readXML( labelattributesnode );
1607  }
1608 
1609  //diagram renderer and diagram layer settings
1610  delete mDiagramRenderer; mDiagramRenderer = 0;
1611  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
1612  if ( !singleCatDiagramElem.isNull() )
1613  {
1614  QDomElement catElem = singleCatDiagramElem.firstChildElement( "DiagramCategory" );
1615  if ( !catElem.isNull() && catElem.attribute( "enabled", "1" ) != "0" )
1616  {
1617  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1618  mDiagramRenderer->readXML( singleCatDiagramElem, this );
1619  }
1620  }
1621  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
1622  if ( !linearDiagramElem.isNull() )
1623  {
1624  QDomElement catElem = linearDiagramElem.firstChildElement( "DiagramCategory" );
1625  if ( !catElem.isNull() && catElem.attribute( "enabled", "1" ) != "0" )
1626  {
1627  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
1628  mDiagramRenderer->readXML( linearDiagramElem, this );
1629  }
1630  }
1631 
1632  if ( mDiagramRenderer )
1633  {
1634  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
1635  if ( !diagramSettingsElem.isNull() )
1636  {
1637  mDiagramLayerSettings = new QgsDiagramLayerSettings();
1638  mDiagramLayerSettings->readXML( diagramSettingsElem, this );
1639  }
1640  }
1641  }
1642 
1643  // process the attribute actions
1644  mActions->readXML( node );
1645 
1646 
1647  QDomNode editFormNode = node.namedItem( "editform" );
1648  if ( !editFormNode.isNull() )
1649  {
1650  QDomElement e = editFormNode.toElement();
1651  mEditForm = QgsProject::instance()->readPath( e.text() );
1652  }
1653 
1654  QDomNode editFormInitNode = node.namedItem( "editforminit" );
1655  if ( !editFormInitNode.isNull() )
1656  {
1657  mEditFormInit = editFormInitNode.toElement().text();
1658  }
1659 
1660  QDomNode fFSuppNode = node.namedItem( "featformsuppress" );
1661  if ( fFSuppNode.isNull() )
1662  {
1663  mFeatureFormSuppress = SuppressDefault;
1664  }
1665  else
1666  {
1667  QDomElement e = fFSuppNode.toElement();
1668  mFeatureFormSuppress = ( QgsVectorLayer::FeatureFormSuppress )e.text().toInt();
1669  }
1670 
1671  QDomNode annotationFormNode = node.namedItem( "annotationform" );
1672  if ( !annotationFormNode.isNull() )
1673  {
1674  QDomElement e = annotationFormNode.toElement();
1675  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1676  }
1677 
1678  mAttributeAliasMap.clear();
1679  QDomNode aliasesNode = node.namedItem( "aliases" );
1680  if ( !aliasesNode.isNull() )
1681  {
1682  QDomElement aliasElem;
1683 
1684  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
1685  for ( int i = 0; i < aliasNodeList.size(); ++i )
1686  {
1687  aliasElem = aliasNodeList.at( i ).toElement();
1688 
1689  QString field;
1690  if ( aliasElem.hasAttribute( "field" ) )
1691  {
1692  field = aliasElem.attribute( "field" );
1693  }
1694  else
1695  {
1696  int index = aliasElem.attribute( "index" ).toInt();
1697 
1698  if ( index >= 0 && index < pendingFields().count() )
1699  field = pendingFields()[ index ].name();
1700  }
1701 
1702  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
1703  }
1704  }
1705 
1706  // tab display
1707  QDomNode editorLayoutNode = node.namedItem( "editorlayout" );
1708  if ( editorLayoutNode.isNull() )
1709  {
1710  mEditorLayout = GeneratedLayout;
1711  }
1712  else
1713  {
1714  if ( editorLayoutNode.toElement().text() == "uifilelayout" )
1715  {
1716  mEditorLayout = UiFileLayout;
1717  }
1718  else if ( editorLayoutNode.toElement().text() == "tablayout" )
1719  {
1720  mEditorLayout = TabLayout;
1721  }
1722  else
1723  {
1724  mEditorLayout = GeneratedLayout;
1725  }
1726  }
1727 
1728  //Attributes excluded from WMS and WFS
1729  mExcludeAttributesWMS.clear();
1730  QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
1731  if ( !excludeWMSNode.isNull() )
1732  {
1733  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
1734  for ( int i = 0; i < attributeNodeList.size(); ++i )
1735  {
1736  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1737  }
1738  }
1739 
1740  mExcludeAttributesWFS.clear();
1741  QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
1742  if ( !excludeWFSNode.isNull() )
1743  {
1744  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
1745  for ( int i = 0; i < attributeNodeList.size(); ++i )
1746  {
1747  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1748  }
1749  }
1750 
1751  // tabs and groups display info
1752  mAttributeEditorElements.clear();
1753  QDomNode attributeEditorFormNode = node.namedItem( "attributeEditorForm" );
1754  QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
1755 
1756  for ( int i = 0; i < attributeEditorFormNodeList.size(); i++ )
1757  {
1758  QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
1759 
1760  QgsAttributeEditorElement *attributeEditorWidget = attributeEditorElementFromDomElement( elem, this );
1761  mAttributeEditorElements.append( attributeEditorWidget );
1762  }
1763 
1764  return true;
1765 }
1766 
1768 {
1769  QgsAttributeEditorElement* newElement = NULL;
1770 
1771  if ( elem.tagName() == "attributeEditorContainer" )
1772  {
1773  QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( elem.attribute( "name" ), parent );
1774 
1775  QDomNodeList childNodeList = elem.childNodes();
1776 
1777  for ( int i = 0; i < childNodeList.size(); i++ )
1778  {
1779  QDomElement childElem = childNodeList.at( i ).toElement();
1780  QgsAttributeEditorElement *myElem = attributeEditorElementFromDomElement( childElem, container );
1781  if ( myElem )
1782  container->addChildElement( myElem );
1783  }
1784 
1785  newElement = container;
1786  }
1787  else if ( elem.tagName() == "attributeEditorField" )
1788  {
1789  QString name = elem.attribute( "name" );
1790  int idx = fieldNameIndex( name );
1791  newElement = new QgsAttributeEditorField( name, idx, parent );
1792  }
1793  else if ( elem.tagName() == "attributeEditorRelation" )
1794  {
1795  // At this time, the relations are not loaded
1796  // So we only grab the id and delegate the rest to onRelationsLoaded()
1797  QString name = elem.attribute( "name" );
1798  newElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
1799  }
1800  return newElement;
1801 }
1802 
1803 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1804 {
1805  QDomElement mapLayerNode = node.toElement();
1806 
1807  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
1808 
1809  if ( hasGeometryType() )
1810  {
1811  QDomElement rendererElement = mRendererV2->save( doc );
1812  node.appendChild( rendererElement );
1813 
1814  // use scale dependent visibility flag
1815  if ( mLabel )
1816  {
1817  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
1818  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
1819  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
1820  }
1821 
1822  // save the simplification drawing settings
1823  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
1824  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
1825  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
1826  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
1827 
1828  //save customproperties (for labeling ng)
1829  writeCustomProperties( node, doc );
1830 
1831  // add the blend mode field
1832  QDomElement blendModeElem = doc.createElement( "blendMode" );
1833  QDomText blendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( blendMode() ) ) );
1834  blendModeElem.appendChild( blendModeText );
1835  node.appendChild( blendModeElem );
1836 
1837  // add the feature blend mode field
1838  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
1839  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( featureBlendMode() ) ) );
1840  featureBlendModeElem.appendChild( featureBlendModeText );
1841  node.appendChild( featureBlendModeElem );
1842 
1843  // add the layer transparency
1844  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
1845  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
1846  layerTransparencyElem.appendChild( layerTransparencyText );
1847  node.appendChild( layerTransparencyElem );
1848 
1849  // add the display field
1850  QDomElement dField = doc.createElement( "displayfield" );
1851  QDomText dFieldText = doc.createTextNode( displayField() );
1852  dField.appendChild( dFieldText );
1853  node.appendChild( dField );
1854 
1855  // add label node
1856  QDomElement labelElem = doc.createElement( "label" );
1857  QDomText labelText = doc.createTextNode( "" );
1858 
1859  if ( hasLabelsEnabled() )
1860  {
1861  labelText.setData( "1" );
1862  }
1863  else
1864  {
1865  labelText.setData( "0" );
1866  }
1867  labelElem.appendChild( labelText );
1868 
1869  node.appendChild( labelElem );
1870 
1871  // Now we get to do all that all over again for QgsLabel
1872 
1873  if ( mLabel )
1874  {
1875  QString fieldname = mLabel->labelField( QgsLabel::Text );
1876  if ( fieldname != "" )
1877  {
1878  dField = doc.createElement( "labelfield" );
1879  dFieldText = doc.createTextNode( fieldname );
1880  dField.appendChild( dFieldText );
1881  node.appendChild( dField );
1882  }
1883 
1884  mLabel->writeXML( node, doc );
1885  }
1886 
1887  if ( mDiagramRenderer )
1888  {
1889  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
1890  if ( mDiagramLayerSettings )
1891  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
1892  }
1893  }
1894 
1895  // FIXME
1896  // edittypes are written to the layerNode
1897  // by slot QgsEditorWidgetRegistry::writeMapLayer()
1898  // triggered by signal QgsProject::writeMapLayer()
1899  // still other editing settings are written here,
1900  // although they are not part of symbology either
1901 
1902  QDomElement efField = doc.createElement( "editform" );
1903  QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( mEditForm ) );
1904  efField.appendChild( efText );
1905  node.appendChild( efField );
1906 
1907  QDomElement efiField = doc.createElement( "editforminit" );
1908  if ( !mEditFormInit.isEmpty() )
1909  efiField.appendChild( doc.createTextNode( mEditFormInit ) );
1910  node.appendChild( efiField );
1911 
1912  QDomElement fFSuppElem = doc.createElement( "featformsuppress" );
1913  QDomText fFSuppText = doc.createTextNode( QString::number( featureFormSuppress() ) );
1914  fFSuppElem.appendChild( fFSuppText );
1915  node.appendChild( fFSuppElem );
1916 
1917  QDomElement afField = doc.createElement( "annotationform" );
1918  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
1919  afField.appendChild( afText );
1920  node.appendChild( afField );
1921 
1922  // tab display
1923  QDomElement editorLayoutElem = doc.createElement( "editorlayout" );
1924  switch ( mEditorLayout )
1925  {
1926  case UiFileLayout:
1927  editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
1928  break;
1929 
1930  case TabLayout:
1931  editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
1932  break;
1933 
1934  case GeneratedLayout:
1935  default:
1936  editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
1937  break;
1938  }
1939 
1940  node.appendChild( editorLayoutElem );
1941 
1942  //attribute aliases
1943  if ( mAttributeAliasMap.size() > 0 )
1944  {
1945  QDomElement aliasElem = doc.createElement( "aliases" );
1946  QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
1947  for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
1948  {
1949  int idx = fieldNameIndex( a_it.key() );
1950  if ( idx < 0 )
1951  continue;
1952 
1953  QDomElement aliasEntryElem = doc.createElement( "alias" );
1954  aliasEntryElem.setAttribute( "field", a_it.key() );
1955  aliasEntryElem.setAttribute( "index", idx );
1956  aliasEntryElem.setAttribute( "name", a_it.value() );
1957  aliasElem.appendChild( aliasEntryElem );
1958  }
1959  node.appendChild( aliasElem );
1960  }
1961 
1962  //exclude attributes WMS
1963  QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
1964  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
1965  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
1966  {
1967  QDomElement attrElem = doc.createElement( "attribute" );
1968  QDomText attrText = doc.createTextNode( *attWMSIt );
1969  attrElem.appendChild( attrText );
1970  excludeWMSElem.appendChild( attrElem );
1971  }
1972  node.appendChild( excludeWMSElem );
1973 
1974  //exclude attributes WFS
1975  QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
1976  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
1977  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
1978  {
1979  QDomElement attrElem = doc.createElement( "attribute" );
1980  QDomText attrText = doc.createTextNode( *attWFSIt );
1981  attrElem.appendChild( attrText );
1982  excludeWFSElem.appendChild( attrElem );
1983  }
1984  node.appendChild( excludeWFSElem );
1985 
1986  // tabs and groups of edit form
1987  if ( mAttributeEditorElements.size() > 0 )
1988  {
1989  QDomElement tabsElem = doc.createElement( "attributeEditorForm" );
1990 
1991  for ( QList< QgsAttributeEditorElement* >::const_iterator it = mAttributeEditorElements.begin(); it != mAttributeEditorElements.end(); ++it )
1992  {
1993  QDomElement attributeEditorWidgetElem = ( *it )->toDomElement( doc );
1994  tabsElem.appendChild( attributeEditorWidgetElem );
1995  }
1996 
1997  node.appendChild( tabsElem );
1998  }
1999 
2000  // add attribute actions
2001  mActions->writeXML( node, doc );
2002 
2003  return true;
2004 }
2005 
2006 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
2007 {
2008  // get the Name element
2009  QDomElement nameElem = node.firstChildElement( "Name" );
2010  if ( nameElem.isNull() )
2011  {
2012  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
2013  }
2014 
2015  if ( hasGeometryType() )
2016  {
2017  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
2018  if ( !r )
2019  return false;
2020 
2021  setRendererV2( r );
2022 
2023  // labeling
2024  readSldLabeling( node );
2025  }
2026  return true;
2027 }
2028 
2029 
2030 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2031 {
2032  Q_UNUSED( errorMessage );
2033 
2034  // store the Name element
2035  QDomElement nameNode = doc.createElement( "se:Name" );
2036  nameNode.appendChild( doc.createTextNode( name() ) );
2037  node.appendChild( nameNode );
2038 
2039  if ( hasGeometryType() )
2040  {
2041  node.appendChild( mRendererV2->writeSld( doc, name() ) );
2042  }
2043  return true;
2044 }
2045 
2046 
2048 {
2049  if ( !mEditBuffer || !mDataProvider )
2050  {
2051  return false;
2052  }
2053 
2054  updateExtents();
2055 
2056  return mEditBuffer->changeGeometry( fid, geom );
2057 }
2058 
2059 
2060 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, QVariant value, bool emitSignal )
2061 {
2062  Q_UNUSED( emitSignal );
2063  return changeAttributeValue( fid, field, value );
2064 }
2065 
2066 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2067 {
2068  if ( !mEditBuffer || !mDataProvider )
2069  return false;
2070 
2071  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2072 }
2073 
2075 {
2076  if ( !mEditBuffer || !mDataProvider )
2077  return false;
2078 
2079  return mEditBuffer->addAttribute( field );
2080 }
2081 
2083 {
2084  if ( attIndex < 0 || attIndex >= pendingFields().count() )
2085  return;
2086 
2087  QString name = pendingFields()[ attIndex ].name();
2088  if ( mAttributeAliasMap.contains( name ) )
2089  {
2090  mAttributeAliasMap.remove( name );
2091  emit layerModified();
2092  }
2093 }
2094 
2095 void QgsVectorLayer::addAttributeAlias( int attIndex, QString aliasString )
2096 {
2097  if ( attIndex < 0 || attIndex >= pendingFields().count() )
2098  return;
2099 
2100  QString name = pendingFields()[ attIndex ].name();
2101 
2102  mAttributeAliasMap.insert( name, aliasString );
2103  emit layerModified(); // TODO[MD]: should have a different signal?
2104 }
2105 
2107 {
2108  mAttributeEditorElements.append( data );
2109 }
2110 
2111 const QString QgsVectorLayer::editorWidgetV2( int fieldIdx ) const
2112 {
2113  if ( fieldIdx < 0 || fieldIdx >= mUpdatedFields.count() )
2114  return "TextEdit";
2115 
2116  return mEditorWidgetV2Types.value( mUpdatedFields[fieldIdx].name(), "TextEdit" );
2117 }
2118 
2119 const QString QgsVectorLayer::editorWidgetV2( const QString& fieldName ) const
2120 {
2121  return mEditorWidgetV2Types.value( fieldName, "TextEdit" );
2122 }
2123 
2125 {
2126  if ( fieldIdx < 0 || fieldIdx >= mUpdatedFields.count() )
2127  return QgsEditorWidgetConfig();
2128 
2129  return mEditorWidgetV2Configs.value( mUpdatedFields[fieldIdx].name() );
2130 }
2131 
2132 const QgsEditorWidgetConfig QgsVectorLayer::editorWidgetV2Config( const QString& fieldName ) const
2133 {
2134  return mEditorWidgetV2Configs.value( fieldName );
2135 }
2136 
2137 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2138 {
2139  if ( attributeIndex < 0 || attributeIndex >= pendingFields().count() )
2140  return "";
2141 
2142  QString name = pendingFields()[ attributeIndex ].name();
2143 
2144  return mAttributeAliasMap.value( name, "" );
2145 }
2146 
2147 QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
2148 {
2149  QString displayName = attributeAlias( attributeIndex );
2150  if ( displayName.isEmpty() )
2151  {
2152  const QgsFields& fields = pendingFields();
2153  if ( attributeIndex >= 0 && attributeIndex < fields.count() )
2154  {
2155  displayName = fields[attributeIndex].name();
2156  }
2157  }
2158  return displayName;
2159 }
2160 
2162 {
2163  if ( index < 0 || index >= pendingFields().count() )
2164  return false;
2165 
2166  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2167  {
2168  removeExpressionField( index );
2169  return true;
2170  }
2171 
2172  if ( !mEditBuffer || !mDataProvider )
2173  return false;
2174 
2175  return mEditBuffer->deleteAttribute( index );
2176 }
2177 
2178 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
2179 {
2180  bool deleted = false;
2181 
2182  // Remove multiple occurrences of same attribute
2183  attrs = attrs.toSet().toList();
2184 
2185  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2186 
2187  Q_FOREACH ( int attr, attrs )
2188  {
2189  if ( deleteAttribute( attr ) )
2190  {
2191  deleted = true;
2192  }
2193  }
2194 
2195  return deleted;
2196 }
2197 
2199 {
2200  if ( !mEditBuffer )
2201  return false;
2202 
2203  bool res = mEditBuffer->deleteFeature( fid );
2204  if ( res )
2205  mSelectedFeatureIds.remove( fid ); // remove it from selection
2206 
2207  updateExtents();
2208 
2209  return res;
2210 }
2211 
2213 {
2214  return mUpdatedFields;
2215 }
2216 
2218 {
2219  return mUpdatedFields.allAttributesList();
2220 }
2221 
2223 {
2224  QgsAttributeList pkAttributesList;
2225 
2226  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2227  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2228  {
2229  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2230  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2231  pkAttributesList << i;
2232  }
2233 
2234  return pkAttributesList;
2235 }
2236 
2238 {
2239  return mDataProvider->featureCount() +
2240  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2241 }
2242 
2244 {
2245  mCommitErrors.clear();
2246 
2247  if ( !mDataProvider )
2248  {
2249  mCommitErrors << tr( "ERROR: no provider" );
2250  return false;
2251  }
2252 
2253  if ( !mEditBuffer )
2254  {
2255  mCommitErrors << tr( "ERROR: layer not editable" );
2256  return false;
2257  }
2258 
2259  emit beforeCommitChanges();
2260 
2261  bool success = mEditBuffer->commitChanges( mCommitErrors );
2262 
2263  if ( success )
2264  {
2265  delete mEditBuffer;
2266  mEditBuffer = 0;
2267  undoStack()->clear();
2268  emit editingStopped();
2269  }
2270  else
2271  {
2272  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2273  }
2274 
2275  if ( mCache )
2276  {
2277  mCache->deleteCachedGeometries();
2278  }
2279 
2280  updateFields();
2281  mDataProvider->updateExtents();
2282 
2283  emit repaintRequested();
2284 
2285  return success;
2286 }
2287 
2288 const QStringList &QgsVectorLayer::commitErrors()
2289 {
2290  return mCommitErrors;
2291 }
2292 
2293 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2294 {
2295  if ( !mEditBuffer )
2296  {
2297  return false;
2298  }
2299 
2300  emit beforeRollBack();
2301 
2302  mEditBuffer->rollBack();
2303 
2304  if ( isModified() )
2305  {
2306  // new undo stack roll back method
2307  // old method of calling every undo could cause many canvas refreshes
2308  undoStack()->setIndex( 0 );
2309  }
2310 
2311  updateFields();
2312 
2313  if ( deleteBuffer )
2314  {
2315  delete mEditBuffer;
2316  mEditBuffer = 0;
2317  undoStack()->clear();
2318  }
2319  emit editingStopped();
2320 
2321  if ( mCache )
2322  {
2323  mCache->deleteCachedGeometries();
2324  }
2325 
2326  emit repaintRequested();
2327  return true;
2328 }
2329 
2331 {
2332  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - ids;
2333 
2334  mSelectedFeatureIds = ids;
2335 
2336  emit selectionChanged( ids, deselectedFeatures, true );
2337 }
2338 
2340 {
2341  return mSelectedFeatureIds.size();
2342 }
2343 
2345 {
2346  return mSelectedFeatureIds;
2347 }
2348 
2350 {
2351  QgsFeatureList features;
2352  QgsFeature f;
2353 
2354  if ( mSelectedFeatureIds.count() <= 8 )
2355  {
2356  // for small amount of selected features, fetch them directly
2357  // because request with FilterFids would go iterate over the whole layer
2358  foreach ( QgsFeatureId fid, mSelectedFeatureIds )
2359  {
2360  getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
2361  features << f;
2362  }
2363  }
2364  else
2365  {
2367 
2368  while ( it.nextFeature( f ) )
2369  {
2370  features.push_back( f );
2371  }
2372  }
2373 
2374  return features;
2375 }
2376 
2378 {
2379  if ( mSelectedFeatureIds.count() == 0 )
2380  return QgsFeatureIterator();
2381 
2382  if ( geometryType() == QGis::NoGeometry )
2384 
2385  if ( mSelectedFeatureIds.count() == 1 )
2386  request.setFilterFid( *mSelectedFeatureIds.constBegin() );
2387  else
2388  request.setFilterFids( mSelectedFeatureIds );
2389 
2390  return getFeatures( request );
2391 }
2392 
2393 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2394 {
2395  if ( !mEditBuffer || !mDataProvider )
2396  return false;
2397 
2398  bool res = mEditBuffer->addFeatures( features );
2399 
2400  if ( makeSelected )
2401  {
2402  QgsFeatureIds ids;
2403 
2404  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2405  ids << iter->id();
2406 
2407  setSelectedFeatures( ids );
2408  }
2409 
2410  updateExtents();
2411 
2412  return res;
2413 }
2414 
2415 
2416 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2417 {
2418  if ( !hasGeometryType() )
2419  return false;
2420 
2421  QMultiMap<double, QgsSnappingResult> snapResults;
2422  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2423 
2424  if ( result != 0 )
2425  {
2426  return false;
2427  }
2428 
2429  if ( snapResults.size() < 1 )
2430  {
2431  return false;
2432  }
2433 
2434  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
2435  point.setX( snap_it.value().snappedVertex.x() );
2436  point.setY( snap_it.value().snappedVertex.y() );
2437  return true;
2438 }
2439 
2440 
2441 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2442  QMultiMap<double, QgsSnappingResult>& snappingResults,
2443  QgsSnapper::SnappingType snap_to )
2444 {
2445  if ( !hasGeometryType() )
2446  return 1;
2447 
2448  if ( snappingTolerance <= 0 || !mDataProvider )
2449  {
2450  return 1;
2451  }
2452 
2453  QList<QgsFeature> featureList;
2454  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2455  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2456  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2457 
2458  int n = 0;
2459  QgsFeature f;
2460 
2461  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2462  {
2463  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2464  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2465  {
2466  QgsGeometry* g = &( it.value() );
2467  if ( g->boundingBox().intersects( searchRect ) )
2468  {
2469  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2470  ++n;
2471  }
2472  }
2473  }
2474  else
2475  {
2476  // snapping outside cached area
2477 
2479  .setFilterRect( searchRect )
2481  .setSubsetOfAttributes( QgsAttributeList() ) );
2482 
2483  while ( fit.nextFeature( f ) )
2484  {
2485  snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
2486  ++n;
2487  }
2488  }
2489 
2490  return n == 0 ? 2 : 0;
2491 }
2492 
2493 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2494  QgsFeatureId featureId,
2495  QgsGeometry* geom,
2496  double sqrSnappingTolerance,
2497  QMultiMap<double, QgsSnappingResult>& snappingResults,
2498  QgsSnapper::SnappingType snap_to ) const
2499 {
2500  if ( !geom )
2501  {
2502  return;
2503  }
2504 
2505  int atVertex, beforeVertex, afterVertex;
2506  double sqrDistVertexSnap, sqrDistSegmentSnap;
2507  QgsPoint snappedPoint;
2508  QgsSnappingResult snappingResultVertex;
2509  QgsSnappingResult snappingResultSegment;
2510 
2511  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2512  {
2513  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2514  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2515  {
2516  snappingResultVertex.snappedVertex = snappedPoint;
2517  snappingResultVertex.snappedVertexNr = atVertex;
2518  snappingResultVertex.beforeVertexNr = beforeVertex;
2519  if ( beforeVertex != -1 ) // make sure the vertex is valid
2520  {
2521  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2522  }
2523  snappingResultVertex.afterVertexNr = afterVertex;
2524  if ( afterVertex != -1 ) // make sure the vertex is valid
2525  {
2526  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2527  }
2528  snappingResultVertex.snappedAtGeometry = featureId;
2529  snappingResultVertex.layer = this;
2530  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2531  return;
2532  }
2533  }
2534  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2535  {
2536  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2537  {
2538  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, NULL, crs().geographicFlag() ? 1e-12 : 1e-8 );
2539 
2540  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2541  {
2542  snappingResultSegment.snappedVertex = snappedPoint;
2543  snappingResultSegment.snappedVertexNr = -1;
2544  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2545  snappingResultSegment.afterVertexNr = afterVertex;
2546  snappingResultSegment.snappedAtGeometry = featureId;
2547  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2548  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2549  snappingResultSegment.layer = this;
2550  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2551  }
2552  }
2553  }
2554 }
2555 
2556 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
2557 {
2558  QgsVectorLayerEditUtils utils( this );
2559  return utils.insertSegmentVerticesForSnap( snapResults );
2560 }
2561 
2562 
2564 {
2565  QgsDebugMsg( "----- Computing Coordinate System" );
2566 
2567  //
2568  // Get the layers project info and set up the QgsCoordinateTransform
2569  // for this layer
2570  //
2571 
2572  if ( hasGeometryType() )
2573  {
2574  // get CRS directly from provider
2575  setCrs( mDataProvider->crs() );
2576  }
2577  else
2578  {
2580  }
2581 }
2582 
2583 
2584 const QString QgsVectorLayer::displayField() const
2585 {
2586  return mDisplayField;
2587 }
2588 
2590 {
2591  mDisplayExpression = displayExpression;
2592 }
2593 
2595 {
2596  return mDisplayExpression;
2597 }
2598 
2600 {
2601  return ( mEditBuffer && mDataProvider );
2602 }
2603 
2605 {
2606  return mReadOnly;
2607 }
2608 
2609 bool QgsVectorLayer::setReadOnly( bool readonly )
2610 {
2611  // exit if the layer is in editing mode
2612  if ( readonly && mEditBuffer )
2613  return false;
2614 
2615  mReadOnly = readonly;
2616  return true;
2617 }
2618 
2620 {
2621  emit beforeModifiedCheck();
2622  return mEditBuffer && mEditBuffer->isModified();
2623 }
2624 
2626 {
2627  if ( idx < 0 || idx >= mUpdatedFields.count() )
2628  return Hidden;
2629 
2631  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
2633 }
2634 
2636 {
2637  if ( idx < 0 || idx >= mUpdatedFields.count() )
2638  return;
2639 
2641 
2643  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
2645 
2646  setEditorWidgetV2( idx, widgetType );
2647  setEditorWidgetV2Config( idx, cfg );
2648 }
2649 
2651 {
2652  return mEditorLayout;
2653 }
2654 
2656 {
2657  mEditorLayout = editorLayout;
2658 }
2659 
2660 void QgsVectorLayer::setEditorWidgetV2( int attrIdx, const QString& widgetType )
2661 {
2662  if ( attrIdx < 0 || attrIdx >= mUpdatedFields.count() )
2663  return;
2664 
2665  mEditorWidgetV2Types[ mUpdatedFields[ attrIdx ].name()] = widgetType;
2666 }
2667 
2669 {
2670  if ( attrIdx < 0 || attrIdx >= mUpdatedFields.count() )
2671  return;
2672 
2673  mEditorWidgetV2Configs[ mUpdatedFields[ attrIdx ].name()] = config;
2674 }
2675 
2677 {
2678  return mEditForm;
2679 }
2680 
2682 {
2683  if ( ui.isEmpty() || ui.isNull() )
2684  {
2686  }
2687  else
2688  {
2690  }
2691  mEditForm = ui;
2692 }
2693 
2694 void QgsVectorLayer::setAnnotationForm( const QString& ui )
2695 {
2696  mAnnotationForm = ui;
2697 }
2698 
2700 {
2701  return mEditFormInit;
2702 }
2703 
2704 void QgsVectorLayer::setEditFormInit( QString function )
2705 {
2706  mEditFormInit = function;
2707 }
2708 
2709 QMap< QString, QVariant > QgsVectorLayer::valueMap( int idx )
2710 {
2711  return editorWidgetV2Config( idx );
2712 }
2713 
2715 {
2716  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2717  return RangeData(
2718  cfg.value( "Min" ),
2719  cfg.value( "Max" ),
2720  cfg.value( "Step" )
2721  );
2722 }
2723 
2724 QString QgsVectorLayer::dateFormat( int idx )
2725 {
2726  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
2727 }
2728 
2730 {
2731  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2732  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
2733 }
2734 
2736 {
2737  const QgsFields &fields = pendingFields();
2738  if ( idx >= 0 && idx < fields.count() )
2739  {
2740  if ( mUpdatedFields.fieldOrigin( idx ) == QgsFields::OriginJoin
2741  || mUpdatedFields.fieldOrigin( idx ) == QgsFields::OriginExpression )
2742  return false;
2743  return mFieldEditables.value( fields[idx].name(), true );
2744  }
2745  else
2746  return true;
2747 }
2748 
2750 {
2751  const QgsFields &fields = pendingFields();
2752  if ( idx >= 0 && idx < fields.count() )
2753  return mLabelOnTop.value( fields[idx].name(), false );
2754  else
2755  return false;
2756 }
2757 
2758 void QgsVectorLayer::setFieldEditable( int idx, bool editable )
2759 {
2760  const QgsFields &fields = pendingFields();
2761  if ( idx >= 0 && idx < fields.count() )
2762  mFieldEditables[ fields[idx].name()] = editable;
2763 }
2764 
2765 void QgsVectorLayer::setLabelOnTop( int idx, bool onTop )
2766 {
2767  const QgsFields &fields = pendingFields();
2768  if ( idx >= 0 && idx < fields.count() )
2769  mLabelOnTop[ fields[idx].name()] = onTop;
2770 }
2771 
2773 {
2774  return mRendererV2;
2775 }
2776 
2778 {
2779  if ( !hasGeometryType() )
2780  return;
2781 
2782  if ( r != mRendererV2 )
2783  {
2784  delete mRendererV2;
2785  mRendererV2 = r;
2786  mSymbolFeatureCounted = false;
2787  mSymbolFeatureCountMap.clear();
2788 
2789  emit rendererChanged();
2790  }
2791 }
2792 
2793 
2794 
2796 {
2797  if ( !mDataProvider )
2798  {
2799  return;
2800  }
2801  if ( !mDataProvider->transaction() )
2802  {
2803  undoStack()->beginMacro( text );
2804  emit editCommandStarted( text );
2805  }
2806 }
2807 
2809 {
2810  if ( !mDataProvider )
2811  {
2812  return;
2813  }
2814  if ( !mDataProvider->transaction() )
2815  {
2816  undoStack()->endMacro();
2817  emit editCommandEnded();
2818  }
2819 }
2820 
2822 {
2823  if ( !mDataProvider )
2824  {
2825  return;
2826  }
2827  if ( !mDataProvider->transaction() )
2828  {
2829  undoStack()->endMacro();
2830  undoStack()->undo();
2831  emit editCommandDestroyed();
2832  }
2833 }
2834 
2835 
2836 void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
2837 {
2839  cfg["CheckedState"] = checked;
2840  cfg["UncheckedState"] = unchecked;
2841  setEditorWidgetV2Config( idx, cfg );
2842 }
2843 
2844 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
2845 {
2846  return pendingFields().fieldNameIndex( fieldName );
2847 }
2848 
2850 {
2851  return mJoinBuffer && mJoinBuffer->addJoin( joinInfo );
2852 }
2853 
2854 void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
2855 {
2856  removeJoin( theLayerId );
2857 }
2858 
2859 void QgsVectorLayer::removeJoin( const QString& joinLayerId )
2860 {
2861  if ( mJoinBuffer )
2862  mJoinBuffer->removeJoin( joinLayerId );
2863 }
2864 
2865 const QList< QgsVectorJoinInfo > QgsVectorLayer::vectorJoins() const
2866 {
2867  if ( mJoinBuffer )
2868  return mJoinBuffer->vectorJoins();
2869  else
2870  return QList< QgsVectorJoinInfo >();
2871 }
2872 
2873 void QgsVectorLayer::addExpressionField( const QString& exp, const QgsField& fld )
2874 {
2875  mExpressionFieldBuffer->addExpression( exp, fld );
2876  updateFields();
2877  int idx = mUpdatedFields.indexFromName( fld.name() );
2878  emit attributeAdded( idx );
2879 }
2880 
2882 {
2883  int oi = mUpdatedFields.fieldOriginIndex( index );
2884  mExpressionFieldBuffer->removeExpression( oi );
2885  updateFields();
2886  emit attributeDeleted( index );
2887 }
2888 
2890 {
2891  if ( !mDataProvider )
2892  return;
2893 
2894  QgsFields oldFields = mUpdatedFields;
2895 
2896  mUpdatedFields = mDataProvider->fields();
2897 
2898  // added / removed fields
2899  if ( mEditBuffer )
2900  mEditBuffer->updateFields( mUpdatedFields );
2901 
2902  // joined fields
2903  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
2904  mJoinBuffer->updateFields( mUpdatedFields );
2905 
2906  if ( mExpressionFieldBuffer )
2907  mExpressionFieldBuffer->updateFields( mUpdatedFields );
2908 
2909  if ( oldFields != mUpdatedFields )
2910  emit updatedFields();
2911 }
2912 
2913 
2915 {
2916  if ( mJoinBuffer->containsJoins() )
2917  {
2918  mJoinBuffer->createJoinCaches();
2919  }
2920 }
2921 
2922 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
2923 {
2924  uniqueValues.clear();
2925  if ( !mDataProvider )
2926  {
2927  return;
2928  }
2929 
2930  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
2931  if ( origin == QgsFields::OriginUnknown )
2932  {
2933  return;
2934  }
2935 
2936  if ( origin == QgsFields::OriginProvider ) //a provider field
2937  {
2938  mDataProvider->uniqueValues( index, uniqueValues, limit );
2939 
2940  if ( mEditBuffer )
2941  {
2942  QSet<QString> vals;
2943  Q_FOREACH ( const QVariant& v, uniqueValues )
2944  {
2945  vals << v.toString();
2946  }
2947 
2948  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
2949  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
2950  {
2951  it.next();
2952  QVariant v = it.value().value( index );
2953  if ( v.isValid() )
2954  {
2955  QString vs = v.toString();
2956  if ( !vals.contains( vs ) )
2957  {
2958  vals << vs;
2959  uniqueValues << v;
2960  }
2961  }
2962  }
2963  }
2964 
2965  return;
2966  }
2967  else if ( origin == QgsFields::OriginJoin )
2968  {
2969  int sourceLayerIndex;
2970  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
2971  Q_ASSERT( join );
2972 
2974 
2975  if ( vl )
2976  vl->dataProvider()->uniqueValues( sourceLayerIndex, uniqueValues, limit );
2977 
2978  return;
2979  }
2980  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
2981  {
2982  // the layer is editable, but in certain cases it can still be avoided going through all features
2983  if ( origin == QgsFields::OriginEdit && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mAddedFeatures.isEmpty() && !mEditBuffer->mDeletedAttributeIds.contains( index ) && mEditBuffer->mChangedAttributeValues.isEmpty() )
2984  {
2985  mDataProvider->uniqueValues( index, uniqueValues, limit );
2986  return;
2987  }
2988 
2989  // we need to go through each feature
2990  QgsAttributeList attList;
2991  attList << index;
2992 
2994  .setFlags( QgsFeatureRequest::NoGeometry )
2995  .setSubsetOfAttributes( attList ) );
2996 
2997  QgsFeature f;
2998  QVariant currentValue;
2999  QHash<QString, QVariant> val;
3000  while ( fit.nextFeature( f ) )
3001  {
3002  currentValue = f.attribute( index );
3003  val.insert( currentValue.toString(), currentValue );
3004  if ( limit >= 0 && val.size() >= limit )
3005  {
3006  break;
3007  }
3008  }
3009 
3010  uniqueValues = val.values();
3011  return;
3012  }
3013 
3014  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
3015 }
3016 
3018 {
3019  if ( !mDataProvider )
3020  {
3021  return QVariant();
3022  }
3023 
3024  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
3025  if ( origin == QgsFields::OriginUnknown )
3026  {
3027  return QVariant();
3028  }
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  if ( origin == QgsFields::OriginUnknown )
3092  {
3093  return QVariant();
3094  }
3095 
3096  if ( origin == QgsFields::OriginProvider ) //a provider field
3097  {
3098  return mDataProvider->maximumValue( index );
3099  }
3100  else if ( origin == QgsFields::OriginJoin )
3101  {
3102  int sourceLayerIndex;
3103  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
3104  Q_ASSERT( join );
3105 
3107  Q_ASSERT( vl );
3108 
3109  return vl->maximumValue( sourceLayerIndex );
3110  }
3111  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
3112  {
3113  // the layer is editable, but in certain cases it can still be avoided going through all features
3114  if ( origin == QgsFields::OriginEdit &&
3115  mEditBuffer->mDeletedFeatureIds.isEmpty() &&
3116  mEditBuffer->mAddedFeatures.isEmpty() &&
3117  !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
3118  mEditBuffer->mChangedAttributeValues.isEmpty() )
3119  {
3120  return mDataProvider->maximumValue( index );
3121  }
3122 
3123  // we need to go through each feature
3124  QgsAttributeList attList;
3125  attList << index;
3126 
3128  .setFlags( QgsFeatureRequest::NoGeometry )
3129  .setSubsetOfAttributes( attList ) );
3130 
3131  QgsFeature f;
3133  double currentValue = 0;
3134  while ( fit.nextFeature( f ) )
3135  {
3136  currentValue = f.attribute( index ).toDouble();
3137  if ( currentValue > maximumValue )
3138  {
3139  maximumValue = currentValue;
3140  }
3141  }
3142  return QVariant( maximumValue );
3143  }
3144 
3145  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3146  return QVariant();
3147 }
3148 
3150 void QgsVectorLayer::setFeatureBlendMode( const QPainter::CompositionMode &featureBlendMode )
3151 {
3152  mFeatureBlendMode = featureBlendMode;
3153  emit featureBlendModeChanged( featureBlendMode );
3154 }
3155 
3157 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3158 {
3159  return mFeatureBlendMode;
3160 }
3161 
3164 {
3165  mLayerTransparency = layerTransparency;
3166  emit layerTransparencyChanged( layerTransparency );
3167 }
3168 
3171 {
3172  return mLayerTransparency;
3173 }
3174 
3175 
3176 
3177 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3178 {
3179  QDomElement element = node.toElement();
3180  if ( element.isNull() )
3181  return;
3182 
3183  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3184  if ( userStyleElem.isNull() )
3185  {
3186  QgsDebugMsg( "Info: UserStyle element not found." );
3187  return;
3188  }
3189 
3190  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3191  if ( featureTypeStyleElem.isNull() )
3192  {
3193  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3194  return;
3195  }
3196 
3197  // use last rule
3198  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3199  if ( ruleElem.isNull() )
3200  {
3201  QgsDebugMsg( "Info: Rule element not found." );
3202  return;
3203  }
3204 
3205  // use last text symbolizer
3206  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3207  if ( textSymbolizerElem.isNull() )
3208  {
3209  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3210  return;
3211  }
3212 
3213  // Label
3214  setCustomProperty( "labeling/enabled", false );
3215  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3216  if ( !labelElem.isNull() )
3217  {
3218  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3219  if ( !propertyNameElem.isNull() )
3220  {
3221  // enable labeling
3222  setCustomProperty( "labeling", "pal" );
3223  setCustomProperty( "labeling/enabled", true );
3224 
3225  // set labeling defaults
3226  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3227  setCustomProperty( "labeling/fontItalic", false );
3228  setCustomProperty( "labeling/fontSize", 10 );
3229  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3230  setCustomProperty( "labeling/fontBold", false );
3231  setCustomProperty( "labeling/fontUnderline", false );
3232  setCustomProperty( "labeling/textColorR", 0 );
3233  setCustomProperty( "labeling/textColorG", 0 );
3234  setCustomProperty( "labeling/textColorB", 0 );
3235  setCustomProperty( "labeling/textTransp", 0 );
3236  setCustomProperty( "labeling/bufferDraw", false );
3237  setCustomProperty( "labeling/bufferSize", 1 );
3238  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3239  setCustomProperty( "labeling/bufferColorR", 255 );
3240  setCustomProperty( "labeling/bufferColorG", 255 );
3241  setCustomProperty( "labeling/bufferColorB", 255 );
3242  setCustomProperty( "labeling/bufferTransp", 0 );
3243  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3244  setCustomProperty( "labeling/xOffset", 0 );
3245  setCustomProperty( "labeling/yOffset", 0 );
3246  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3247  setCustomProperty( "labeling/angleOffset", 0 );
3248 
3249  // label attribute
3250  QString labelAttribute = propertyNameElem.text();
3251  setCustomProperty( "labeling/fieldName", labelAttribute );
3252  setCustomProperty( "labeling/isExpression", false );
3253 
3254  int fieldIndex = fieldNameIndex( labelAttribute );
3255  if ( fieldIndex == -1 )
3256  {
3257  // label attribute is not in columns, check if it is an expression
3258  QgsExpression exp( labelAttribute );
3259  if ( !exp.hasEvalError() )
3260  {
3261  setCustomProperty( "labeling/isExpression", true );
3262  }
3263  else
3264  {
3265  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3266  }
3267  }
3268  }
3269  else
3270  {
3271  QgsDebugMsg( "Info: PropertyName element not found." );
3272  return;
3273  }
3274  }
3275  else
3276  {
3277  QgsDebugMsg( "Info: Label element not found." );
3278  return;
3279  }
3280 
3281  // Font
3282  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3283  if ( !fontElem.isNull() )
3284  {
3285  QString cssName;
3286  QString elemText;
3287  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3288  while ( !cssElem.isNull() )
3289  {
3290  cssName = cssElem.attribute( "name", "not_found" );
3291  if ( cssName != "not_found" )
3292  {
3293  elemText = cssElem.text();
3294  if ( cssName == "font-family" )
3295  {
3296  setCustomProperty( "labeling/fontFamily", elemText );
3297  }
3298  else if ( cssName == "font-style" )
3299  {
3300  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3301  }
3302  else if ( cssName == "font-size" )
3303  {
3304  bool ok;
3305  int fontSize = elemText.toInt( &ok );
3306  if ( ok )
3307  {
3308  setCustomProperty( "labeling/fontSize", fontSize );
3309  }
3310  }
3311  else if ( cssName == "font-weight" )
3312  {
3313  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3314  }
3315  else if ( cssName == "font-underline" )
3316  {
3317  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3318  }
3319  }
3320 
3321  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3322  }
3323  }
3324 
3325  // Fill
3326  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3327  if ( textColor.isValid() )
3328  {
3329  setCustomProperty( "labeling/textColorR", textColor.red() );
3330  setCustomProperty( "labeling/textColorG", textColor.green() );
3331  setCustomProperty( "labeling/textColorB", textColor.blue() );
3332  setCustomProperty( "labeling/textTransp", 100 - ( int )( 100 * textColor.alphaF() ) );
3333  }
3334 
3335  // Halo
3336  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3337  if ( !haloElem.isNull() )
3338  {
3339  setCustomProperty( "labeling/bufferDraw", true );
3340  setCustomProperty( "labeling/bufferSize", 1 );
3341 
3342  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3343  if ( !radiusElem.isNull() )
3344  {
3345  bool ok;
3346  double bufferSize = radiusElem.text().toDouble( &ok );
3347  if ( ok )
3348  {
3349  setCustomProperty( "labeling/bufferSize", bufferSize );
3350  }
3351  }
3352 
3353  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3354  if ( bufferColor.isValid() )
3355  {
3356  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3357  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3358  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3359  setCustomProperty( "labeling/bufferTransp", 100 - ( int )( 100 * bufferColor.alphaF() ) );
3360  }
3361  }
3362 
3363  // LabelPlacement
3364  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3365  if ( !labelPlacementElem.isNull() )
3366  {
3367  // PointPlacement
3368  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3369  if ( !pointPlacementElem.isNull() )
3370  {
3371  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3372 
3373  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3374  if ( !displacementElem.isNull() )
3375  {
3376  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3377  if ( !displacementXElem.isNull() )
3378  {
3379  bool ok;
3380  double xOffset = displacementXElem.text().toDouble( &ok );
3381  if ( ok )
3382  {
3383  setCustomProperty( "labeling/xOffset", xOffset );
3384  }
3385  }
3386  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3387  if ( !displacementYElem.isNull() )
3388  {
3389  bool ok;
3390  double yOffset = displacementYElem.text().toDouble( &ok );
3391  if ( ok )
3392  {
3393  setCustomProperty( "labeling/yOffset", yOffset );
3394  }
3395  }
3396  }
3397 
3398  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
3399  if ( !rotationElem.isNull() )
3400  {
3401  bool ok;
3402  double rotation = rotationElem.text().toDouble( &ok );
3403  if ( ok )
3404  {
3405  setCustomProperty( "labeling/angleOffset", rotation );
3406  }
3407  }
3408  }
3409  }
3410 }
3411 
3413 {
3414  if ( !mDiagramLayerSettings )
3415  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3416  *mDiagramLayerSettings = s;
3417 }
3418 
3420 {
3421  QString myMetadata = "<html><body>";
3422 
3423  //-------------
3424 
3425  myMetadata += "<p class=\"subheaderglossy\">";
3426  myMetadata += tr( "General" );
3427  myMetadata += "</p>\n";
3428 
3429  // data comment
3430  if ( !( dataComment().isEmpty() ) )
3431  {
3432  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
3433  myMetadata += "<p>";
3434  myMetadata += dataComment();
3435  myMetadata += "</p>\n";
3436  }
3437 
3438  //storage type
3439  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
3440  myMetadata += "<p>";
3441  myMetadata += storageType();
3442  myMetadata += "</p>\n";
3443 
3444  if ( dataProvider() )
3445  {
3446  //provider description
3447  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
3448  myMetadata += "<p>";
3449  myMetadata += dataProvider()->description().replace( "\n", "<br>" );
3450  myMetadata += "</p>\n";
3451  }
3452 
3453  // data source
3454  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
3455  myMetadata += "<p>";
3456  myMetadata += publicSource();
3457  myMetadata += "</p>\n";
3458 
3459  //geom type
3460 
3462 
3463  if ( type < 0 || type > QGis::NoGeometry )
3464  {
3465  QgsDebugMsg( "Invalid vector type" );
3466  }
3467  else
3468  {
3469  QString typeString( QGis::vectorGeometryType( geometryType() ) );
3470 
3471  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
3472  myMetadata += "<p>";
3473  myMetadata += typeString;
3474  myMetadata += "</p>\n";
3475  }
3476 
3478  if ( !pkAttrList.isEmpty() )
3479  {
3480  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
3481  myMetadata += "<p>";
3482  foreach ( int idx, pkAttrList )
3483  {
3484  myMetadata += pendingFields()[ idx ].name() + " ";
3485  }
3486  myMetadata += "</p>\n";
3487  }
3488 
3489 
3490  //feature count
3491  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
3492  myMetadata += "<p>";
3493  myMetadata += QString::number( featureCount() );
3494  myMetadata += "</p>\n";
3495  //capabilities
3496  myMetadata += "<p class=\"glossy\">" + tr( "Editing capabilities of this layer" ) + "</p>\n";
3497  myMetadata += "<p>";
3498  myMetadata += capabilitiesString();
3499  myMetadata += "</p>\n";
3500 
3501  //-------------
3502 
3503  QgsRectangle myExtent = extent();
3504  myMetadata += "<p class=\"subheaderglossy\">";
3505  myMetadata += tr( "Extents" );
3506  myMetadata += "</p>\n";
3507 
3508  //extents in layer cs TODO...maybe make a little nested table to improve layout...
3509  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
3510  myMetadata += "<p>";
3511  // Try to be a bit clever over what number format we use for the
3512  // extents. Some people don't like it using scientific notation when the
3513  // numbers get large, but for small numbers this is the more practical
3514  // option (so we can't force the format to 'f' for all values).
3515  // The scheme:
3516  // - for all numbers with more than 5 digits, force non-scientific notation
3517  // and 2 digits after the decimal point.
3518  // - for all smaller numbers let the OS decide which format to use (it will
3519  // generally use non-scientific unless the number gets much less than 1).
3520 
3521  if ( !myExtent.isEmpty() )
3522  {
3523  QString xMin, yMin, xMax, yMax;
3524  double changeoverValue = 99999; // The 'largest' 5 digit number
3525  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
3526  {
3527  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
3528  }
3529  else
3530  {
3531  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
3532  }
3533  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
3534  {
3535  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
3536  }
3537  else
3538  {
3539  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
3540  }
3541  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
3542  {
3543  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
3544  }
3545  else
3546  {
3547  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
3548  }
3549  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
3550  {
3551  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
3552  }
3553  else
3554  {
3555  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
3556  }
3557 
3558  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3559  .arg( xMin ).arg( yMin ).arg( xMax ).arg( yMax );
3560  }
3561  else
3562  {
3563  myMetadata += tr( "unknown extent" );
3564  }
3565 
3566  myMetadata += "</p>\n";
3567 
3568  //extents in project cs
3569 
3570  try
3571  {
3572 #if 0
3573  // TODO: currently disabled, will revisit later [MD]
3574  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
3575  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3576  myMetadata += "<p>";
3577  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3578  .arg( myProjectedExtent.xMinimum() )
3579  .arg( myProjectedExtent.yMinimum() )
3580  .arg( myProjectedExtent.xMaximum() )
3581  .arg( myProjectedExtent.yMaximum() );
3582  myMetadata += "</p>\n";
3583 #endif
3584 
3585  //
3586  // Display layer spatial ref system
3587  //
3588  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
3589  myMetadata += "<p>";
3590  myMetadata += crs().toProj4().replace( QRegExp( "\"" ), " \"" );
3591  myMetadata += "</p>\n";
3592 
3593  //
3594  // Display project (output) spatial ref system
3595  //
3596 #if 0
3597  // TODO: disabled for now, will revisit later [MD]
3598  //myMetadata += "<tr><td bgcolor=\"gray\">";
3599  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
3600  myMetadata += "<p>";
3601  myMetadata += coordinateTransform->destCRS().toProj4().replace( QRegExp( "\"" ), " \"" );
3602  myMetadata += "</p>\n";
3603 #endif
3604  }
3605  catch ( QgsCsException &cse )
3606  {
3607  Q_UNUSED( cse );
3608  QgsDebugMsg( cse.what() );
3609 
3610  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3611  myMetadata += "<p>";
3612  myMetadata += tr( "(Invalid transformation of layer extents)" );
3613  myMetadata += "</p>\n";
3614 
3615  }
3616 
3617 #if 0
3618  //
3619  // Add the info about each field in the attribute table
3620  //
3621  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
3622  myMetadata += "<p>";
3623 
3624  // Start a nested table in this trow
3625  myMetadata += "<table width=\"100%\">";
3626  myMetadata += "<tr><th>";
3627  myMetadata += tr( "Field" );
3628  myMetadata += "</th>";
3629  myMetadata += "<th>";
3630  myMetadata += tr( "Type" );
3631  myMetadata += "</th>";
3632  myMetadata += "<th>";
3633  myMetadata += tr( "Length" );
3634  myMetadata += "</th>";
3635  myMetadata += "<th>";
3636  myMetadata += tr( "Precision" );
3637  myMetadata += "</th>";
3638  myMetadata += "<th>";
3639  myMetadata += tr( "Comment" );
3640  myMetadata += "</th>";
3641 
3642  //get info for each field by looping through them
3643  const QgsFields& myFields = pendingFields();
3644  for ( int i = 0, n = myFields.size(); i < n; ++i )
3645  {
3646  const QgsField& myField = fields[i];
3647 
3648  myMetadata += "<tr><td>";
3649  myMetadata += myField.name();
3650  myMetadata += "</td>";
3651  myMetadata += "<td>";
3652  myMetadata += myField.typeName();
3653  myMetadata += "</td>";
3654  myMetadata += "<td>";
3655  myMetadata += QString( "%1" ).arg( myField.length() );
3656  myMetadata += "</td>";
3657  myMetadata += "<td>";
3658  myMetadata += QString( "%1" ).arg( myField.precision() );
3659  myMetadata += "</td>";
3660  myMetadata += "<td>";
3661  myMetadata += QString( "%1" ).arg( myField.comment() );
3662  myMetadata += "</td></tr>";
3663  }
3664 
3665  //close field list
3666  myMetadata += "</table>"; //end of nested table
3667 #endif
3668 
3669  myMetadata += "</body></html>";
3670  return myMetadata;
3671 }
3672 
3674 {
3675  mSymbolFeatureCounted = false;
3676 }
3677 
3678 void QgsVectorLayer::onRelationsLoaded()
3679 {
3680  Q_FOREACH ( QgsAttributeEditorElement* elem, mAttributeEditorElements )
3681  {
3683  {
3684  QgsAttributeEditorContainer* cont = dynamic_cast< QgsAttributeEditorContainer* >( elem );
3685  if ( !cont )
3686  continue;
3687 
3688  QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
3689  Q_FOREACH ( QgsAttributeEditorElement* relElem, relations )
3690  {
3691  QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
3692  if ( !rel )
3693  continue;
3694 
3695  rel->init( QgsProject::instance()->relationManager() );
3696  }
3697  }
3698  }
3699 }
3700 
3701 void QgsVectorLayer::onJoinedFieldsChanged()
3702 {
3703  // some of the fields of joined layers have changed -> we need to update this layer's fields too
3704  updateFields();
3705 }
3706 
3708 {
3709  if ( editorWidgetV2( idx ) == "ValueRelation" )
3710  {
3712 
3713  return ValueRelationData( cfg.value( "Layer" ).toString(),
3714  cfg.value( "Key" ).toString(),
3715  cfg.value( "Value" ).toString(),
3716  cfg.value( "AllowNull" ).toBool(),
3717  cfg.value( "OrderByValue" ).toBool(),
3718  cfg.value( "AllowMulti" ).toBool(),
3719  cfg.value( "FilterExpression" ).toString()
3720  );
3721  }
3722  else
3723  {
3724  return ValueRelationData();
3725  }
3726 }
3727 
3728 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx )
3729 {
3730  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
3731 }
3732 
3733 QList<QgsAttributeEditorElement*> &QgsVectorLayer::attributeEditorElements()
3734 {
3735  return mAttributeEditorElements;
3736 }
3737 
3739 {
3740  mAttributeEditorElements.clear();
3741 }
3742 
3743 QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
3744 {
3745  QDomElement elem = doc.createElement( "attributeEditorContainer" );
3746  elem.setAttribute( "name", mName );
3747 
3748  Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
3749  {
3750  elem.appendChild( child->toDomElement( doc ) );
3751  }
3752  return elem;
3753 }
3754 
3756 {
3757  mChildren.append( widget );
3758 }
3759 
3761 {
3762  QList<QgsAttributeEditorElement*> results;
3763 
3764  Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
3765  {
3766  if ( elem->type() == type )
3767  {
3768  results.append( elem );
3769  }
3770 
3771  if ( elem->type() == AeTypeContainer )
3772  {
3773  QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
3774  if ( cont )
3775  results += cont->findElements( type );
3776  }
3777  }
3778 
3779  return results;
3780 }
3781 
3782 QDomElement QgsAttributeEditorField::toDomElement( QDomDocument& doc ) const
3783 {
3784  QDomElement elem = doc.createElement( "attributeEditorField" );
3785  elem.setAttribute( "name", mName );
3786  elem.setAttribute( "index", mIdx );
3787  return elem;
3788 }
3789 
3790 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
3791 {
3793  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3794  if ( !myLib )
3795  {
3796  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3797  return -1;
3798  }
3799  listStyles_t* listStylesExternalMethod = ( listStyles_t * ) cast_to_fptr( myLib->resolve( "listStyles" ) );
3800 
3801  if ( !listStylesExternalMethod )
3802  {
3803  delete myLib;
3804  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "listStyles" );
3805  return -1;
3806  }
3807 
3808  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
3809 }
3810 
3811 QString QgsVectorLayer::getStyleFromDatabase( QString styleId, QString &msgError )
3812 {
3814  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3815  if ( !myLib )
3816  {
3817  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3818  return QObject::tr( "" );
3819  }
3820  getStyleById_t* getStyleByIdMethod = ( getStyleById_t * ) cast_to_fptr( myLib->resolve( "getStyleById" ) );
3821 
3822  if ( !getStyleByIdMethod )
3823  {
3824  delete myLib;
3825  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "getStyleById" );
3826  return QObject::tr( "" );
3827  }
3828 
3829  return getStyleByIdMethod( mDataSource, styleId, msgError );
3830 }
3831 
3832 
3833 void QgsVectorLayer::saveStyleToDatabase( QString name, QString description,
3834  bool useAsDefault, QString uiFileContent, QString &msgError )
3835 {
3836 
3837  QString sldStyle, qmlStyle;
3839  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3840  if ( !myLib )
3841  {
3842  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3843  return;
3844  }
3845  saveStyle_t* saveStyleExternalMethod = ( saveStyle_t * ) cast_to_fptr( myLib->resolve( "saveStyle" ) );
3846 
3847  if ( !saveStyleExternalMethod )
3848  {
3849  delete myLib;
3850  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "saveStyle" );
3851  return;
3852  }
3853 
3854  QDomDocument qmlDocument, sldDocument;
3855  this->exportNamedStyle( qmlDocument, msgError );
3856  if ( !msgError.isNull() )
3857  {
3858  return;
3859  }
3860  qmlStyle = qmlDocument.toString();
3861 
3862  this->exportSldStyle( sldDocument, msgError );
3863  if ( !msgError.isNull() )
3864  {
3865  return;
3866  }
3867  sldStyle = sldDocument.toString();
3868 
3869  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
3870  description, uiFileContent, useAsDefault, msgError );
3871 }
3872 
3873 
3874 
3875 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
3876 {
3877  return loadNamedStyle( theURI, theResultFlag, false );
3878 }
3879 
3880 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
3881 {
3882  QgsDataSourceURI dsUri( theURI );
3883  if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
3884  {
3886  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3887  if ( myLib )
3888  {
3889  loadStyle_t* loadStyleExternalMethod = ( loadStyle_t * ) cast_to_fptr( myLib->resolve( "loadStyle" ) );
3890  if ( loadStyleExternalMethod )
3891  {
3892  QString qml, errorMsg;
3893  qml = loadStyleExternalMethod( mDataSource, errorMsg );
3894  if ( !qml.isEmpty() )
3895  {
3896  theResultFlag = this->applyNamedStyle( qml, errorMsg );
3897  return QObject::tr( "Loaded from Provider" );
3898  }
3899  }
3900  }
3901  }
3902 
3903  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
3904 }
3905 
3906 bool QgsVectorLayer::applyNamedStyle( QString namedStyle, QString& errorMsg )
3907 {
3908  QDomDocument myDocument( "qgis" );
3909  myDocument.setContent( namedStyle );
3910 
3911  return importNamedStyle( myDocument, errorMsg );
3912 }
3913 
3914 
3915 QDomElement QgsAttributeEditorRelation::toDomElement( QDomDocument& doc ) const
3916 {
3917  QDomElement elem = doc.createElement( "attributeEditorRelation" );
3918  elem.setAttribute( "name", mName );
3919  elem.setAttribute( "relation", mRelation.id() );
3920  return elem;
3921 }
3922 
3924 {
3925  mRelation = relationManager->relation( mRelationId );
3926  return mRelation.isValid();
3927 }
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:87
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:60
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:358
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:47
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.
const QList< QgsVectorJoinInfo > vectorJoins() const
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.
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:180
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:94
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.
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
GeometryType
Definition: qgis.h:155
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:38
void removeJoin(const QString &joinLayerId)
Removes a vector layer join.
QString publicSource() const
void beforeRollBack()
Is emitted, before changes are rolled back.
int addRing(const QList< QgsPoint > &ring, QgsFeatureId *featureId=0)
Adds a ring to polygon/multipolygon features.
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
EditorLayout
The different types to layout the attribute editor.
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
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:181
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:360
float maxScale() const
Definition: qgslabel.cpp:1399
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:365
void beginEditCommand(QString text)
Create edit command for undo/redo operations.
const QgsVectorJoinList & vectorJoins() const
int fieldNameIndex(const QString &fieldName) const
Look up field&#39;s index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:263
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&#39;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.
VertexMarkerType
Editing vertex markers.
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&#39;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:452
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:80
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.
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.
WkbType
Used for symbology operations.
Definition: qgis.h:53
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
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:179
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:156
QList< QgsRelation > referencingRelations(int idx)
Get relations, where the foreign key is on this layer.
static const int EditingCapabilities
bitmask of all provider&#39;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. ...
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
void invertSelection()
Select not selected features and deselect selected ones.
double x() const
Definition: qgspoint.h:126
it has not been specified where the field comes from
Definition: qgsfield.h:178
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...
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.
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;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.
The attribute value should not be shown in the attribute form.
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&#39;s spatial reference system.
Q_DECL_DEPRECATED EditType editType(int idx)
Get edit type.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists).
int snapWithContext(const QgsPoint &startPoint, double snappingTolerance, QMultiMap< double, QgsSnappingResult > &snappingResults, QgsSnapper::SnappingType snap_to)
Snaps to segment or vertex within given tolerance.
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&#39;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:185
bool scaleBasedVisibility() const
Definition: qgslabel.cpp:1379
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.
bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
change feature&#39;s geometry
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
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
void setFeatureBlendMode(const QPainter::CompositionMode &blendMode)
Write blend mode for features.
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.
fast access to features using their ID
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.
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()
int indexFromName(const QString &name) const
Look up field&#39;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
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&#39;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:453
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.
int addRing(const QList< QgsPoint > &ring, QgsFeatureId *featureId=0)
Adds a ring to polygon/multipolygon features.
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
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:355
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())
void setSelectedFeatures(const QgsFeatureIds &ids)
Change selection to the new set of features.
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:70
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 &#39;true&#39; 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:75
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
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&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:247
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:85
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 addExpressionField(const QString &exp, const QgsField &fld)
Add a new field which is calculated by the expression specified.
void setLayerName(const QString &name)
Set the display name of the layer.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;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:303
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&#39;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.
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)
FeatureFormSuppress
Types of feature form suppression after feature creation.
void setCoordinateSystem()
Setup the coordinate system transformation for the layer.
This is the base class for vector data providers.
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)
A vector of attributes.
Definition: qgsfeature.h:103
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:42
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void modifySelection(QgsFeatureIds selectIds, QgsFeatureIds deselectIds)
Modifies the current selection on this layer.
field is calculated from an expression
Definition: qgsfield.h:182
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
int max(int a, int b)
Definition: util.h:87
const QgsVectorLayer * layer
Layer where the snap occurred.
Definition: qgssnapper.h:56
QString joinLayerId
Source layer.
void layerModified()
This signal is emitted when modifications has been done on layer.
QgsAttributeList mDeletedAttributeIds
deleted attributes fields which are not commited.
QString evalErrorString() const
Returns evaluation error.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:280
void drawLabels(QgsRenderContext &rendererContext) override
Draws the layer labels using coordinate transformation.
bool readXML(const QDomNode &layer_node)
Reads the actions in in XML format.
virtual bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
change feature&#39;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:71
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.
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)