QGIS API Documentation  2.7.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"
71 #include "qgsvectorlayerrenderer.h"
73 
74 #include "qgsrendererv2.h"
75 #include "qgssymbolv2.h"
76 #include "qgssymbollayerv2.h"
78 #include "qgsdiagramrendererv2.h"
79 #include "qgsstylev2.h"
81 #include "qgspallabeling.h"
82 #include "qgssimplifymethod.h"
83 
84 #include "diagram/qgsdiagram.h"
85 
86 #ifdef TESTPROVIDERLIB
87 #include <dlfcn.h>
88 #endif
89 
90 typedef bool saveStyle_t(
91  const QString& uri,
92  const QString& qmlStyle,
93  const QString& sldStyle,
94  const QString& styleName,
95  const QString& styleDescription,
96  const QString& uiFileContent,
97  bool useAsDefault,
98  QString& errCause
99 );
100 
101 typedef QString loadStyle_t(
102  const QString& uri,
103  QString& errCause
104 );
105 
106 typedef int listStyles_t(
107  const QString& uri,
108  QStringList &ids,
109  QStringList &names,
110  QStringList &descriptions,
111  QString& errCause
112 );
113 
114 typedef QString getStyleById_t(
115  const QString& uri,
116  QString styleID,
117  QString& errCause
118 );
119 
120 QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
121  QString baseName,
122  QString providerKey,
123  bool loadDefaultStyleFlag )
124  : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
125  , mDataProvider( NULL )
126  , mProviderKey( providerKey )
127  , mReadOnly( false )
128  , mRendererV2( NULL )
129  , mLabel( 0 )
130  , mLabelOn( false )
131  , mLabelFontNotFoundNotified( false )
132  , mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
133  , mLayerTransparency( 0 )
134  , mVertexMarkerOnlyForSelection( false )
135  , mEditorLayout( GeneratedLayout )
136  , mFeatureFormSuppress( SuppressDefault )
137  , mCache( new QgsGeometryCache() )
138  , mEditBuffer( 0 )
139  , mJoinBuffer( 0 )
140  , mExpressionFieldBuffer( 0 )
141  , mDiagramRenderer( 0 )
142  , mDiagramLayerSettings( 0 )
143  , mValidExtent( false )
144  , mLazyExtent( true )
145  , mSymbolFeatureCounted( false )
146 
147 {
148  mActions = new QgsAttributeAction( this );
149 
150  // if we're given a provider type, try to create and bind one to this layer
151  if ( ! mProviderKey.isEmpty() )
152  {
153  setDataProvider( mProviderKey );
154  }
155  if ( mValid )
156  {
157  // Always set crs
159 
160  // check if there is a default style / propertysheet defined
161  // for this layer and if so apply it
162  bool defaultLoadedFlag = false;
163  if ( loadDefaultStyleFlag )
164  {
165  loadDefaultStyle( defaultLoadedFlag );
166  }
167 
168  // if the default style failed to load or was disabled use some very basic defaults
169  if ( !defaultLoadedFlag && hasGeometryType() )
170  {
171  // add single symbol renderer
173  }
174 
176 
177  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
178  }
179 
180  connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( selectionChanged() ) );
181 
182  connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( repaintRequested() ) );
183 
184  connect( QgsProject::instance()->relationManager(), SIGNAL( relationsLoaded() ), this, SLOT( onRelationsLoaded() ) );
185 
186  // Default simplify drawing settings
187  QSettings settings;
188  mSimplifyMethod.setSimplifyHints(( QgsVectorSimplifyMethod::SimplifyHints ) settings.value( "/qgis/simplifyDrawingHints", ( int ) mSimplifyMethod.simplifyHints() ).toInt() );
189  mSimplifyMethod.setThreshold( settings.value( "/qgis/simplifyDrawingTol", mSimplifyMethod.threshold() ).toFloat() );
190  mSimplifyMethod.setForceLocalOptimization( settings.value( "/qgis/simplifyLocal", mSimplifyMethod.forceLocalOptimization() ).toBool() );
191  mSimplifyMethod.setMaximumScale( settings.value( "/qgis/simplifyMaxScale", mSimplifyMethod.maximumScale() ).toFloat() );
192 
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 ( 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  if ( mSelectedFeatureIds.size() == 0 )
1051  return true;
1052 
1053  while ( mSelectedFeatureIds.size() > 0 )
1054  {
1055  QgsFeatureId fid = *mSelectedFeatureIds.begin();
1056  deleteFeature( fid ); // removes from selection
1057  }
1058 
1059  triggerRepaint();
1060  updateExtents();
1061 
1062  return true;
1063 }
1064 
1065 int QgsVectorLayer::addRing( const QList<QgsPoint>& ring )
1066 {
1067  if ( !mEditBuffer || !mDataProvider )
1068  return 6;
1069 
1070  QgsVectorLayerEditUtils utils( this );
1071  return utils.addRing( ring );
1072 }
1073 
1074 int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
1075 {
1076  if ( !mEditBuffer || !mDataProvider )
1077  return 7;
1078 
1079  //number of selected features must be 1
1080 
1081  if ( mSelectedFeatureIds.size() < 1 )
1082  {
1083  QgsDebugMsg( "Number of selected features <1" );
1084  return 4;
1085  }
1086  else if ( mSelectedFeatureIds.size() > 1 )
1087  {
1088  QgsDebugMsg( "Number of selected features >1" );
1089  return 5;
1090  }
1091 
1092  QgsVectorLayerEditUtils utils( this );
1093  return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1094 }
1095 
1096 
1097 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1098 {
1099  if ( !mEditBuffer || !mDataProvider )
1100  return -1;
1101 
1102  QgsVectorLayerEditUtils utils( this );
1103  return utils.translateFeature( featureId, dx, dy );
1104 }
1105 
1106 int QgsVectorLayer::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1107 {
1108  if ( !mEditBuffer || !mDataProvider )
1109  return -1;
1110 
1111  QgsVectorLayerEditUtils utils( this );
1112  return utils.splitParts( splitLine, topologicalEditing );
1113 }
1114 
1115 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
1116 {
1117  if ( !mEditBuffer || !mDataProvider )
1118  return -1;
1119 
1120  QgsVectorLayerEditUtils utils( this );
1121  return utils.splitFeatures( splitLine, topologicalEditing );
1122 }
1123 
1125 {
1126  if ( !hasGeometryType() )
1127  return 1;
1128 
1129  int returnValue = 0;
1130 
1131  //first test if geom really has type polygon or multipolygon
1132  if ( geom->type() != QGis::Polygon )
1133  {
1134  return 1;
1135  }
1136 
1137  //get bounding box of geom
1138  QgsRectangle geomBBox = geom->boundingBox();
1139 
1140  //get list of features that intersect this bounding box
1142  .setFilterRect( geomBBox )
1144  .setSubsetOfAttributes( QgsAttributeList() ) );
1145 
1146  QgsFeature f;
1147  while ( fit.nextFeature( f ) )
1148  {
1149  if ( ignoreFeatures.contains( f.id() ) )
1150  {
1151  continue;
1152  }
1153 
1154  //call geometry->makeDifference for each feature
1155  QgsGeometry *currentGeom = f.geometry();
1156  if ( currentGeom )
1157  {
1158  if ( geom->makeDifference( currentGeom ) != 0 )
1159  {
1160  returnValue = 2;
1161  }
1162  }
1163  }
1164 
1165  return returnValue;
1166 }
1167 
1169 {
1170  if ( !mEditBuffer || !mDataProvider )
1171  return -1;
1172 
1173  QgsVectorLayerEditUtils utils( this );
1174  return utils.addTopologicalPoints( geom );
1175 }
1176 
1178 {
1179  if ( !mEditBuffer || !mDataProvider )
1180  return -1;
1181 
1182  QgsVectorLayerEditUtils utils( this );
1183  return utils.addTopologicalPoints( p );
1184 }
1185 
1187 {
1188  return mLabel;
1189 }
1190 
1192 {
1193  return mLabel;
1194 }
1195 
1197 {
1198  mLabelOn = on;
1199 }
1200 
1202 {
1203  return mLabelOn;
1204 }
1205 
1207 {
1208  if ( !mDataProvider )
1209  {
1210  return false;
1211  }
1212 
1213  // allow editing if provider supports any of the capabilities
1214  if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
1215  {
1216  return false;
1217  }
1218 
1219  if ( mReadOnly )
1220  {
1221  return false;
1222  }
1223 
1224  if ( mEditBuffer )
1225  {
1226  // editing already underway
1227  return false;
1228  }
1229 
1230  mEditBuffer = new QgsVectorLayerEditBuffer( this );
1231  // forward signals
1232  connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( invalidateSymbolCountedFlag() ) );
1233  connect( mEditBuffer, SIGNAL( layerModified() ), this, SIGNAL( layerModified() ) ); // TODO[MD]: necessary?
1234  //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
1235  connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( featureAdded( QgsFeatureId ) ) );
1236  connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SIGNAL( featureDeleted( QgsFeatureId ) ) );
1237  connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
1238  connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
1239  connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), this, SIGNAL( attributeAdded( int ) ) );
1240  connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), this, SIGNAL( attributeDeleted( int ) ) );
1241  connect( mEditBuffer, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ), this, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ) );
1242  connect( mEditBuffer, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ), this, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ) );
1243 
1244  updateFields();
1245 
1246  emit editingStarted();
1247 
1248  return true;
1249 }
1250 
1251 bool QgsVectorLayer::readXml( const QDomNode& layer_node )
1252 {
1253  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
1254 
1255  //process provider key
1256  QDomNode pkeyNode = layer_node.namedItem( "provider" );
1257 
1258  if ( pkeyNode.isNull() )
1259  {
1260  mProviderKey = "";
1261  }
1262  else
1263  {
1264  QDomElement pkeyElt = pkeyNode.toElement();
1265  mProviderKey = pkeyElt.text();
1266  }
1267 
1268  // determine type of vector layer
1269  if ( ! mProviderKey.isNull() )
1270  {
1271  // if the provider string isn't empty, then we successfully
1272  // got the stored provider
1273  }
1274  else if ( mDataSource.contains( "dbname=" ) )
1275  {
1276  mProviderKey = "postgres";
1277  }
1278  else
1279  {
1280  mProviderKey = "ogr";
1281  }
1282 
1283  if ( ! setDataProvider( mProviderKey ) )
1284  {
1285  return false;
1286  }
1287 
1288  QDomElement pkeyElem = pkeyNode.toElement();
1289  if ( !pkeyElem.isNull() )
1290  {
1291  QString encodingString = pkeyElem.attribute( "encoding" );
1292  if ( !encodingString.isEmpty() )
1293  {
1294  mDataProvider->setEncoding( encodingString );
1295  }
1296  }
1297 
1298  //load vector joins
1299  if ( !mJoinBuffer )
1300  {
1301  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1302  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1303  }
1304  mJoinBuffer->readXml( layer_node );
1305 
1306  if ( !mExpressionFieldBuffer )
1307  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1308  mExpressionFieldBuffer->readXml( layer_node );
1309 
1310  updateFields();
1311  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
1312 
1313  QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );
1314 
1315  if ( prevExpNode.isNull() )
1316  {
1317  mDisplayExpression = "";
1318  }
1319  else
1320  {
1321  QDomElement prevExpElem = prevExpNode.toElement();
1322  mDisplayExpression = prevExpElem.text();
1323  }
1324 
1325  QString errorMsg;
1326  if ( !readSymbology( layer_node, errorMsg ) )
1327  {
1328  return false;
1329  }
1330 
1332 
1333  return mValid; // should be true if read successfully
1334 
1335 } // void QgsVectorLayer::readXml
1336 
1337 
1338 bool QgsVectorLayer::setDataProvider( QString const & provider )
1339 {
1340  // XXX should I check for and possibly delete any pre-existing providers?
1341  // XXX How often will that scenario occur?
1342 
1343  mProviderKey = provider; // XXX is this necessary? Usually already set
1344  // XXX when execution gets here.
1345 
1346  //XXX - This was a dynamic cast but that kills the Windows
1347  // version big-time with an abnormal termination error
1348  mDataProvider =
1350 
1351  if ( mDataProvider )
1352  {
1353  QgsDebugMsg( "Instantiated the data provider plugin" );
1354 
1355  mValid = mDataProvider->isValid();
1356  if ( mValid )
1357  {
1358  // TODO: Check if the provider has the capability to send fullExtentCalculated
1359  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
1360 
1361  // get and store the feature type
1362  mWkbType = mDataProvider->geometryType();
1363 
1364  mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
1365  connect( mJoinBuffer, SIGNAL( joinedFieldsChanged() ), this, SLOT( onJoinedFieldsChanged() ) );
1366  mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
1367  updateFields();
1368 
1369  // look at the fields in the layer and set the primary
1370  // display field using some real fuzzy logic
1371  setDisplayField();
1372 
1373  if ( mProviderKey == "postgres" )
1374  {
1375  QgsDebugMsg( "Beautifying layer name " + name() );
1376 
1377  // adjust the display name for postgres layers
1378  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
1379  if ( reg.indexIn( name() ) >= 0 )
1380  {
1381  QStringList stuff = reg.capturedTexts();
1382  QString lName = stuff[1];
1383 
1384  const QMap<QString, QgsMapLayer*> &layers = QgsMapLayerRegistry::instance()->mapLayers();
1385 
1386  QMap<QString, QgsMapLayer*>::const_iterator it;
1387  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1388  ;
1389 
1390  if ( it != layers.constEnd() && stuff.size() > 2 )
1391  {
1392  lName += "." + stuff[2].mid( 2, stuff[2].length() - 3 );
1393  }
1394 
1395  if ( !lName.isEmpty() )
1396  setLayerName( lName );
1397  }
1398 
1399  QgsDebugMsg( "Beautified layer name " + name() );
1400 
1401  // deal with unnecessary schema qualification to make v.in.ogr happy
1402  mDataSource = mDataProvider->dataSourceUri();
1403  }
1404  else if ( mProviderKey == "osm" )
1405  {
1406  // make sure that the "observer" has been removed from URI to avoid crashes
1407  mDataSource = mDataProvider->dataSourceUri();
1408  }
1409  else if ( provider == "ogr" )
1410  {
1411  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1412  mDataSource = mDataProvider->dataSourceUri();
1413  if ( mDataSource.right( 10 ) == "|layerid=0" )
1414  mDataSource.chop( 10 );
1415  }
1416 
1417  // label
1418  mLabel = new QgsLabel( mDataProvider->fields() );
1419  mLabelOn = false;
1420  }
1421  else
1422  {
1423  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
1424  return false;
1425  }
1426  }
1427  else
1428  {
1429  QgsDebugMsg( " unable to get data provider" );
1430  return false;
1431  }
1432 
1433  return true;
1434 
1435 } // QgsVectorLayer:: setDataProvider
1436 
1437 
1438 
1439 
1440 /* virtual */
1441 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
1442  QDomDocument & document )
1443 {
1444  // first get the layer element so that we can append the type attribute
1445 
1446  QDomElement mapLayerNode = layer_node.toElement();
1447 
1448  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1449  {
1450  QgsDebugMsg( "can't find <maplayer>" );
1451  return false;
1452  }
1453 
1454  mapLayerNode.setAttribute( "type", "vector" );
1455 
1456  // set the geometry type
1457  mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
1458 
1459  // add provider node
1460  if ( mDataProvider )
1461  {
1462  QDomElement provider = document.createElement( "provider" );
1463  provider.setAttribute( "encoding", mDataProvider->encoding() );
1464  QDomText providerText = document.createTextNode( providerType() );
1465  provider.appendChild( providerText );
1466  layer_node.appendChild( provider );
1467  }
1468 
1469  // save preview expression
1470  QDomElement prevExpElem = document.createElement( "previewExpression" );
1471  QDomText prevExpText = document.createTextNode( mDisplayExpression );
1472  prevExpElem.appendChild( prevExpText );
1473  layer_node.appendChild( prevExpElem );
1474 
1475  //save joins
1476  mJoinBuffer->writeXml( layer_node, document );
1477 
1478  // save expression fields
1479  mExpressionFieldBuffer->writeXml( layer_node, document );
1480 
1481  // renderer specific settings
1482  QString errorMsg;
1483  return writeSymbology( layer_node, document, errorMsg );
1484 } // bool QgsVectorLayer::writeXml
1485 
1486 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
1487 {
1488  emit readCustomSymbology( node.toElement(), errorMessage );
1489 
1490  if ( hasGeometryType() )
1491  {
1492  // try renderer v2 first
1493  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
1494  if ( !rendererElement.isNull() )
1495  {
1496  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
1497  if ( !r )
1498  return false;
1499 
1500  setRendererV2( r );
1501  }
1502  else
1503  {
1505  if ( !r )
1507 
1508  setRendererV2( r );
1509  }
1510 
1511  // get and set the display field if it exists.
1512  QDomNode displayFieldNode = node.namedItem( "displayfield" );
1513  if ( !displayFieldNode.isNull() )
1514  {
1515  QDomElement e = displayFieldNode.toElement();
1516  setDisplayField( e.text() );
1517  }
1518 
1519  // get and set the blend mode if it exists
1520  QDomNode blendModeNode = node.namedItem( "blendMode" );
1521  if ( !blendModeNode.isNull() )
1522  {
1523  QDomElement e = blendModeNode.toElement();
1525  }
1526 
1527  // get and set the feature blend mode if it exists
1528  QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
1529  if ( !featureBlendModeNode.isNull() )
1530  {
1531  QDomElement e = featureBlendModeNode.toElement();
1533  }
1534 
1535  // get and set the layer transparency if it exists
1536  QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
1537  if ( !layerTransparencyNode.isNull() )
1538  {
1539  QDomElement e = layerTransparencyNode.toElement();
1540  setLayerTransparency( e.text().toInt() );
1541  }
1542 
1543  // use scale dependent visibility flag
1544  QDomElement e = node.toElement();
1545  if ( mLabel )
1546  {
1547  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
1548  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
1549  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
1550  }
1551 
1552  // get the simplification drawing settings
1553  mSimplifyMethod.setSimplifyHints(( QgsVectorSimplifyMethod::SimplifyHints ) e.attribute( "simplifyDrawingHints", "1" ).toInt() );
1554  mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
1555  mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
1556  mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
1557 
1558  //also restore custom properties (for labeling-ng)
1559  readCustomProperties( node, "labeling" );
1560 
1561  // Test if labeling is on or off
1562  QDomNode labelnode = node.namedItem( "label" );
1563  QDomElement element = labelnode.toElement();
1564  int hasLabelsEnabled = element.text().toInt();
1565  if ( hasLabelsEnabled < 1 )
1566  {
1567  enableLabels( false );
1568  }
1569  else
1570  {
1571  enableLabels( true );
1572  }
1573 
1574  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
1575 
1576  if ( !labelattributesnode.isNull() && mLabel )
1577  {
1578  QgsDebugMsg( "calling readXML" );
1579  mLabel->readXML( labelattributesnode );
1580  }
1581 
1582  //diagram renderer and diagram layer settings
1583  delete mDiagramRenderer; mDiagramRenderer = 0;
1584  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
1585  if ( !singleCatDiagramElem.isNull() )
1586  {
1587  mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
1588  mDiagramRenderer->readXML( singleCatDiagramElem, this );
1589  }
1590  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
1591  if ( !linearDiagramElem.isNull() )
1592  {
1593  mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
1594  mDiagramRenderer->readXML( linearDiagramElem, this );
1595  }
1596 
1597  if ( mDiagramRenderer )
1598  {
1599  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
1600  if ( !diagramSettingsElem.isNull() )
1601  {
1602  mDiagramLayerSettings = new QgsDiagramLayerSettings();
1603  mDiagramLayerSettings->readXML( diagramSettingsElem, this );
1604  }
1605  }
1606  }
1607 
1608  // process the attribute actions
1609  mActions->readXML( node );
1610 
1611 
1612  QDomNode editFormNode = node.namedItem( "editform" );
1613  if ( !editFormNode.isNull() )
1614  {
1615  QDomElement e = editFormNode.toElement();
1616  mEditForm = QgsProject::instance()->readPath( e.text() );
1617  }
1618 
1619  QDomNode editFormInitNode = node.namedItem( "editforminit" );
1620  if ( !editFormInitNode.isNull() )
1621  {
1622  mEditFormInit = editFormInitNode.toElement().text();
1623  }
1624 
1625  QDomNode fFSuppNode = node.namedItem( "featformsuppress" );
1626  if ( fFSuppNode.isNull() )
1627  {
1628  mFeatureFormSuppress = SuppressDefault;
1629  }
1630  else
1631  {
1632  QDomElement e = fFSuppNode.toElement();
1633  mFeatureFormSuppress = ( QgsVectorLayer::FeatureFormSuppress )e.text().toInt();
1634  }
1635 
1636  QDomNode annotationFormNode = node.namedItem( "annotationform" );
1637  if ( !annotationFormNode.isNull() )
1638  {
1639  QDomElement e = annotationFormNode.toElement();
1640  mAnnotationForm = QgsProject::instance()->readPath( e.text() );
1641  }
1642 
1643  mAttributeAliasMap.clear();
1644  QDomNode aliasesNode = node.namedItem( "aliases" );
1645  if ( !aliasesNode.isNull() )
1646  {
1647  QDomElement aliasElem;
1648 
1649  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
1650  for ( int i = 0; i < aliasNodeList.size(); ++i )
1651  {
1652  aliasElem = aliasNodeList.at( i ).toElement();
1653 
1654  QString field;
1655  if ( aliasElem.hasAttribute( "field" ) )
1656  {
1657  field = aliasElem.attribute( "field" );
1658  }
1659  else
1660  {
1661  int index = aliasElem.attribute( "index" ).toInt();
1662 
1663  if ( index >= 0 && index < pendingFields().count() )
1664  field = pendingFields()[ index ].name();
1665  }
1666 
1667  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
1668  }
1669  }
1670 
1671  // tab display
1672  QDomNode editorLayoutNode = node.namedItem( "editorlayout" );
1673  if ( editorLayoutNode.isNull() )
1674  {
1675  mEditorLayout = GeneratedLayout;
1676  }
1677  else
1678  {
1679  if ( editorLayoutNode.toElement().text() == "uifilelayout" )
1680  {
1681  mEditorLayout = UiFileLayout;
1682  }
1683  else if ( editorLayoutNode.toElement().text() == "tablayout" )
1684  {
1685  mEditorLayout = TabLayout;
1686  }
1687  else
1688  {
1689  mEditorLayout = GeneratedLayout;
1690  }
1691  }
1692 
1693  //Attributes excluded from WMS and WFS
1694  mExcludeAttributesWMS.clear();
1695  QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
1696  if ( !excludeWMSNode.isNull() )
1697  {
1698  QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
1699  for ( int i = 0; i < attributeNodeList.size(); ++i )
1700  {
1701  mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
1702  }
1703  }
1704 
1705  mExcludeAttributesWFS.clear();
1706  QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
1707  if ( !excludeWFSNode.isNull() )
1708  {
1709  QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
1710  for ( int i = 0; i < attributeNodeList.size(); ++i )
1711  {
1712  mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
1713  }
1714  }
1715 
1716  // tabs and groups display info
1717  mAttributeEditorElements.clear();
1718  QDomNode attributeEditorFormNode = node.namedItem( "attributeEditorForm" );
1719  QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
1720 
1721  for ( int i = 0; i < attributeEditorFormNodeList.size(); i++ )
1722  {
1723  QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
1724 
1725  QgsAttributeEditorElement *attributeEditorWidget = attributeEditorElementFromDomElement( elem, this );
1726  mAttributeEditorElements.append( attributeEditorWidget );
1727  }
1728 
1729  return true;
1730 }
1731 
1733 {
1734  QgsAttributeEditorElement* newElement = NULL;
1735 
1736  if ( elem.tagName() == "attributeEditorContainer" )
1737  {
1738  QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( elem.attribute( "name" ), parent );
1739 
1740  QDomNodeList childNodeList = elem.childNodes();
1741 
1742  for ( int i = 0; i < childNodeList.size(); i++ )
1743  {
1744  QDomElement childElem = childNodeList.at( i ).toElement();
1745  QgsAttributeEditorElement* myElem = attributeEditorElementFromDomElement( childElem, container );
1746  if ( myElem )
1747  container->addChildElement( myElem );
1748  }
1749 
1750  newElement = container;
1751  }
1752  else if ( elem.tagName() == "attributeEditorField" )
1753  {
1754  QString name = elem.attribute( "name" );
1755  int idx = *( dataProvider()->fieldNameMap() ).find( name );
1756  newElement = new QgsAttributeEditorField( name, idx, parent );
1757  }
1758  else if ( elem.tagName() == "attributeEditorRelation" )
1759  {
1760  // At this time, the relations are not loaded
1761  // So we only grab the id and delegate the rest to onRelationsLoaded()
1762  QString name = elem.attribute( "name" );
1763  newElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
1764  }
1765  return newElement;
1766 }
1767 
1768 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1769 {
1770  QDomElement mapLayerNode = node.toElement();
1771 
1772  emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
1773 
1774  if ( hasGeometryType() )
1775  {
1776  QDomElement rendererElement = mRendererV2->save( doc );
1777  node.appendChild( rendererElement );
1778 
1779  // use scale dependent visibility flag
1780  if ( mLabel )
1781  {
1782  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
1783  mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
1784  mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
1785  }
1786 
1787  // save the simplification drawing settings
1788  mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
1789  mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
1790  mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
1791  mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );
1792 
1793  //save customproperties (for labeling ng)
1794  writeCustomProperties( node, doc );
1795 
1796  // add the blend mode field
1797  QDomElement blendModeElem = doc.createElement( "blendMode" );
1798  QDomText blendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( blendMode() ) ) );
1799  blendModeElem.appendChild( blendModeText );
1800  node.appendChild( blendModeElem );
1801 
1802  // add the feature blend mode field
1803  QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
1804  QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( featureBlendMode() ) ) );
1805  featureBlendModeElem.appendChild( featureBlendModeText );
1806  node.appendChild( featureBlendModeElem );
1807 
1808  // add the layer transparency
1809  QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
1810  QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
1811  layerTransparencyElem.appendChild( layerTransparencyText );
1812  node.appendChild( layerTransparencyElem );
1813 
1814  // add the display field
1815  QDomElement dField = doc.createElement( "displayfield" );
1816  QDomText dFieldText = doc.createTextNode( displayField() );
1817  dField.appendChild( dFieldText );
1818  node.appendChild( dField );
1819 
1820  // add label node
1821  QDomElement labelElem = doc.createElement( "label" );
1822  QDomText labelText = doc.createTextNode( "" );
1823 
1824  if ( hasLabelsEnabled() )
1825  {
1826  labelText.setData( "1" );
1827  }
1828  else
1829  {
1830  labelText.setData( "0" );
1831  }
1832  labelElem.appendChild( labelText );
1833 
1834  node.appendChild( labelElem );
1835 
1836  // Now we get to do all that all over again for QgsLabel
1837 
1838  if ( mLabel )
1839  {
1840  QString fieldname = mLabel->labelField( QgsLabel::Text );
1841  if ( fieldname != "" )
1842  {
1843  dField = doc.createElement( "labelfield" );
1844  dFieldText = doc.createTextNode( fieldname );
1845  dField.appendChild( dFieldText );
1846  node.appendChild( dField );
1847  }
1848 
1849  mLabel->writeXML( node, doc );
1850  }
1851 
1852  if ( mDiagramRenderer )
1853  {
1854  mDiagramRenderer->writeXML( mapLayerNode, doc, this );
1855  if ( mDiagramLayerSettings )
1856  mDiagramLayerSettings->writeXML( mapLayerNode, doc, this );
1857  }
1858  }
1859 
1860  // FIXME
1861  // edittypes are written to the layerNode
1862  // by slot QgsEditorWidgetRegistry::writeMapLayer()
1863  // triggered by signal QgsProject::writeMapLayer()
1864  // still other editing settings are written here,
1865  // although they are not part of symbology either
1866 
1867  QDomElement efField = doc.createElement( "editform" );
1868  QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( mEditForm ) );
1869  efField.appendChild( efText );
1870  node.appendChild( efField );
1871 
1872  QDomElement efiField = doc.createElement( "editforminit" );
1873  QDomText efiText = doc.createTextNode( mEditFormInit );
1874  efiField.appendChild( efiText );
1875  node.appendChild( efiField );
1876 
1877  QDomElement fFSuppElem = doc.createElement( "featformsuppress" );
1878  QDomText fFSuppText = doc.createTextNode( QString::number( featureFormSuppress() ) );
1879  fFSuppElem.appendChild( fFSuppText );
1880  node.appendChild( fFSuppElem );
1881 
1882  QDomElement afField = doc.createElement( "annotationform" );
1883  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
1884  afField.appendChild( afText );
1885  node.appendChild( afField );
1886 
1887  // tab display
1888  QDomElement editorLayoutElem = doc.createElement( "editorlayout" );
1889  switch ( mEditorLayout )
1890  {
1891  case UiFileLayout:
1892  editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
1893  break;
1894 
1895  case TabLayout:
1896  editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
1897  break;
1898 
1899  case GeneratedLayout:
1900  default:
1901  editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
1902  break;
1903  }
1904 
1905  node.appendChild( editorLayoutElem );
1906 
1907  //attribute aliases
1908  if ( mAttributeAliasMap.size() > 0 )
1909  {
1910  QDomElement aliasElem = doc.createElement( "aliases" );
1911  QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
1912  for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
1913  {
1914  int idx = fieldNameIndex( a_it.key() );
1915  if ( idx < 0 )
1916  continue;
1917 
1918  QDomElement aliasEntryElem = doc.createElement( "alias" );
1919  aliasEntryElem.setAttribute( "field", a_it.key() );
1920  aliasEntryElem.setAttribute( "index", idx );
1921  aliasEntryElem.setAttribute( "name", a_it.value() );
1922  aliasElem.appendChild( aliasEntryElem );
1923  }
1924  node.appendChild( aliasElem );
1925  }
1926 
1927  //exclude attributes WMS
1928  QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
1929  QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
1930  for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
1931  {
1932  QDomElement attrElem = doc.createElement( "attribute" );
1933  QDomText attrText = doc.createTextNode( *attWMSIt );
1934  attrElem.appendChild( attrText );
1935  excludeWMSElem.appendChild( attrElem );
1936  }
1937  node.appendChild( excludeWMSElem );
1938 
1939  //exclude attributes WFS
1940  QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
1941  QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
1942  for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
1943  {
1944  QDomElement attrElem = doc.createElement( "attribute" );
1945  QDomText attrText = doc.createTextNode( *attWFSIt );
1946  attrElem.appendChild( attrText );
1947  excludeWFSElem.appendChild( attrElem );
1948  }
1949  node.appendChild( excludeWFSElem );
1950 
1951  // tabs and groups of edit form
1952  if ( mAttributeEditorElements.size() > 0 )
1953  {
1954  QDomElement tabsElem = doc.createElement( "attributeEditorForm" );
1955 
1956  for ( QList< QgsAttributeEditorElement* >::const_iterator it = mAttributeEditorElements.begin(); it != mAttributeEditorElements.end(); ++it )
1957  {
1958  QDomElement attributeEditorWidgetElem = ( *it )->toDomElement( doc );
1959  tabsElem.appendChild( attributeEditorWidgetElem );
1960  }
1961 
1962  node.appendChild( tabsElem );
1963  }
1964 
1965  // add attribute actions
1966  mActions->writeXML( node, doc );
1967 
1968  return true;
1969 }
1970 
1971 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
1972 {
1973  // get the Name element
1974  QDomElement nameElem = node.firstChildElement( "Name" );
1975  if ( nameElem.isNull() )
1976  {
1977  errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
1978  }
1979 
1980  if ( hasGeometryType() )
1981  {
1982  QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
1983  if ( !r )
1984  return false;
1985 
1986  setRendererV2( r );
1987 
1988  // labeling
1989  readSldLabeling( node );
1990  }
1991  return true;
1992 }
1993 
1994 
1995 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1996 {
1997  Q_UNUSED( errorMessage );
1998 
1999  // store the Name element
2000  QDomElement nameNode = doc.createElement( "se:Name" );
2001  nameNode.appendChild( doc.createTextNode( name() ) );
2002  node.appendChild( nameNode );
2003 
2004  if ( hasGeometryType() )
2005  {
2006  node.appendChild( mRendererV2->writeSld( doc, *this ) );
2007  }
2008  return true;
2009 }
2010 
2011 
2013 {
2014  if ( !mEditBuffer || !mDataProvider )
2015  {
2016  return false;
2017  }
2018 
2019  updateExtents();
2020 
2021  return mEditBuffer->changeGeometry( fid, geom );
2022 }
2023 
2024 
2025 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, QVariant value, bool emitSignal )
2026 {
2027  Q_UNUSED( emitSignal );
2028  return changeAttributeValue( fid, field, value );
2029 }
2030 
2031 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
2032 {
2033  if ( !mEditBuffer || !mDataProvider )
2034  return false;
2035 
2036  return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
2037 }
2038 
2040 {
2041  if ( !mEditBuffer || !mDataProvider )
2042  return false;
2043 
2044  return mEditBuffer->addAttribute( field );
2045 }
2046 
2048 {
2049  if ( attIndex < 0 || attIndex >= pendingFields().count() )
2050  return;
2051 
2052  QString name = pendingFields()[ attIndex ].name();
2053  if ( mAttributeAliasMap.contains( name ) )
2054  {
2055  mAttributeAliasMap.remove( name );
2056  emit layerModified();
2057  }
2058 }
2059 
2060 void QgsVectorLayer::addAttributeAlias( int attIndex, QString aliasString )
2061 {
2062  if ( attIndex < 0 || attIndex >= pendingFields().count() )
2063  return;
2064 
2065  QString name = pendingFields()[ attIndex ].name();
2066 
2067  mAttributeAliasMap.insert( name, aliasString );
2068  emit layerModified(); // TODO[MD]: should have a different signal?
2069 }
2070 
2072 {
2073  mAttributeEditorElements.append( data );
2074 }
2075 
2076 const QString QgsVectorLayer::editorWidgetV2( int fieldIdx ) const
2077 {
2078  return mEditorWidgetV2Types.value( mUpdatedFields[fieldIdx].name(), "TextEdit" );
2079 }
2080 
2081 const QString QgsVectorLayer::editorWidgetV2( const QString& fieldName ) const
2082 {
2083  return mEditorWidgetV2Types.value( fieldName, "TextEdit" );
2084 }
2085 
2087 {
2088  return mEditorWidgetV2Configs.value( mUpdatedFields[fieldIdx].name() );
2089 }
2090 
2091 const QgsEditorWidgetConfig QgsVectorLayer::editorWidgetV2Config( const QString& fieldName ) const
2092 {
2093  return mEditorWidgetV2Configs.value( fieldName );
2094 }
2095 
2096 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
2097 {
2098  if ( attributeIndex < 0 || attributeIndex >= pendingFields().count() )
2099  return "";
2100 
2101  QString name = pendingFields()[ attributeIndex ].name();
2102 
2103  return mAttributeAliasMap.value( name, "" );
2104 }
2105 
2106 QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
2107 {
2108  QString displayName = attributeAlias( attributeIndex );
2109  if ( displayName.isEmpty() )
2110  {
2111  const QgsFields& fields = pendingFields();
2112  if ( attributeIndex >= 0 && attributeIndex < fields.count() )
2113  {
2114  displayName = fields[attributeIndex].name();
2115  }
2116  }
2117  return displayName;
2118 }
2119 
2121 {
2122  if ( index < 0 || index >= pendingFields().count() )
2123  return false;
2124 
2125  if ( mUpdatedFields.fieldOrigin( index ) == QgsFields::OriginExpression )
2126  {
2127  removeExpressionField( index );
2128  return true;
2129  }
2130 
2131  if ( !mEditBuffer || !mDataProvider )
2132  return false;
2133 
2134  return mEditBuffer->deleteAttribute( index );
2135 }
2136 
2137 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
2138 {
2139  bool deleted = false;
2140 
2141  // Remove multiple occurences of same attribute
2142  attrs = attrs.toSet().toList();
2143 
2144  qSort( attrs.begin(), attrs.end(), qGreater<int>() );
2145 
2146  Q_FOREACH ( int attr, attrs )
2147  {
2148  if ( deleteAttribute( attr ) )
2149  {
2150  deleted = true;
2151  }
2152  }
2153 
2154  return deleted;
2155 }
2156 
2158 {
2159  if ( !mEditBuffer )
2160  return false;
2161 
2162  bool res = mEditBuffer->deleteFeature( fid );
2163  if ( res )
2164  mSelectedFeatureIds.remove( fid ); // remove it from selection
2165 
2166  updateExtents();
2167 
2168  return res;
2169 }
2170 
2172 {
2173  return mUpdatedFields;
2174 }
2175 
2177 {
2178  return mUpdatedFields.allAttributesList();
2179 }
2180 
2182 {
2183  QgsAttributeList pkAttributesList;
2184 
2185  QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
2186  for ( int i = 0; i < mUpdatedFields.count(); ++i )
2187  {
2188  if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
2189  providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
2190  pkAttributesList << i;
2191  }
2192 
2193  return pkAttributesList;
2194 }
2195 
2197 {
2198  return mDataProvider->featureCount() +
2199  ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
2200 }
2201 
2203 {
2204  mCommitErrors.clear();
2205 
2206  if ( !mDataProvider )
2207  {
2208  mCommitErrors << tr( "ERROR: no provider" );
2209  return false;
2210  }
2211 
2212  if ( !mEditBuffer )
2213  {
2214  mCommitErrors << tr( "ERROR: layer not editable" );
2215  return false;
2216  }
2217 
2218  emit beforeCommitChanges();
2219 
2220  bool success = mEditBuffer->commitChanges( mCommitErrors );
2221 
2222  if ( success )
2223  {
2224  delete mEditBuffer;
2225  mEditBuffer = 0;
2226  undoStack()->clear();
2227  emit editingStopped();
2228  }
2229  else
2230  {
2231  QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( "\n " ) ) );
2232  }
2233 
2234  if ( mCache )
2235  {
2236  mCache->deleteCachedGeometries();
2237  }
2238 
2239  updateFields();
2240  mDataProvider->updateExtents();
2241 
2242  emit repaintRequested();
2243 
2244  return success;
2245 }
2246 
2247 const QStringList &QgsVectorLayer::commitErrors()
2248 {
2249  return mCommitErrors;
2250 }
2251 
2252 bool QgsVectorLayer::rollBack( bool deleteBuffer )
2253 {
2254  if ( !mEditBuffer )
2255  {
2256  return false;
2257  }
2258 
2259  emit beforeRollBack();
2260 
2261  mEditBuffer->rollBack();
2262 
2263  if ( isModified() )
2264  {
2265  // new undo stack roll back method
2266  // old method of calling every undo could cause many canvas refreshes
2267  undoStack()->setIndex( 0 );
2268  }
2269 
2270  updateFields();
2271 
2272  if ( deleteBuffer )
2273  {
2274  delete mEditBuffer;
2275  mEditBuffer = 0;
2276  undoStack()->clear();
2277  }
2278  emit editingStopped();
2279 
2280  if ( mCache )
2281  {
2282  mCache->deleteCachedGeometries();
2283  }
2284 
2285  emit repaintRequested();
2286  return true;
2287 }
2288 
2290 {
2291  QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - ids;
2292 
2293  mSelectedFeatureIds = ids;
2294 
2295  emit selectionChanged( ids, deselectedFeatures, true );
2296 }
2297 
2299 {
2300  return mSelectedFeatureIds.size();
2301 }
2302 
2304 {
2305  return mSelectedFeatureIds;
2306 }
2307 
2309 {
2310  QgsFeatureList features;
2311 
2313 
2314  QgsFeature f;
2315  while ( it.nextFeature( f ) )
2316  {
2317  features.push_back( f );
2318  }
2319 
2320  return features;
2321 }
2322 
2324 {
2325  if ( geometryType() == QGis::NoGeometry )
2327 
2328  request.setFilterFids( mSelectedFeatureIds );
2329 
2330  return getFeatures( request );
2331 }
2332 
2333 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
2334 {
2335  if ( !mEditBuffer || !mDataProvider )
2336  return false;
2337 
2338  bool res = mEditBuffer->addFeatures( features );
2339 
2340  if ( makeSelected )
2341  {
2342  QgsFeatureIds ids;
2343 
2344  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
2345  ids << iter->id();
2346 
2347  setSelectedFeatures( ids );
2348  }
2349 
2350  updateExtents();
2351 
2352  return res;
2353 }
2354 
2355 
2356 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
2357 {
2358  if ( !hasGeometryType() )
2359  return false;
2360 
2361  QMultiMap<double, QgsSnappingResult> snapResults;
2362  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
2363 
2364  if ( result != 0 )
2365  {
2366  return false;
2367  }
2368 
2369  if ( snapResults.size() < 1 )
2370  {
2371  return false;
2372  }
2373 
2374  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
2375  point.setX( snap_it.value().snappedVertex.x() );
2376  point.setY( snap_it.value().snappedVertex.y() );
2377  return true;
2378 }
2379 
2380 
2381 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
2382  QMultiMap<double, QgsSnappingResult>& snappingResults,
2383  QgsSnapper::SnappingType snap_to )
2384 {
2385  if ( !hasGeometryType() )
2386  return 1;
2387 
2388  if ( snappingTolerance <= 0 || !mDataProvider )
2389  {
2390  return 1;
2391  }
2392 
2393  QList<QgsFeature> featureList;
2394  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
2395  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
2396  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
2397 
2398  int n = 0;
2399  QgsFeature f;
2400 
2401  if ( mCache->cachedGeometriesRect().contains( searchRect ) )
2402  {
2403  QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
2404  for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
2405  {
2406  QgsGeometry* g = &( it.value() );
2407  if ( g->boundingBox().intersects( searchRect ) )
2408  {
2409  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
2410  ++n;
2411  }
2412  }
2413  }
2414  else
2415  {
2416  // snapping outside cached area
2417 
2419  .setFilterRect( searchRect )
2421  .setSubsetOfAttributes( QgsAttributeList() ) );
2422 
2423  while ( fit.nextFeature( f ) )
2424  {
2425  snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
2426  ++n;
2427  }
2428  }
2429 
2430  return n == 0 ? 2 : 0;
2431 }
2432 
2433 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
2434  QgsFeatureId featureId,
2435  QgsGeometry* geom,
2436  double sqrSnappingTolerance,
2437  QMultiMap<double, QgsSnappingResult>& snappingResults,
2438  QgsSnapper::SnappingType snap_to ) const
2439 {
2440  if ( !geom )
2441  {
2442  return;
2443  }
2444 
2445  int atVertex, beforeVertex, afterVertex;
2446  double sqrDistVertexSnap, sqrDistSegmentSnap;
2447  QgsPoint snappedPoint;
2448  QgsSnappingResult snappingResultVertex;
2449  QgsSnappingResult snappingResultSegment;
2450 
2451  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
2452  {
2453  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
2454  if ( sqrDistVertexSnap < sqrSnappingTolerance )
2455  {
2456  snappingResultVertex.snappedVertex = snappedPoint;
2457  snappingResultVertex.snappedVertexNr = atVertex;
2458  snappingResultVertex.beforeVertexNr = beforeVertex;
2459  if ( beforeVertex != -1 ) // make sure the vertex is valid
2460  {
2461  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
2462  }
2463  snappingResultVertex.afterVertexNr = afterVertex;
2464  if ( afterVertex != -1 ) // make sure the vertex is valid
2465  {
2466  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
2467  }
2468  snappingResultVertex.snappedAtGeometry = featureId;
2469  snappingResultVertex.layer = this;
2470  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
2471  return;
2472  }
2473  }
2474  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
2475  {
2476  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
2477  {
2478  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, NULL, crs().geographicFlag() ? 1e-12 : 1e-8 );
2479 
2480  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
2481  {
2482  snappingResultSegment.snappedVertex = snappedPoint;
2483  snappingResultSegment.snappedVertexNr = -1;
2484  snappingResultSegment.beforeVertexNr = afterVertex - 1;
2485  snappingResultSegment.afterVertexNr = afterVertex;
2486  snappingResultSegment.snappedAtGeometry = featureId;
2487  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
2488  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
2489  snappingResultSegment.layer = this;
2490  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
2491  }
2492  }
2493  }
2494 }
2495 
2496 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
2497 {
2498  QgsVectorLayerEditUtils utils( this );
2499  return utils.insertSegmentVerticesForSnap( snapResults );
2500 }
2501 
2502 
2504 {
2505  QgsDebugMsg( "----- Computing Coordinate System" );
2506 
2507  //
2508  // Get the layers project info and set up the QgsCoordinateTransform
2509  // for this layer
2510  //
2511 
2512  if ( hasGeometryType() )
2513  {
2514  // get CRS directly from provider
2515  setCrs( mDataProvider->crs() );
2516  }
2517  else
2518  {
2520  }
2521 }
2522 
2523 
2524 const QString QgsVectorLayer::displayField() const
2525 {
2526  return mDisplayField;
2527 }
2528 
2529 void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
2530 {
2531  mDisplayExpression = displayExpression;
2532 }
2533 
2535 {
2536  return mDisplayExpression;
2537 }
2538 
2540 {
2541  return ( mEditBuffer && mDataProvider );
2542 }
2543 
2545 {
2546  return mReadOnly;
2547 }
2548 
2549 bool QgsVectorLayer::setReadOnly( bool readonly )
2550 {
2551  // exit if the layer is in editing mode
2552  if ( readonly && mEditBuffer )
2553  return false;
2554 
2555  mReadOnly = readonly;
2556  return true;
2557 }
2558 
2560 {
2561  emit beforeModifiedCheck();
2562  return mEditBuffer && mEditBuffer->isModified();
2563 }
2564 
2566 {
2568  return QgsLegacyHelpers::convertEditType( editorWidgetV2( idx ), editorWidgetV2Config( idx ), this, mUpdatedFields[ idx ].name() );
2570 }
2571 
2573 {
2575 
2577  const QString widgetType = QgsLegacyHelpers::convertEditType( type, cfg, this, mUpdatedFields[idx].name() );
2579 
2580  setEditorWidgetV2( idx, widgetType );
2581  setEditorWidgetV2Config( idx, cfg );
2582 }
2583 
2585 {
2586  return mEditorLayout;
2587 }
2588 
2590 {
2591  mEditorLayout = editorLayout;
2592 }
2593 
2594 void QgsVectorLayer::setEditorWidgetV2( int attrIdx, const QString& widgetType )
2595 {
2596  mEditorWidgetV2Types[ mUpdatedFields[ attrIdx ].name()] = widgetType;
2597 }
2598 
2600 {
2601  mEditorWidgetV2Configs[ mUpdatedFields[ attrIdx ].name()] = config;
2602 }
2603 
2605 {
2606  return mEditForm;
2607 }
2608 
2610 {
2611  if ( ui.isEmpty() || ui.isNull() )
2612  {
2614  }
2615  else
2616  {
2618  }
2619  mEditForm = ui;
2620 }
2621 
2622 void QgsVectorLayer::setAnnotationForm( const QString& ui )
2623 {
2624  mAnnotationForm = ui;
2625 }
2626 
2628 {
2629  return mEditFormInit;
2630 }
2631 
2632 void QgsVectorLayer::setEditFormInit( QString function )
2633 {
2634  mEditFormInit = function;
2635 }
2636 
2637 QMap< QString, QVariant > QgsVectorLayer::valueMap( int idx )
2638 {
2639  return editorWidgetV2Config( idx );
2640 }
2641 
2643 {
2644  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2645  return RangeData(
2646  cfg.value( "Min" ),
2647  cfg.value( "Max" ),
2648  cfg.value( "Step" )
2649  );
2650 }
2651 
2652 QString QgsVectorLayer::dateFormat( int idx )
2653 {
2654  return editorWidgetV2Config( idx ).value( "DateFormat" ).toString();
2655 }
2656 
2658 {
2659  const QgsEditorWidgetConfig cfg = editorWidgetV2Config( idx );
2660  return QSize( cfg.value( "Width" ).toInt(), cfg.value( "Height" ).toInt() );
2661 }
2662 
2664 {
2665  const QgsFields &fields = pendingFields();
2666  if ( idx >= 0 && idx < fields.count() )
2667  {
2668  if ( mUpdatedFields.fieldOrigin( idx ) == QgsFields::OriginJoin
2669  || mUpdatedFields.fieldOrigin( idx ) == QgsFields::OriginExpression )
2670  return false;
2671  return mFieldEditables.value( fields[idx].name(), true );
2672  }
2673  else
2674  return true;
2675 }
2676 
2678 {
2679  const QgsFields &fields = pendingFields();
2680  if ( idx >= 0 && idx < fields.count() )
2681  return mLabelOnTop.value( fields[idx].name(), false );
2682  else
2683  return false;
2684 }
2685 
2686 void QgsVectorLayer::setFieldEditable( int idx, bool editable )
2687 {
2688  const QgsFields &fields = pendingFields();
2689  if ( idx >= 0 && idx < fields.count() )
2690  mFieldEditables[ fields[idx].name()] = editable;
2691 }
2692 
2693 void QgsVectorLayer::setLabelOnTop( int idx, bool onTop )
2694 {
2695  const QgsFields &fields = pendingFields();
2696  if ( idx >= 0 && idx < fields.count() )
2697  mLabelOnTop[ fields[idx].name()] = onTop;
2698 }
2699 
2701 {
2702  return mRendererV2;
2703 }
2704 
2706 {
2707  if ( !hasGeometryType() )
2708  return;
2709 
2710  if ( r != mRendererV2 )
2711  {
2712  delete mRendererV2;
2713  mRendererV2 = r;
2714  mSymbolFeatureCounted = false;
2715  mSymbolFeatureCountMap.clear();
2716 
2717  emit rendererChanged();
2718  }
2719 }
2720 
2721 
2722 
2724 {
2725  undoStack()->beginMacro( text );
2726  emit editCommandStarted( text );
2727 }
2728 
2730 {
2731  undoStack()->endMacro();
2732  emit editCommandEnded();
2733 }
2734 
2736 {
2737  undoStack()->endMacro();
2738  undoStack()->undo();
2739  emit editCommandDestroyed();
2740 }
2741 
2742 
2743 void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
2744 {
2746  cfg["CheckedState"] = checked;
2747  cfg["UncheckedState"] = unchecked;
2748  setEditorWidgetV2Config( idx, cfg );
2749 }
2750 
2751 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
2752 {
2753  return pendingFields().fieldNameIndex( fieldName );
2754 }
2755 
2757 {
2758  return mJoinBuffer->addJoin( joinInfo );
2759 }
2760 
2761 void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
2762 {
2763  removeJoin( theLayerId );
2764 }
2765 
2766 void QgsVectorLayer::removeJoin( const QString& joinLayerId )
2767 {
2768  mJoinBuffer->removeJoin( joinLayerId );
2769 }
2770 
2771 const QList< QgsVectorJoinInfo >& QgsVectorLayer::vectorJoins() const
2772 {
2773  return mJoinBuffer->vectorJoins();
2774 }
2775 
2776 void QgsVectorLayer::addExpressionField( const QString& exp, const QgsField& fld )
2777 {
2778  mExpressionFieldBuffer->addExpression( exp, fld );
2779  updateFields();
2780  int idx = mUpdatedFields.indexFromName( fld.name() );
2781  emit( attributeAdded( idx ) );
2782 }
2783 
2785 {
2786  int oi = mUpdatedFields.fieldOriginIndex( index );
2787  mExpressionFieldBuffer->removeExpression( oi );
2788  updateFields();
2789  emit( attributeDeleted( index ) );
2790 }
2791 
2793 {
2794  if ( !mDataProvider )
2795  return;
2796 
2797  QgsFields oldFields = mUpdatedFields;
2798 
2799  mUpdatedFields = mDataProvider->fields();
2800 
2801  // added / removed fields
2802  if ( mEditBuffer )
2803  mEditBuffer->updateFields( mUpdatedFields );
2804 
2805  // joined fields
2806  if ( mJoinBuffer && mJoinBuffer->containsJoins() )
2807  mJoinBuffer->updateFields( mUpdatedFields );
2808 
2809  if ( mExpressionFieldBuffer )
2810  mExpressionFieldBuffer->updateFields( mUpdatedFields );
2811 
2812  if ( oldFields != mUpdatedFields )
2813  emit updatedFields();
2814 }
2815 
2816 
2818 {
2819  if ( mJoinBuffer->containsJoins() )
2820  {
2821  mJoinBuffer->createJoinCaches();
2822  }
2823 }
2824 
2825 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
2826 {
2827  uniqueValues.clear();
2828  if ( !mDataProvider )
2829  {
2830  return;
2831  }
2832 
2833  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
2834 
2835  if ( origin == QgsFields::OriginProvider ) //a provider field
2836  {
2837  mDataProvider->uniqueValues( index, uniqueValues, limit );
2838 
2839  if ( mEditBuffer )
2840  {
2841  QSet<QString> vals;
2842  Q_FOREACH ( const QVariant& v, uniqueValues )
2843  {
2844  vals << v.toString();
2845  }
2846 
2847  QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
2848  while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
2849  {
2850  it.next();
2851  QVariant v = it.value().value( index );
2852  if ( v.isValid() )
2853  {
2854  QString vs = v.toString();
2855  if ( !vals.contains( vs ) )
2856  {
2857  vals << vs;
2858  uniqueValues << v;
2859  }
2860  }
2861  }
2862  }
2863 
2864  return;
2865  }
2866  else if ( origin == QgsFields::OriginJoin )
2867  {
2868  int sourceLayerIndex;
2869  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
2870  Q_ASSERT( join );
2871 
2873  Q_ASSERT( vl );
2874 
2875  return vl->dataProvider()->uniqueValues( sourceLayerIndex, uniqueValues, limit );
2876  }
2877  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
2878  {
2879  // the layer is editable, but in certain cases it can still be avoided going through all features
2880  if ( origin == QgsFields::OriginEdit && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mAddedFeatures.isEmpty() && !mEditBuffer->mDeletedAttributeIds.contains( index ) && mEditBuffer->mChangedAttributeValues.isEmpty() )
2881  {
2882  return mDataProvider->uniqueValues( index, uniqueValues, limit );
2883  }
2884 
2885  // we need to go through each feature
2886  QgsAttributeList attList;
2887  attList << index;
2888 
2890  .setFlags( QgsFeatureRequest::NoGeometry )
2891  .setSubsetOfAttributes( attList ) );
2892 
2893  QgsFeature f;
2894  QVariant currentValue;
2895  QHash<QString, QVariant> val;
2896  while ( fit.nextFeature( f ) )
2897  {
2898  currentValue = f.attribute( index );
2899  val.insert( currentValue.toString(), currentValue );
2900  if ( limit >= 0 && val.size() >= limit )
2901  {
2902  break;
2903  }
2904  }
2905 
2906  uniqueValues = val.values();
2907  return;
2908  }
2909 
2910  Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
2911 }
2912 
2914 {
2915  if ( !mDataProvider )
2916  {
2917  return QVariant();
2918  }
2919 
2920  QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
2921 
2922  if ( origin == QgsFields::OriginProvider ) //a provider field
2923  {
2924  return mDataProvider->minimumValue( index );
2925  }
2926  else if ( origin == QgsFields::OriginJoin )
2927  {
2928  int sourceLayerIndex;
2929  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
2930  Q_ASSERT( join );
2931 
2933  Q_ASSERT( vl );
2934 
2935  return vl->minimumValue( sourceLayerIndex );
2936  }
2937  else if ( origin == QgsFields::OriginEdit || origin == QgsFields::OriginExpression )
2938  {
2939  // the layer is editable, but in certain cases it can still be avoided going through all features
2940  if ( origin == QgsFields::OriginEdit &&
2941  mEditBuffer->mDeletedFeatureIds.isEmpty() &&
2942  mEditBuffer->mAddedFeatures.isEmpty() && !
2943  mEditBuffer->mDeletedAttributeIds.contains( index ) &&
2944  mEditBuffer->mChangedAttributeValues.isEmpty() )
2945  {
2946  return mDataProvider->minimumValue( index );
2947  }
2948 
2949  // we need to go through each feature
2950  QgsAttributeList attList;
2951  attList << index;
2952 
2954  .setFlags( QgsFeatureRequest::NoGeometry )
2955  .setSubsetOfAttributes( attList ) );
2956 
2957  QgsFeature f;
2959  double currentValue = 0;
2960  while ( fit.nextFeature( f ) )
2961  {
2962  currentValue = f.attribute( index ).toDouble();
2963  if ( currentValue < minimumValue )
2964  {
2965  minimumValue = currentValue;
2966  }
2967  }
2968  return QVariant( minimumValue );
2969  }
2970 
2971  Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
2972  return QVariant();
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->maximumValue( 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->maximumValue( 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->maximumValue( 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 > maximumValue )
3026  {
3027  maximumValue = currentValue;
3028  }
3029  }
3030  return QVariant( maximumValue );
3031  }
3032 
3033  Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
3034  return QVariant();
3035 }
3036 
3038 void QgsVectorLayer::setFeatureBlendMode( const QPainter::CompositionMode &featureBlendMode )
3039 {
3040  mFeatureBlendMode = featureBlendMode;
3041  emit featureBlendModeChanged( featureBlendMode );
3042 }
3043 
3045 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
3046 {
3047  return mFeatureBlendMode;
3048 }
3049 
3051 void QgsVectorLayer::setLayerTransparency( int layerTransparency )
3052 {
3053  mLayerTransparency = layerTransparency;
3054  emit layerTransparencyChanged( layerTransparency );
3055 }
3056 
3059 {
3060  return mLayerTransparency;
3061 }
3062 
3063 
3064 
3065 void QgsVectorLayer::readSldLabeling( const QDomNode& node )
3066 {
3067  QDomElement element = node.toElement();
3068  if ( element.isNull() )
3069  return;
3070 
3071  QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
3072  if ( userStyleElem.isNull() )
3073  {
3074  QgsDebugMsg( "Info: UserStyle element not found." );
3075  return;
3076  }
3077 
3078  QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
3079  if ( featureTypeStyleElem.isNull() )
3080  {
3081  QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
3082  return;
3083  }
3084 
3085  // use last rule
3086  QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
3087  if ( ruleElem.isNull() )
3088  {
3089  QgsDebugMsg( "Info: Rule element not found." );
3090  return;
3091  }
3092 
3093  // use last text symbolizer
3094  QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
3095  if ( textSymbolizerElem.isNull() )
3096  {
3097  QgsDebugMsg( "Info: TextSymbolizer element not found." );
3098  return;
3099  }
3100 
3101  // Label
3102  setCustomProperty( "labeling/enabled", false );
3103  QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
3104  if ( !labelElem.isNull() )
3105  {
3106  QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
3107  if ( !propertyNameElem.isNull() )
3108  {
3109  // enable labeling
3110  setCustomProperty( "labeling", "pal" );
3111  setCustomProperty( "labeling/enabled", true );
3112 
3113  // set labeling defaults
3114  setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
3115  setCustomProperty( "labeling/fontItalic", false );
3116  setCustomProperty( "labeling/fontSize", 10 );
3117  setCustomProperty( "labeling/fontSizeInMapUnits", false );
3118  setCustomProperty( "labeling/fontBold", false );
3119  setCustomProperty( "labeling/fontUnderline", false );
3120  setCustomProperty( "labeling/textColorR", 0 );
3121  setCustomProperty( "labeling/textColorG", 0 );
3122  setCustomProperty( "labeling/textColorB", 0 );
3123  setCustomProperty( "labeling/textTransp", 0 );
3124  setCustomProperty( "labeling/bufferDraw", false );
3125  setCustomProperty( "labeling/bufferSize", 1 );
3126  setCustomProperty( "labeling/bufferSizeInMapUnits", false );
3127  setCustomProperty( "labeling/bufferColorR", 255 );
3128  setCustomProperty( "labeling/bufferColorG", 255 );
3129  setCustomProperty( "labeling/bufferColorB", 255 );
3130  setCustomProperty( "labeling/bufferTransp", 0 );
3131  setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
3132  setCustomProperty( "labeling/xOffset", 0 );
3133  setCustomProperty( "labeling/yOffset", 0 );
3134  setCustomProperty( "labeling/labelOffsetInMapUnits", false );
3135  setCustomProperty( "labeling/angleOffset", 0 );
3136 
3137  // label attribute
3138  QString labelAttribute = propertyNameElem.text();
3139  setCustomProperty( "labeling/fieldName", labelAttribute );
3140  setCustomProperty( "labeling/isExpression", false );
3141 
3142  int fieldIndex = fieldNameIndex( labelAttribute );
3143  if ( fieldIndex == -1 )
3144  {
3145  // label attribute is not in columns, check if it is an expression
3146  QgsExpression exp( labelAttribute );
3147  if ( !exp.hasEvalError() )
3148  {
3149  setCustomProperty( "labeling/isExpression", true );
3150  }
3151  else
3152  {
3153  QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
3154  }
3155  }
3156  }
3157  else
3158  {
3159  QgsDebugMsg( "Info: PropertyName element not found." );
3160  return;
3161  }
3162  }
3163  else
3164  {
3165  QgsDebugMsg( "Info: Label element not found." );
3166  return;
3167  }
3168 
3169  // Font
3170  QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
3171  if ( !fontElem.isNull() )
3172  {
3173  QString cssName;
3174  QString elemText;
3175  QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
3176  while ( !cssElem.isNull() )
3177  {
3178  cssName = cssElem.attribute( "name", "not_found" );
3179  if ( cssName != "not_found" )
3180  {
3181  elemText = cssElem.text();
3182  if ( cssName == "font-family" )
3183  {
3184  setCustomProperty( "labeling/fontFamily", elemText );
3185  }
3186  else if ( cssName == "font-style" )
3187  {
3188  setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
3189  }
3190  else if ( cssName == "font-size" )
3191  {
3192  bool ok;
3193  int fontSize = elemText.toInt( &ok );
3194  if ( ok )
3195  {
3196  setCustomProperty( "labeling/fontSize", fontSize );
3197  }
3198  }
3199  else if ( cssName == "font-weight" )
3200  {
3201  setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
3202  }
3203  else if ( cssName == "font-underline" )
3204  {
3205  setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
3206  }
3207  }
3208 
3209  cssElem = cssElem.nextSiblingElement( "CssParameter" );
3210  }
3211  }
3212 
3213  // Fill
3214  QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
3215  if ( textColor.isValid() )
3216  {
3217  setCustomProperty( "labeling/textColorR", textColor.red() );
3218  setCustomProperty( "labeling/textColorG", textColor.green() );
3219  setCustomProperty( "labeling/textColorB", textColor.blue() );
3220  setCustomProperty( "labeling/textTransp", 100 - ( int )( 100 * textColor.alphaF() ) );
3221  }
3222 
3223  // Halo
3224  QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
3225  if ( !haloElem.isNull() )
3226  {
3227  setCustomProperty( "labeling/bufferDraw", true );
3228  setCustomProperty( "labeling/bufferSize", 1 );
3229 
3230  QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
3231  if ( !radiusElem.isNull() )
3232  {
3233  bool ok;
3234  double bufferSize = radiusElem.text().toDouble( &ok );
3235  if ( ok )
3236  {
3237  setCustomProperty( "labeling/bufferSize", bufferSize );
3238  }
3239  }
3240 
3241  QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
3242  if ( bufferColor.isValid() )
3243  {
3244  setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
3245  setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
3246  setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
3247  setCustomProperty( "labeling/bufferTransp", 100 - ( int )( 100 * bufferColor.alphaF() ) );
3248  }
3249  }
3250 
3251  // LabelPlacement
3252  QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
3253  if ( !labelPlacementElem.isNull() )
3254  {
3255  // PointPlacement
3256  QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
3257  if ( !pointPlacementElem.isNull() )
3258  {
3259  setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );
3260 
3261  QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
3262  if ( !displacementElem.isNull() )
3263  {
3264  QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
3265  if ( !displacementXElem.isNull() )
3266  {
3267  bool ok;
3268  double xOffset = displacementXElem.text().toDouble( &ok );
3269  if ( ok )
3270  {
3271  setCustomProperty( "labeling/xOffset", xOffset );
3272  }
3273  }
3274  QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
3275  if ( !displacementYElem.isNull() )
3276  {
3277  bool ok;
3278  double yOffset = displacementYElem.text().toDouble( &ok );
3279  if ( ok )
3280  {
3281  setCustomProperty( "labeling/yOffset", yOffset );
3282  }
3283  }
3284  }
3285 
3286  QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
3287  if ( !rotationElem.isNull() )
3288  {
3289  bool ok;
3290  double rotation = rotationElem.text().toDouble( &ok );
3291  if ( ok )
3292  {
3293  setCustomProperty( "labeling/angleOffset", rotation );
3294  }
3295  }
3296  }
3297  }
3298 }
3299 
3301 {
3302  if ( !mDiagramLayerSettings )
3303  mDiagramLayerSettings = new QgsDiagramLayerSettings();
3304  *mDiagramLayerSettings = s;
3305 }
3306 
3308 {
3309  QString myMetadata = "<html><body>";
3310 
3311  //-------------
3312 
3313  myMetadata += "<p class=\"subheaderglossy\">";
3314  myMetadata += tr( "General" );
3315  myMetadata += "</p>\n";
3316 
3317  // data comment
3318  if ( !( dataComment().isEmpty() ) )
3319  {
3320  myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
3321  myMetadata += "<p>";
3322  myMetadata += dataComment();
3323  myMetadata += "</p>\n";
3324  }
3325 
3326  //storage type
3327  myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
3328  myMetadata += "<p>";
3329  myMetadata += storageType();
3330  myMetadata += "</p>\n";
3331 
3332  if ( dataProvider() )
3333  {
3334  //provider description
3335  myMetadata += "<p class=\"glossy\">" + tr( "Description of this provider" ) + "</p>\n";
3336  myMetadata += "<p>";
3337  myMetadata += dataProvider()->description().replace( "\n", "<br>" );
3338  myMetadata += "</p>\n";
3339  }
3340 
3341  // data source
3342  myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
3343  myMetadata += "<p>";
3344  myMetadata += publicSource();
3345  myMetadata += "</p>\n";
3346 
3347  //geom type
3348 
3350 
3351  if ( type < 0 || type > QGis::NoGeometry )
3352  {
3353  QgsDebugMsg( "Invalid vector type" );
3354  }
3355  else
3356  {
3357  QString typeString( QGis::vectorGeometryType( geometryType() ) );
3358 
3359  myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
3360  myMetadata += "<p>";
3361  myMetadata += typeString;
3362  myMetadata += "</p>\n";
3363  }
3364 
3366  if ( !pkAttrList.isEmpty() )
3367  {
3368  myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
3369  myMetadata += "<p>";
3370  foreach ( int idx, pkAttrList )
3371  {
3372  myMetadata += pendingFields()[ idx ].name() + " ";
3373  }
3374  myMetadata += "</p>\n";
3375  }
3376 
3377 
3378  //feature count
3379  myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
3380  myMetadata += "<p>";
3381  myMetadata += QString::number( featureCount() );
3382  myMetadata += "</p>\n";
3383  //capabilities
3384  myMetadata += "<p class=\"glossy\">" + tr( "Editing capabilities of this layer" ) + "</p>\n";
3385  myMetadata += "<p>";
3386  myMetadata += capabilitiesString();
3387  myMetadata += "</p>\n";
3388 
3389  //-------------
3390 
3391  QgsRectangle myExtent = extent();
3392  myMetadata += "<p class=\"subheaderglossy\">";
3393  myMetadata += tr( "Extents" );
3394  myMetadata += "</p>\n";
3395 
3396  //extents in layer cs TODO...maybe make a little nested table to improve layout...
3397  myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
3398  myMetadata += "<p>";
3399  // Try to be a bit clever over what number format we use for the
3400  // extents. Some people don't like it using scientific notation when the
3401  // numbers get large, but for small numbers this is the more practical
3402  // option (so we can't force the format to 'f' for all values).
3403  // The scheme:
3404  // - for all numbers with more than 5 digits, force non-scientific notation
3405  // and 2 digits after the decimal point.
3406  // - for all smaller numbers let the OS decide which format to use (it will
3407  // generally use non-scientific unless the number gets much less than 1).
3408 
3409  if ( !myExtent.isEmpty() )
3410  {
3411  QString xMin, yMin, xMax, yMax;
3412  double changeoverValue = 99999; // The 'largest' 5 digit number
3413  if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
3414  {
3415  xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
3416  }
3417  else
3418  {
3419  xMin = QString( "%1" ).arg( myExtent.xMinimum() );
3420  }
3421  if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
3422  {
3423  yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
3424  }
3425  else
3426  {
3427  yMin = QString( "%1" ).arg( myExtent.yMinimum() );
3428  }
3429  if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
3430  {
3431  xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
3432  }
3433  else
3434  {
3435  xMax = QString( "%1" ).arg( myExtent.xMaximum() );
3436  }
3437  if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
3438  {
3439  yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
3440  }
3441  else
3442  {
3443  yMax = QString( "%1" ).arg( myExtent.yMaximum() );
3444  }
3445 
3446  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3447  .arg( xMin ).arg( yMin ).arg( xMax ).arg( yMax );
3448  }
3449  else
3450  {
3451  myMetadata += tr( "unknown extent" );
3452  }
3453 
3454  myMetadata += "</p>\n";
3455 
3456  //extents in project cs
3457 
3458  try
3459  {
3460 #if 0
3461  // TODO: currently disabled, will revisit later [MD]
3462  QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
3463  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3464  myMetadata += "<p>";
3465  myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
3466  .arg( myProjectedExtent.xMinimum() )
3467  .arg( myProjectedExtent.yMinimum() )
3468  .arg( myProjectedExtent.xMaximum() )
3469  .arg( myProjectedExtent.yMaximum() );
3470  myMetadata += "</p>\n";
3471 #endif
3472 
3473  //
3474  // Display layer spatial ref system
3475  //
3476  myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
3477  myMetadata += "<p>";
3478  myMetadata += crs().toProj4().replace( QRegExp( "\"" ), " \"" );
3479  myMetadata += "</p>\n";
3480 
3481  //
3482  // Display project (output) spatial ref system
3483  //
3484 #if 0
3485  // TODO: disabled for now, will revisit later [MD]
3486  //myMetadata += "<tr><td bgcolor=\"gray\">";
3487  myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
3488  myMetadata += "<p>";
3489  myMetadata += coordinateTransform->destCRS().toProj4().replace( QRegExp( "\"" ), " \"" );
3490  myMetadata += "</p>\n";
3491 #endif
3492  }
3493  catch ( QgsCsException &cse )
3494  {
3495  Q_UNUSED( cse );
3496  QgsDebugMsg( cse.what() );
3497 
3498  myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
3499  myMetadata += "<p>";
3500  myMetadata += tr( "(Invalid transformation of layer extents)" );
3501  myMetadata += "</p>\n";
3502 
3503  }
3504 
3505 #if 0
3506  //
3507  // Add the info about each field in the attribute table
3508  //
3509  myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
3510  myMetadata += "<p>";
3511 
3512  // Start a nested table in this trow
3513  myMetadata += "<table width=\"100%\">";
3514  myMetadata += "<tr><th>";
3515  myMetadata += tr( "Field" );
3516  myMetadata += "</th>";
3517  myMetadata += "<th>";
3518  myMetadata += tr( "Type" );
3519  myMetadata += "</th>";
3520  myMetadata += "<th>";
3521  myMetadata += tr( "Length" );
3522  myMetadata += "</th>";
3523  myMetadata += "<th>";
3524  myMetadata += tr( "Precision" );
3525  myMetadata += "</th>";
3526  myMetadata += "<th>";
3527  myMetadata += tr( "Comment" );
3528  myMetadata += "</th>";
3529 
3530  //get info for each field by looping through them
3531  const QgsFields& myFields = pendingFields();
3532  for ( int i = 0, n = myFields.size(); i < n; ++i )
3533  {
3534  const QgsField& myField = fields[i];
3535 
3536  myMetadata += "<tr><td>";
3537  myMetadata += myField.name();
3538  myMetadata += "</td>";
3539  myMetadata += "<td>";
3540  myMetadata += myField.typeName();
3541  myMetadata += "</td>";
3542  myMetadata += "<td>";
3543  myMetadata += QString( "%1" ).arg( myField.length() );
3544  myMetadata += "</td>";
3545  myMetadata += "<td>";
3546  myMetadata += QString( "%1" ).arg( myField.precision() );
3547  myMetadata += "</td>";
3548  myMetadata += "<td>";
3549  myMetadata += QString( "%1" ).arg( myField.comment() );
3550  myMetadata += "</td></tr>";
3551  }
3552 
3553  //close field list
3554  myMetadata += "</table>"; //end of nested table
3555 #endif
3556 
3557  myMetadata += "</body></html>";
3558  return myMetadata;
3559 }
3560 
3562 {
3563  mSymbolFeatureCounted = false;
3564 }
3565 
3566 void QgsVectorLayer::onRelationsLoaded()
3567 {
3568  Q_FOREACH ( QgsAttributeEditorElement* elem, mAttributeEditorElements )
3569  {
3571  {
3572  QgsAttributeEditorContainer* cont = dynamic_cast< QgsAttributeEditorContainer* >( elem );
3573  QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
3574  Q_FOREACH ( QgsAttributeEditorElement* relElem, relations )
3575  {
3576  QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
3577  rel->init( QgsProject::instance()->relationManager() );
3578  }
3579  }
3580  }
3581 }
3582 
3583 void QgsVectorLayer::onJoinedFieldsChanged()
3584 {
3585  // some of the fields of joined layers have changed -> we need to update this layer's fields too
3586  updateFields();
3587 }
3588 
3590 {
3591  if ( editorWidgetV2( idx ) == "ValueRelation" )
3592  {
3594 
3595  return ValueRelationData( cfg.value( "Layer" ).toString(),
3596  cfg.value( "Key" ).toString(),
3597  cfg.value( "Value" ).toString(),
3598  cfg.value( "AllowNull" ).toBool(),
3599  cfg.value( "OrderByValue" ).toBool(),
3600  cfg.value( "AllowMulti" ).toBool(),
3601  cfg.value( "FilterExpression" ).toString()
3602  );
3603  }
3604  else
3605  {
3606  return ValueRelationData();
3607  }
3608 }
3609 
3610 QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx )
3611 {
3612  return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
3613 }
3614 
3615 QList<QgsAttributeEditorElement*> &QgsVectorLayer::attributeEditorElements()
3616 {
3617  return mAttributeEditorElements;
3618 }
3619 
3621 {
3622  mAttributeEditorElements.clear();
3623 }
3624 
3625 QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
3626 {
3627  QDomElement elem = doc.createElement( "attributeEditorContainer" );
3628  elem.setAttribute( "name", mName );
3629 
3630  Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
3631  {
3632  elem.appendChild( child->toDomElement( doc ) );
3633  }
3634  return elem;
3635 }
3636 
3638 {
3639  mChildren.append( widget );
3640 }
3641 
3643 {
3644  QList<QgsAttributeEditorElement*> results;
3645 
3646  Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
3647  {
3648  if ( elem->type() == type )
3649  {
3650  results.append( elem );
3651  }
3652 
3653  if ( elem->type() == AeTypeContainer )
3654  {
3655  QgsAttributeEditorContainer* cont = dynamic_cast<QgsAttributeEditorContainer*>( elem );
3656  results += cont->findElements( type );
3657  }
3658  }
3659 
3660  return results;
3661 }
3662 
3663 QDomElement QgsAttributeEditorField::toDomElement( QDomDocument& doc ) const
3664 {
3665  QDomElement elem = doc.createElement( "attributeEditorField" );
3666  elem.setAttribute( "name", mName );
3667  elem.setAttribute( "index", mIdx );
3668  return elem;
3669 }
3670 
3671 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
3672 {
3674  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3675  if ( !myLib )
3676  {
3677  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3678  return -1;
3679  }
3680  listStyles_t* listStylesExternalMethod = ( listStyles_t * ) cast_to_fptr( myLib->resolve( "listStyles" ) );
3681 
3682  if ( !listStylesExternalMethod )
3683  {
3684  delete myLib;
3685  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "listStyles" );
3686  return -1;
3687  }
3688 
3689  return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
3690 }
3691 
3692 QString QgsVectorLayer::getStyleFromDatabase( QString styleId, QString &msgError )
3693 {
3695  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3696  if ( !myLib )
3697  {
3698  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3699  return QObject::tr( "" );
3700  }
3701  getStyleById_t* getStyleByIdMethod = ( getStyleById_t * ) cast_to_fptr( myLib->resolve( "getStyleById" ) );
3702 
3703  if ( !getStyleByIdMethod )
3704  {
3705  delete myLib;
3706  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "getStyleById" );
3707  return QObject::tr( "" );
3708  }
3709 
3710  return getStyleByIdMethod( mDataSource, styleId, msgError );
3711 }
3712 
3713 
3714 void QgsVectorLayer::saveStyleToDatabase( QString name, QString description,
3715  bool useAsDefault, QString uiFileContent, QString &msgError )
3716 {
3717 
3718  QString sldStyle, qmlStyle;
3720  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3721  if ( !myLib )
3722  {
3723  msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
3724  return;
3725  }
3726  saveStyle_t* saveStyleExternalMethod = ( saveStyle_t * ) cast_to_fptr( myLib->resolve( "saveStyle" ) );
3727 
3728  if ( !saveStyleExternalMethod )
3729  {
3730  delete myLib;
3731  msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "saveStyle" );
3732  return;
3733  }
3734 
3735  QDomDocument qmlDocument, sldDocument;
3736  this->exportNamedStyle( qmlDocument, msgError );
3737  if ( !msgError.isNull() )
3738  {
3739  return;
3740  }
3741  qmlStyle = qmlDocument.toString();
3742 
3743  this->exportSldStyle( sldDocument, msgError );
3744  if ( !msgError.isNull() )
3745  {
3746  return;
3747  }
3748  sldStyle = sldDocument.toString();
3749 
3750  saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
3751  description, uiFileContent, useAsDefault, msgError );
3752 }
3753 
3754 
3755 
3756 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
3757 {
3758  return loadNamedStyle( theURI, theResultFlag, false );
3759 }
3760 
3761 QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag, bool loadFromLocalDB )
3762 {
3763  QgsDataSourceURI dsUri( theURI );
3764  if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
3765  {
3767  QLibrary *myLib = pReg->providerLibrary( mProviderKey );
3768  if ( myLib )
3769  {
3770  loadStyle_t* loadStyleExternalMethod = ( loadStyle_t * ) cast_to_fptr( myLib->resolve( "loadStyle" ) );
3771  if ( loadStyleExternalMethod )
3772  {
3773  QString qml, errorMsg;
3774  qml = loadStyleExternalMethod( mDataSource, errorMsg );
3775  if ( !qml.isEmpty() )
3776  {
3777  theResultFlag = this->applyNamedStyle( qml, errorMsg );
3778  return QObject::tr( "Loaded from Provider" );
3779  }
3780  }
3781  }
3782  }
3783 
3784  return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
3785 }
3786 
3787 bool QgsVectorLayer::applyNamedStyle( QString namedStyle, QString errorMsg )
3788 {
3789  QDomDocument myDocument( "qgis" );
3790  myDocument.setContent( namedStyle );
3791 
3792  QDomElement myRoot = myDocument.firstChildElement( "qgis" );
3793 
3794  if ( myRoot.isNull() )
3795  {
3796  errorMsg = tr( "Error: qgis element could not be found" );
3797  return false;
3798  }
3799  setScaleBasedVisibility( myRoot.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
3800  setMinimumScale( myRoot.attribute( "minimumScale" ).toFloat() );
3801  setMaximumScale( myRoot.attribute( "maximumScale" ).toFloat() );
3802 
3803 #if 0
3804  //read transparency level
3805  QDomNode transparencyNode = myRoot.namedItem( "transparencyLevelInt" );
3806  if ( ! transparencyNode.isNull() )
3807  {
3808  // set transparency level only if it's in project
3809  // (otherwise it sets the layer transparent)
3810  QDomElement myElement = transparencyNode.toElement();
3811  setTransparency( myElement.text().toInt() );
3812  }
3813 #endif
3814 
3815  return readSymbology( myRoot, errorMsg );
3816 }
3817 
3818 
3819 QDomElement QgsAttributeEditorRelation::toDomElement( QDomDocument& doc ) const
3820 {
3821  QDomElement elem = doc.createElement( "attributeEditorRelation" );
3822  elem.setAttribute( "name", mName );
3823  elem.setAttribute( "relation", mRelation.id() );
3824  return elem;
3825 }
3826 
3828 {
3829  mRelation = relationManager->relation( mRelationId );
3830  return mRelation.isValid();
3831 }
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.
virtual QString subsetString()
Get the string (typically sql) used to define a subset of the layer.
virtual QDomElement toDomElement(QDomDocument &doc) const
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:48
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.
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:89
bool addAttribute(const QgsField &field)
add an attribute field (but does not commit it) returns true if the field was added ...
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.
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)...
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:1397
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 drawLabels(QgsRenderContext &rendererContext)
Draws the layer labels using coordinate transformation.
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:208
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...
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.
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
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
QGis::GeometryType type()
Returns type of the vector.
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.
virtual bool writeXml(QDomNode &layer_node, QDomDocument &doc)
write vector layer specific state to project file Dom node.
Container of fields for a vector layer.
Definition: qgsfield.h:172
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.
bool readSld(const QDomNode &node, QString &errorMessage)
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.
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:1387
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()
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
QgsRectangle extent()
Return the extent of the layer as a QRect.
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)
Return new instance of QgsMapLayerRenderer that will be used for rendering of given context...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
void 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.
virtual void reload()
Synchronises with changes in the datasource.
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
fast access to features using their ID
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 ...
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:1372
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
virtual QDomElement toDomElement(QDomDocument &doc) const
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:1377
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
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:729
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:548
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
virtual bool readXml(const QDomNode &layer_node)
reads vector layer specific state from project file Dom node.
QMap< QString, int > fieldNameMap() const
Return a map where the key is the name of the field and the value is its index.
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:1022
void removeJoin(const QString &joinLayerId)
Removes a vector layer join.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
int addRing(const QList< QgsPoint > &ring)
Adds a ring to polygon/multipolygon features.
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:241
bool labelOnTop(int idx)
label widget on top
void invalidateSymbolCountedFlag()
bool readSymbology(const QDomNode &node, QString &errorMessage)
Read the symbology for the current layer from the Dom node supplied.
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
virtual QDomElement toDomElement(QDomDocument &doc) const
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 setMaximumScale(const float theMaxScale)
Sets the maximum scale denominator at which the layer will be visible.
void setY(double y)
Definition: qgspoint.h:111
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.
void setMinimumScale(const float theMinScale)
Sets the minimum scale denominator at which the layer will be visible.
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)...
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:1392
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
void setExtent(const QgsRectangle &rect)
Set the extent.
QString mDataSource
data source description string, varies by layer type
Definition: qgsmaplayer.h:551
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())
bool draw(QgsRenderContext &rendererContext)
Draws the layer.
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.
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
Definition: qgsfield.h:234
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:362
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 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.
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.
const QString & comment() const
Returns the field comment.
Definition: qgsfield.cpp:84
void setFieldEditable(int idx, bool editable)
set edit widget editable
bool deleteFeature(QgsFeatureId fid)
delete a feature from the layer (but does not commit it)
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.
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 ...
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:1382
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
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.
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
virtual bool isEditable() const
Returns true if the provider is in editing mode.
QString metadata()
Obtain Metadata for this layer.
static QgsFeatureRendererV2 * readOldRenderer(const QDomNode &layerNode, QGis::GeometryType geomType)
Read old renderer definition from XML and create matching new renderer.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
Write the symbology for the layer into the docment provided.
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 ...
bool isModified() const
Returns true if the provider has been modified since the last commit.
bool deleteSelectedFeatures()
Deletes the selected features.
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:220
virtual bool applyNamedStyle(QString namedStyle, QString errorMsg)
bool readXML(const QDomNode &layer_node)
Reads the actions in in XML format.
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
void setScaleBasedVisibility(const bool enabled)
Sets whether scale based visibility is enabled for the layer.
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)
virtual bool render()
Do the rendering (based on data stored in the class)
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)