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