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