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