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