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