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