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