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