Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator 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 /* $Id$ */
24 
25 #include <cfloat>
26 #include <cstring>
27 #include <climits>
28 #include <cmath>
29 #include <iosfwd>
30 #include <limits>
31 #include <memory>
32 #include <set>
33 #include <sstream>
34 #include <utility>
35 
36 #include <QImage>
37 #include <QPainter>
38 #include <QPainterPath>
39 #include <QPolygonF>
40 #include <QSettings>
41 #include <QString>
42 #include <QDomNode>
43 
44 #include "qgsvectorlayer.h"
45 
46 // renderers
49 #include "qgsrenderer.h"
51 #include "qgsuniquevaluerenderer.h"
52 
53 #include "qgsattributeaction.h"
54 
55 #include "qgis.h" //for globals
56 #include "qgsapplication.h"
57 #include "qgscoordinatetransform.h"
58 #include "qgsfeature.h"
59 #include "qgsfield.h"
60 #include "qgsgeometry.h"
61 #include "qgslabel.h"
62 #include "qgslogger.h"
63 #include "qgsmaptopixel.h"
64 #include "qgspoint.h"
65 #include "qgsproviderregistry.h"
66 #include "qgsrectangle.h"
67 #include "qgsrendercontext.h"
69 #include "qgsvectordataprovider.h"
72 #include "qgsvectoroverlay.h"
73 #include "qgsmaplayerregistry.h"
74 #include "qgsclipper.h"
75 #include "qgsproject.h"
76 
77 #include "qgsrendererv2.h"
78 #include "qgssymbolv2.h"
79 #include "qgssymbollayerv2.h"
81 #include "qgsdiagramrendererv2.h"
82 
83 #ifdef TESTPROVIDERLIB
84 #include <dlfcn.h>
85 #endif
86 
87 
88 static const char * const ident_ = "$Id$";
89 
90 // typedef for the QgsDataProvider class factory
91 typedef QgsDataProvider * create_it( const QString* uri );
92 
93 
94 
95 QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
96  QString baseName,
97  QString providerKey,
98  bool loadDefaultStyleFlag )
99  : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
100  , mUpdateThreshold( 0 ) // XXX better default value?
101  , mDataProvider( NULL )
102  , mProviderKey( providerKey )
103  , mEditable( false )
104  , mReadOnly( false )
105  , mModified( false )
106  , mMaxUpdatedIndex( -1 )
107  , mActiveCommand( NULL )
108  , mRenderer( 0 )
109  , mRendererV2( NULL )
110  , mUsingRendererV2( false )
111  , mLabel( 0 )
112  , mLabelOn( false )
113  , mVertexMarkerOnlyForSelection( false )
114  , mFetching( false )
115  , mJoinBuffer( 0 )
116  , mDiagramRenderer( 0 )
117  , mDiagramLayerSettings( 0 )
118 {
119  mActions = new QgsAttributeAction( this );
120 
121  // if we're given a provider type, try to create and bind one to this layer
122  if ( ! mProviderKey.isEmpty() )
123  {
125  }
126  if ( mValid )
127  {
128  // Always set crs
130 
131  QSettings settings;
132  //Changed to default to true as of QGIS 1.7
133  if ( settings.value( "/qgis/use_symbology_ng", true ).toBool() && hasGeometryType() )
134  {
135  // using symbology-ng!
136  setUsingRendererV2( true );
137  }
138 
139  // check if there is a default style / propertysheet defined
140  // for this layer and if so apply it
141  bool defaultLoadedFlag = false;
142  if ( loadDefaultStyleFlag )
143  {
144  loadDefaultStyle( defaultLoadedFlag );
145  }
146 
147  // if the default style failed to load or was disabled use some very basic defaults
148  if ( !defaultLoadedFlag && hasGeometryType() )
149  {
150  // add single symbol renderer
151  if ( mUsingRendererV2 )
152  {
154  }
155  else
156  {
158  setRenderer( renderer );
159  }
160  }
161 
163 
164  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
165  updateFieldMap();
166 
167  // Get the update threshold from user settings. We
168  // do this only on construction to avoid the penality of
169  // fetching this each time the layer is drawn. If the user
170  // changes the threshold from the preferences dialog, it will
171  // have no effect on existing layers
172  // TODO: load this setting somewhere else [MD]
173  //QSettings settings;
174  //mUpdateThreshold = settings.readNumEntry("Map/updateThreshold", 1000);
175  }
176 } // QgsVectorLayer ctor
177 
178 
179 
181 {
182  QgsDebugMsg( "entered." );
183 
184  emit layerDeleted();
185 
186  mValid = false;
187 
188  delete mRenderer;
189  delete mDataProvider;
190  delete mJoinBuffer;
191  delete mLabel;
192  delete mDiagramLayerSettings;
193 
194  // Destroy any cached geometries and clear the references to them
196 
197  delete mActions;
198 
199  //delete remaining overlays
200 
201  QList<QgsVectorOverlay*>::iterator overlayIt = mOverlays.begin();
202  for ( ; overlayIt != mOverlays.end(); ++overlayIt )
203  {
204  delete *overlayIt;
205  }
206 }
207 
209 {
210  if ( mDataProvider )
211  {
212  return mDataProvider->storageType();
213  }
214  return 0;
215 }
216 
217 
219 {
220  if ( mDataProvider )
221  {
223  }
224  return 0;
225 }
226 
228 {
229  if ( mDataProvider )
230  {
231  return mDataProvider->dataComment();
232  }
233  return QString();
234 }
235 
236 
238 {
239  return mProviderKey;
240 }
241 
245 void QgsVectorLayer::setDisplayField( QString fldName )
246 {
247  if ( !hasGeometryType() )
248  return;
249 
250  // If fldName is provided, use it as the display field, otherwise
251  // determine the field index for the feature column of the identify
252  // dialog. We look for fields containing "name" first and second for
253  // fields containing "id". If neither are found, the first field
254  // is used as the node.
255  QString idxName = "";
256  QString idxId = "";
257 
258  if ( !fldName.isEmpty() )
259  {
260  mDisplayField = fldName;
261  }
262  else
263  {
264  const QgsFieldMap &fields = pendingFields();
265  int fieldsSize = fields.size();
266 
267  for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it )
268  {
269  QString fldName = it.value().name();
270  QgsDebugMsg( "Checking field " + fldName + " of " + QString::number( fieldsSize ) + " total" );
271 
272  // Check the fields and keep the first one that matches.
273  // We assume that the user has organized the data with the
274  // more "interesting" field names first. As such, name should
275  // be selected before oldname, othername, etc.
276  if ( fldName.indexOf( "name", false ) > -1 )
277  {
278  if ( idxName.isEmpty() )
279  {
280  idxName = fldName;
281  }
282  }
283  if ( fldName.indexOf( "descrip", false ) > -1 )
284  {
285  if ( idxName.isEmpty() )
286  {
287  idxName = fldName;
288  }
289  }
290  if ( fldName.indexOf( "id", false ) > -1 )
291  {
292  if ( idxId.isEmpty() )
293  {
294  idxId = fldName;
295  }
296  }
297  }
298 
299  //if there were no fields in the dbf just return - otherwise qgis segfaults!
300  if ( fieldsSize == 0 )
301  return;
302 
303  if ( idxName.length() > 0 )
304  {
305  mDisplayField = idxName;
306  }
307  else
308  {
309  if ( idxId.length() > 0 )
310  {
311  mDisplayField = idxId;
312  }
313  else
314  {
315  mDisplayField = fields[0].name();
316  }
317  }
318 
319  }
320 }
321 
322 // NOTE this is a temporary method added by Tim to prevent label clipping
323 // which was occurring when labeller was called in the main draw loop
324 // This method will probably be removed again in the near future!
326 {
327  if ( !hasGeometryType() )
328  return;
329 
330  QgsDebugMsg( "Starting draw of labels" );
331 
332  if (( mRenderer || mRendererV2 ) && mLabelOn &&
334  ( mLabel->minScale() <= rendererContext.rendererScale() &&
335  rendererContext.rendererScale() <= mLabel->maxScale() ) ) )
336  {
337  QgsAttributeList attributes;
338  if ( mRenderer )
339  {
340  attributes = mRenderer->classificationAttributes();
341  }
342  else if ( mRendererV2 )
343  {
344  foreach( QString attrName, mRendererV2->usedAttributes() )
345  {
346  int attrNum = fieldNameIndex( attrName );
347  attributes.append( attrNum );
348  }
349  // make sure the renderer is ready for classification ("symbolForFeature")
350  mRendererV2->startRender( rendererContext, this );
351  }
352 
353  // Add fields required for labels
354  mLabel->addRequiredFields( attributes );
355 
356  QgsDebugMsg( "Selecting features based on view extent" );
357 
358  int featureCount = 0;
359 
360  try
361  {
362  // select the records in the extent. The provider sets a spatial filter
363  // and sets up the selection set for retrieval
364  select( attributes, rendererContext.extent() );
365 
366  QgsFeature fet;
367  while ( nextFeature( fet ) )
368  {
369  if (( mRenderer && mRenderer->willRenderFeature( &fet ) )
370  || ( mRendererV2 && mRendererV2->symbolForFeature( fet ) != NULL ) )
371  {
372  bool sel = mSelectedFeatureIds.contains( fet.id() );
373  mLabel->renderLabel( rendererContext, fet, sel, 0 );
374  }
375  featureCount++;
376  }
377  }
378  catch ( QgsCsException &e )
379  {
380  Q_UNUSED( e );
381  QgsDebugMsg( "Error projecting label locations" );
382  }
383 
384  if ( mRendererV2 )
385  {
386  mRendererV2->stopRender( rendererContext );
387  }
388 
389  QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
390 
391  // XXX Something in our draw event is triggering an additional draw event when resizing [TE 01/26/06]
392  // XXX Calling this will begin processing the next draw event causing image havoc and recursion crashes.
393  //qApp->processEvents();
394 
395  }
396 }
397 
398 
399 unsigned char *QgsVectorLayer::drawLineString( unsigned char *feature, QgsRenderContext &renderContext )
400 {
401  QPainter *p = renderContext.painter();
402  unsigned char *ptr = feature + 5;
403  unsigned int wkbType = *(( int* )( feature + 1 ) );
404  unsigned int nPoints = *(( int* )ptr );
405  ptr = feature + 9;
406 
407  bool hasZValue = ( wkbType == QGis::WKBLineString25D );
408 
409  std::vector<double> x( nPoints );
410  std::vector<double> y( nPoints );
411  std::vector<double> z( nPoints, 0.0 );
412 
413  // Extract the points from the WKB format into the x and y vectors.
414  for ( register unsigned int i = 0; i < nPoints; ++i )
415  {
416  x[i] = *(( double * ) ptr );
417  ptr += sizeof( double );
418  y[i] = *(( double * ) ptr );
419  ptr += sizeof( double );
420 
421  if ( hasZValue ) // ignore Z value
422  ptr += sizeof( double );
423  }
424 
425  // Transform the points into map coordinates (and reproject if
426  // necessary)
427 
428  transformPoints( x, y, z, renderContext );
429 
430  // Work around a +/- 32768 limitation on coordinates
431  // Look through the x and y coordinates and see if there are any
432  // that need trimming. If one is found, there's no need to look at
433  // the rest of them so end the loop at that point.
434  for ( register unsigned int i = 0; i < nPoints; ++i )
435  {
436  if ( qAbs( x[i] ) > QgsClipper::MAX_X ||
437  qAbs( y[i] ) > QgsClipper::MAX_Y )
438  {
439  QgsClipper::trimFeature( x, y, true ); // true = polyline
440  nPoints = x.size(); // trimming may change nPoints.
441  break;
442  }
443  }
444 
445  // set up QPolygonF class with transformed points
446  QPolygonF pa( nPoints );
447  for ( register unsigned int i = 0; i < nPoints; ++i )
448  {
449  pa[i].setX( x[i] );
450  pa[i].setY( y[i] );
451  }
452 
453  // The default pen gives bevelled joins between segements of the
454  // polyline, which is good enough for the moment.
455  //preserve a copy of the pen before we start fiddling with it
456  QPen pen = p->pen(); // to be kept original
457 
458  //
459  // experimental alpha transparency
460  // 255 = opaque
461  //
462  QPen myTransparentPen = p->pen(); // store current pen
463  QColor myColor = myTransparentPen.color();
464  //only set transparency from layer level if renderer does not provide
465  //transparency on class level
466  if ( !mRenderer->usesTransparency() )
467  {
468  myColor.setAlpha( mTransparencyLevel );
469  }
470  myTransparentPen.setColor( myColor );
471  p->setPen( myTransparentPen );
472  p->drawPolyline( pa );
473 
474  // draw vertex markers if in editing mode, but only to the main canvas
475  if ( mEditable && renderContext.drawEditingInformation() )
476  {
477 
478  std::vector<double>::const_iterator xIt;
479  std::vector<double>::const_iterator yIt;
480  for ( xIt = x.begin(), yIt = y.begin(); xIt != x.end(); ++xIt, ++yIt )
481  {
483  }
484  }
485 
486  //restore the pen
487  p->setPen( pen );
488 
489  return ptr;
490 }
491 
492 unsigned char *QgsVectorLayer::drawPolygon( unsigned char *feature, QgsRenderContext &renderContext )
493 {
494  QPainter *p = renderContext.painter();
495  typedef std::pair<std::vector<double>, std::vector<double> > ringType;
496  typedef ringType* ringTypePtr;
497  typedef std::vector<ringTypePtr> ringsType;
498 
499  // get number of rings in the polygon
500  unsigned int numRings = *(( int* )( feature + 1 + sizeof( int ) ) );
501 
502  if ( numRings == 0 ) // sanity check for zero rings in polygon
503  return feature + 9;
504 
505  unsigned int wkbType = *(( int* )( feature + 1 ) );
506 
507  bool hasZValue = ( wkbType == QGis::WKBPolygon25D );
508 
509  int total_points = 0;
510 
511  // A vector containing a pointer to a pair of double vectors.The
512  // first vector in the pair contains the x coordinates, and the
513  // second the y coordinates.
514  ringsType rings;
515 
516  // Set pointer to the first ring
517  unsigned char* ptr = feature + 1 + 2 * sizeof( int );
518 
519  for ( register unsigned int idx = 0; idx < numRings; idx++ )
520  {
521  unsigned int nPoints = *(( int* )ptr );
522 
523  ringTypePtr ring = new ringType( std::vector<double>( nPoints ), std::vector<double>( nPoints ) );
524  ptr += 4;
525 
526  // create a dummy vector for the z coordinate
527  std::vector<double> zVector( nPoints, 0.0 );
528  // Extract the points from the WKB and store in a pair of
529  // vectors.
530  for ( register unsigned int jdx = 0; jdx < nPoints; jdx++ )
531  {
532  ring->first[jdx] = *(( double * ) ptr );
533  ptr += sizeof( double );
534  ring->second[jdx] = *(( double * ) ptr );
535  ptr += sizeof( double );
536 
537  if ( hasZValue )
538  ptr += sizeof( double );
539  }
540  // If ring has fewer than two points, what is it then?
541  // Anyway, this check prevents a crash
542  if ( nPoints < 1 )
543  {
544  QgsDebugMsg( "Ring has only " + QString::number( nPoints ) + " points! Skipping this ring." );
545  continue;
546  }
547 
548  transformPoints( ring->first, ring->second, zVector, renderContext );
549 
550  // Work around a +/- 32768 limitation on coordinates
551  // Look through the x and y coordinates and see if there are any
552  // that need trimming. If one is found, there's no need to look at
553  // the rest of them so end the loop at that point.
554  for ( register unsigned int i = 0; i < nPoints; ++i )
555  {
556  if ( qAbs( ring->first[i] ) > QgsClipper::MAX_X ||
557  qAbs( ring->second[i] ) > QgsClipper::MAX_Y )
558  {
559  QgsClipper::trimFeature( ring->first, ring->second, false );
560  break;
561  }
562  }
563 
564  // Don't bother keeping the ring if it has been trimmed out of
565  // existence.
566  if ( ring->first.size() == 0 )
567  delete ring;
568  else
569  {
570  rings.push_back( ring );
571  total_points += ring->first.size();
572  }
573  }
574 
575  // Now we draw the polygons
576 
577  // use painter paths for drawing polygons with holes
578  // when adding polygon to the path they invert the area
579  // this means that adding inner rings to the path creates
580  // holes in outer ring
581  QPainterPath path; // OddEven fill rule by default
582 
583  // Only try to draw polygons if there is something to draw
584  if ( total_points > 0 )
585  {
586  //preserve a copy of the brush and pen before we start fiddling with it
587  QBrush brush = p->brush(); //to be kept as original
588  QPen pen = p->pen(); // to be kept original
589  //
590  // experimental alpha transparency
591  // 255 = opaque
592  //
593  QBrush myTransparentBrush = p->brush();
594  QColor myColor = brush.color();
595 
596  //only set transparency from layer level if renderer does not provide
597  //transparency on class level
598  if ( !mRenderer->usesTransparency() )
599  {
600  myColor.setAlpha( mTransparencyLevel );
601  }
602  myTransparentBrush.setColor( myColor );
603  QPen myTransparentPen = p->pen(); // store current pen
604  myColor = myTransparentPen.color();
605 
606  //only set transparency from layer level if renderer does not provide
607  //transparency on class level
608  if ( !mRenderer->usesTransparency() )
609  {
610  myColor.setAlpha( mTransparencyLevel );
611  }
612  myTransparentPen.setColor( myColor );
613 
614  p->setBrush( myTransparentBrush );
615  p->setPen( myTransparentPen );
616 
617  if ( numRings == 1 )
618  {
619  ringTypePtr r = rings[0];
620  unsigned ringSize = r->first.size();
621 
622  QPolygonF pa( ringSize );
623  for ( register unsigned int j = 0; j != ringSize; ++j )
624  {
625  pa[j].setX( r->first[j] );
626  pa[j].setY( r->second[j] );
627  }
628  p->drawPolygon( pa );
629 
630  // draw vertex markers if in editing mode, but only to the main canvas
631  if ( mEditable && renderContext.drawEditingInformation() )
632  {
633  for ( register unsigned int j = 0; j != ringSize; ++j )
634  {
635  drawVertexMarker( r->first[j], r->second[j], *p, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
636  }
637  }
638 
639  delete rings[0];
640  }
641  else
642  {
643  // Store size here and use it in the loop to avoid penalty of
644  // multiple calls to size()
645  int numRings = rings.size();
646  for ( register int i = 0; i < numRings; ++i )
647  {
648  // Store the pointer in a variable with a short name so as to make
649  // the following code easier to type and read.
650  ringTypePtr r = rings[i];
651  // only do this once to avoid penalty of additional calls
652  unsigned ringSize = r->first.size();
653 
654  // Transfer points to the array of QPointF
655  QPolygonF pa( ringSize );
656  for ( register unsigned int j = 0; j != ringSize; ++j )
657  {
658  pa[j].setX( r->first[j] );
659  pa[j].setY( r->second[j] );
660  }
661 
662  path.addPolygon( pa );
663 
664  // Tidy up the pointed to pairs of vectors as we finish with them
665  delete rings[i];
666  }
667 
668 #if 0
669  // A bit of code to aid in working out what values of
670  // QgsClipper::minX, etc cause the X11 zoom bug.
671  int largestX = -std::numeric_limits<int>::max();
672  int smallestX = std::numeric_limits<int>::max();
673  int largestY = -std::numeric_limits<int>::max();
674  int smallestY = std::numeric_limits<int>::max();
675 
676  for ( int i = 0; i < pa.size(); ++i )
677  {
678  largestX = qMax( largestX, pa.point( i ).x() );
679  smallestX = qMin( smallestX, pa.point( i ).x() );
680  largestY = qMax( largestY, pa.point( i ).y() );
681  smallestY = qMin( smallestY, pa.point( i ).y() );
682  }
683  QgsDebugMsg( QString( "Largest X coordinate was %1" ).arg( largestX ) );
684  QgsDebugMsg( QString( "Smallest X coordinate was %1" ).arg( smallestX ) );
685  QgsDebugMsg( QString( "Largest Y coordinate was %1" ).arg( largestY ) );
686  QgsDebugMsg( QString( "Smallest Y coordinate was %1" ).arg( smallestY ) );
687 #endif
688 
689  //
690  // draw the polygon
691  //
692  p->drawPath( path );
693 
694  // draw vertex markers if in editing mode, but only to the main canvas
695  if ( mEditable && renderContext.drawEditingInformation() )
696  {
697  for ( int i = 0; i < path.elementCount(); ++i )
698  {
699  const QPainterPath::Element & e = path.elementAt( i );
701  }
702  }
703  }
704 
705  //
706  //restore brush and pen to original
707  //
708  p->setBrush( brush );
709  p->setPen( pen );
710 
711  } // totalPoints > 0
712 
713  return ptr;
714 }
715 
716 void QgsVectorLayer::drawRendererV2( QgsRenderContext& rendererContext, bool labeling )
717 {
718  if ( !hasGeometryType() )
719  return;
720 
721  QSettings settings;
722  bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
723 
724  mRendererV2->startRender( rendererContext, this );
725 
726 #ifndef Q_WS_MAC
727  int featureCount = 0;
728 #endif //Q_WS_MAC
729 
730  QgsFeature fet;
731  while ( nextFeature( fet ) )
732  {
733  try
734  {
735  if ( rendererContext.renderingStopped() )
736  {
737  break;
738  }
739 
740 #ifndef Q_WS_MAC //MH: disable this on Mac for now to avoid problems with resizing
741  if ( mUpdateThreshold > 0 && 0 == featureCount % mUpdateThreshold )
742  {
743  emit screenUpdateRequested();
744  // emit drawingProgress( featureCount, totalFeatures );
745  qApp->processEvents();
746  }
747  else if ( featureCount % 1000 == 0 )
748  {
749  // emit drawingProgress( featureCount, totalFeatures );
750  qApp->processEvents();
751  }
752 #endif //Q_WS_MAC
753 
754  bool sel = mSelectedFeatureIds.contains( fet.id() );
755  bool drawMarker = ( mEditable && ( !vertexMarkerOnlyForSelection || sel ) );
756 
757  // render feature
758  mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker );
759 
760  if ( mEditable )
761  {
762  // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
763  mCachedGeometries[fet.id()] = *fet.geometry();
764  }
765 
766  // labeling - register feature
767  if ( mRendererV2->symbolForFeature( fet ) != NULL && rendererContext.labelingEngine() )
768  {
769  if ( labeling )
770  {
771  rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
772  }
773  if ( mDiagramRenderer )
774  {
775  rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
776  }
777  }
778  }
779  catch ( const QgsCsException &cse )
780  {
781  QgsDebugMsg( QString( "Failed to transform a point while drawing a feature of type '%1'. Ignoring this feature. %2" )
782  .arg( fet.typeName() ).arg( cse.what() ) );
783  }
784 #ifndef Q_WS_MAC
785  ++featureCount;
786 #endif //Q_WS_MAC
787  }
788 
789 #ifndef Q_WS_MAC
790  QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
791 #endif
792 }
793 
794 void QgsVectorLayer::drawRendererV2Levels( QgsRenderContext& rendererContext, bool labeling )
795 {
796  if ( !hasGeometryType() )
797  return;
798 
799  QHash< QgsSymbolV2*, QList<QgsFeature> > features; // key = symbol, value = array of features
800 
801  QSettings settings;
802  bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
803 
804  // startRender must be called before symbolForFeature() calls to make sure renderer is ready
805  mRendererV2->startRender( rendererContext, this );
806 
807  QgsSingleSymbolRendererV2* selRenderer = NULL;
808  if ( !mSelectedFeatureIds.isEmpty() )
809  {
811  selRenderer->symbol()->setColor( QgsRenderer::selectionColor() );
813  selRenderer->startRender( rendererContext, this );
814  }
815 
816  // 1. fetch features
817  QgsFeature fet;
818 #ifndef Q_WS_MAC
819  int featureCount = 0;
820 #endif //Q_WS_MAC
821  while ( nextFeature( fet ) )
822  {
823  if ( rendererContext.renderingStopped() )
824  {
825  stopRendererV2( rendererContext, selRenderer );
826  return;
827  }
828 #ifndef Q_WS_MAC
829  if ( featureCount % 1000 == 0 )
830  {
831  qApp->processEvents();
832  }
833 #endif //Q_WS_MAC
835  if ( !sym )
836  {
837  continue;
838  }
839 
840  if ( !features.contains( sym ) )
841  {
842  features.insert( sym, QList<QgsFeature>() );
843  }
844  features[sym].append( fet );
845 
846  if ( mEditable )
847  {
848  // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
849  mCachedGeometries[fet.id()] = *fet.geometry();
850  }
851 
852  if ( sym && rendererContext.labelingEngine() )
853  {
854  if ( labeling )
855  {
856  rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
857  }
858  if ( mDiagramRenderer )
859  {
860  rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
861  }
862  }
863 
864 #ifndef Q_WS_MAC
865  ++featureCount;
866 #endif //Q_WS_MAC
867  }
868 
869  // find out the order
870  QgsSymbolV2LevelOrder levels;
871  QgsSymbolV2List symbols = mRendererV2->symbols();
872  for ( int i = 0; i < symbols.count(); i++ )
873  {
874  QgsSymbolV2* sym = symbols[i];
875  for ( int j = 0; j < sym->symbolLayerCount(); j++ )
876  {
877  int level = sym->symbolLayer( j )->renderingPass();
878  if ( level < 0 || level >= 1000 ) // ignore invalid levels
879  continue;
880  QgsSymbolV2LevelItem item( sym, j );
881  while ( level >= levels.count() ) // append new empty levels
882  levels.append( QgsSymbolV2Level() );
883  levels[level].append( item );
884  }
885  }
886 
887  // 2. draw features in correct order
888  for ( int l = 0; l < levels.count(); l++ )
889  {
890  QgsSymbolV2Level& level = levels[l];
891  for ( int i = 0; i < level.count(); i++ )
892  {
893  QgsSymbolV2LevelItem& item = level[i];
894  if ( !features.contains( item.symbol() ) )
895  {
896  QgsDebugMsg( "level item's symbol not found!" );
897  continue;
898  }
899  int layer = item.layer();
900  QList<QgsFeature>& lst = features[item.symbol()];
901  QList<QgsFeature>::iterator fit;
902 #ifndef Q_WS_MAC
903  featureCount = 0;
904 #endif //Q_WS_MAC
905  for ( fit = lst.begin(); fit != lst.end(); ++fit )
906  {
907  if ( rendererContext.renderingStopped() )
908  {
909  stopRendererV2( rendererContext, selRenderer );
910  return;
911  }
912 #ifndef Q_WS_MAC
913  if ( featureCount % 1000 == 0 )
914  {
915  qApp->processEvents();
916  }
917 #endif //Q_WS_MAC
918  bool sel = mSelectedFeatureIds.contains( fit->id() );
919  // maybe vertex markers should be drawn only during the last pass...
920  bool drawMarker = ( mEditable && ( !vertexMarkerOnlyForSelection || sel ) );
921 
922  try
923  {
924  mRendererV2->renderFeature( *fit, rendererContext, layer, sel, drawMarker );
925  }
926  catch ( const QgsCsException &cse )
927  {
928  QgsDebugMsg( QString( "Failed to transform a point while drawing a feature of type '%1'. Ignoring this feature. %2" )
929  .arg( fet.typeName() ).arg( cse.what() ) );
930  }
931 #ifndef Q_WS_MAC
932  ++featureCount;
933 #endif //Q_WS_MAC
934  }
935  }
936  }
937 
938  stopRendererV2( rendererContext, selRenderer );
939 }
940 
942 {
943  if ( mDataProvider )
944  {
946  }
947 }
948 
949 bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
950 {
951  if ( !hasGeometryType() )
952  return true;
953 
954  //set update threshold before each draw to make sure the current setting is picked up
955  QSettings settings;
956  mUpdateThreshold = settings.value( "Map/updateThreshold", 0 ).toInt();
957 
958  if ( mUsingRendererV2 )
959  {
960  if ( mRendererV2 == NULL )
961  return false;
962 
963  QgsDebugMsg( "rendering v2:\n" + mRendererV2->dump() );
964 
965  if ( mEditable )
966  {
967  // Destroy all cached geometries and clear the references to them
969  mCachedGeometriesRect = rendererContext.extent();
970 
971  // set editing vertex markers style
973  }
974 
975  QgsAttributeList attributes;
976  foreach( QString attrName, mRendererV2->usedAttributes() )
977  {
978  int attrNum = fieldNameIndex( attrName );
979  attributes.append( attrNum );
980  QgsDebugMsg( "attrs: " + attrName + " - " + QString::number( attrNum ) );
981  }
982 
983  bool labeling = false;
984  //register label and diagram layer to the labeling engine
985  prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
986 
987  select( attributes, rendererContext.extent() );
988 
990  drawRendererV2Levels( rendererContext, labeling );
991  else
992  drawRendererV2( rendererContext, labeling );
993 
994  return true;
995  }
996 
997  //draw ( p, viewExtent, theMapToPixelTransform, ct, drawingToEditingCanvas, 1., 1.);
998 
999  if ( mRenderer )
1000  {
1001  // painter is active (begin has been called
1002  /* Steps to draw the layer
1003  1. get the features in the view extent by SQL query
1004  2. read WKB for a feature
1005  3. transform
1006  4. draw
1007  */
1008 
1009  QPen pen;
1010  /*Pointer to a marker image*/
1011  QImage marker;
1012  //vertex marker type for selection
1014  int vertexMarkerSize = 7;
1015 
1016  if ( mEditable )
1017  {
1018  // Destroy all cached geometries and clear the references to them
1020  mCachedGeometriesRect = rendererContext.extent();
1021  vertexMarker = currentVertexMarkerType();
1022  vertexMarkerSize = currentVertexMarkerSize();
1023  mVertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
1024  }
1025 
1026  // int totalFeatures = pendingFeatureCount();
1027  int featureCount = 0;
1028  QgsFeature fet;
1030 
1031  bool labeling = false;
1032  prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
1033 
1034  select( attributes, rendererContext.extent() );
1035 
1036  try
1037  {
1038  while ( nextFeature( fet ) )
1039  {
1040 
1041  if ( rendererContext.renderingStopped() )
1042  {
1043  break;
1044  }
1045 
1046 #ifndef Q_WS_MAC //MH: disable this on Mac for now to avoid problems with resizing
1047  if ( mUpdateThreshold > 0 && 0 == featureCount % mUpdateThreshold )
1048  {
1049  emit screenUpdateRequested();
1050  // emit drawingProgress( featureCount, totalFeatures );
1051  qApp->processEvents();
1052  }
1053  else if ( featureCount % 1000 == 0 )
1054  {
1055  // emit drawingProgress( featureCount, totalFeatures );
1056  qApp->processEvents();
1057  }
1058 // #else
1059 // Q_UNUSED( totalFeatures );
1060 #endif //Q_WS_MAC
1061 
1062  // check if feature is selected
1063  // only show selections of the current layer
1064  // TODO: create a mechanism to let layer know whether it's current layer or not [MD]
1065  bool sel = mSelectedFeatureIds.contains( fet.id() );
1066 
1069 
1070  if ( mEditable )
1071  {
1072  // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
1073  mCachedGeometries[fet.id()] = *fet.geometry();
1074 
1075  if ( !mVertexMarkerOnlyForSelection || sel )
1076  {
1077  mCurrentVertexMarkerType = vertexMarker;
1078  mCurrentVertexMarkerSize = vertexMarkerSize;
1079  }
1080  }
1081 
1082  //QgsDebugMsg(QString("markerScale before renderFeature(): %1").arg(markerScaleFactor));
1083  // markerScalerFactore reflects the wanted scaling of the marker
1084 
1085  double opacity = 1.0;
1086  if ( !mRenderer->usesTransparency() )
1087  {
1088  opacity = ( mTransparencyLevel * 1.0 ) / 255.0;
1089  }
1090  mRenderer->renderFeature( rendererContext, fet, &marker, sel, opacity );
1091 
1092  // markerScalerFactore now reflects the actual scaling of the marker that the render performed.
1093  //QgsDebugMsg(QString("markerScale after renderFeature(): %1").arg(markerScaleFactor));
1094 
1095  //double scale = rendererContext.scaleFactor() / markerScaleFactor;
1096  drawFeature( rendererContext, fet, &marker );
1097 
1098  if ( mRenderer->willRenderFeature( &fet ) && rendererContext.labelingEngine() )
1099  {
1100  if ( labeling )
1101  {
1102  rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
1103  }
1104  if ( mDiagramRenderer )
1105  {
1106  rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
1107  }
1108  }
1109  ++featureCount;
1110  }
1111  }
1112  catch ( QgsCsException &cse )
1113  {
1114  QgsDebugMsg( QString( "Failed to transform a point while drawing a feature of type '%1'. Rendering stopped. %2" )
1115  .arg( fet.typeName() ).arg( cse.what() ) );
1116  return false;
1117  }
1118 
1119  QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
1120  }
1121  else
1122  {
1123  QgsDebugMsg( "QgsRenderer is null" );
1124  }
1125 
1126  if ( mEditable )
1127  {
1128  QgsDebugMsg( QString( "Cached %1 geometries." ).arg( mCachedGeometries.count() ) );
1129  }
1130 
1131  return true; // Assume success always
1132 }
1133 
1135 {
1136  // Destroy any cached geometries
1137  mCachedGeometries.clear();
1139 }
1140 
1141 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int m )
1142 {
1144  {
1145  p.setPen( QColor( 50, 100, 120, 200 ) );
1146  p.setBrush( QColor( 200, 200, 210, 120 ) );
1147  p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
1148  }
1149  else if ( type == QgsVectorLayer::Cross )
1150  {
1151  p.setPen( QColor( 255, 0, 0 ) );
1152  p.drawLine( x - m, y + m, x + m, y - m );
1153  p.drawLine( x - m, y - m, x + m, y + m );
1154  }
1155 }
1156 
1157 void QgsVectorLayer::select( int number, bool emitSignal )
1158 {
1159  mSelectedFeatureIds.insert( number );
1160 
1161  if ( emitSignal )
1162  {
1163  // invalidate cache
1164  setCacheImage( 0 );
1165 
1166  emit selectionChanged();
1167  }
1168 }
1169 
1170 void QgsVectorLayer::deselect( int number, bool emitSignal )
1171 {
1172  mSelectedFeatureIds.remove( number );
1173 
1174  if ( emitSignal )
1175  {
1176  // invalidate cache
1177  setCacheImage( 0 );
1178 
1179  emit selectionChanged();
1180  }
1181 }
1182 
1183 void QgsVectorLayer::select( QgsRectangle & rect, bool lock )
1184 {
1185  // normalize the rectangle
1186  rect.normalize();
1187 
1188  if ( !lock )
1189  {
1190  removeSelection( false ); // don't emit signal
1191  }
1192 
1193  //select all the elements
1194  select( QgsAttributeList(), rect, false, true );
1195 
1196  QgsFeature f;
1197  while ( nextFeature( f ) )
1198  {
1199  select( f.id(), false ); // don't emit signal (not to redraw it everytime)
1200  }
1201 
1202  // invalidate cache
1203  setCacheImage( 0 );
1204 
1205  emit selectionChanged(); // now emit signal to redraw layer
1206 }
1207 
1209 {
1210  // copy the ids of selected features to tmp
1212 
1213  removeSelection( false ); // don't emit signal
1214 
1215  select( QgsAttributeList(), QgsRectangle(), false );
1216 
1217  QgsFeature fet;
1218  while ( nextFeature( fet ) )
1219  {
1220  select( fet.id(), false ); // don't emit signal
1221  }
1222 
1223  for ( QgsFeatureIds::iterator iter = tmp.begin(); iter != tmp.end(); ++iter )
1224  {
1225  mSelectedFeatureIds.remove( *iter );
1226  }
1227 
1228  // invalidate cache
1229  setCacheImage( 0 );
1230 
1231  emit selectionChanged();
1232 }
1233 
1235 {
1236  // normalize the rectangle
1237  rect.normalize();
1238 
1239  select( QgsAttributeList(), rect, false, true );
1240 
1241  QgsFeature fet;
1242  while ( nextFeature( fet ) )
1243  {
1244  if ( mSelectedFeatureIds.contains( fet.id() ) )
1245  {
1246  deselect( fet.id(), false ); // don't emit signal
1247  }
1248  else
1249  {
1250  select( fet.id(), false ); // don't emit signal
1251  }
1252  }
1253 
1254  // invalidate cache
1255  setCacheImage( 0 );
1256 
1257  emit selectionChanged();
1258 }
1259 
1260 void QgsVectorLayer::removeSelection( bool emitSignal )
1261 {
1262  if ( mSelectedFeatureIds.size() == 0 )
1263  return;
1264 
1265  mSelectedFeatureIds.clear();
1266 
1267  if ( emitSignal )
1268  {
1269  // invalidate cache
1270  setCacheImage( 0 );
1271 
1272  emit selectionChanged();
1273  }
1274 }
1275 
1277 {
1278  emit repaintRequested();
1279 }
1280 
1282 {
1283  return mDataProvider;
1284 }
1285 
1287 {
1288  return mDataProvider;
1289 }
1290 
1291 void QgsVectorLayer::setProviderEncoding( const QString& encoding )
1292 {
1293  if ( mDataProvider )
1294  {
1295  mDataProvider->setEncoding( encoding );
1296  }
1297 }
1298 
1299 
1301 {
1302  return mRenderer;
1303 }
1304 
1306 {
1307  if ( !hasGeometryType() )
1308  return;
1309 
1310  if ( r != mRenderer )
1311  {
1312  delete mRenderer;
1313  mRenderer = r;
1314  }
1315 }
1316 
1318 {
1319  delete mDiagramRenderer;
1320  mDiagramRenderer = r;
1321 }
1322 
1324 {
1325  if ( mDataProvider )
1326  {
1327  int type = mDataProvider->geometryType();
1328  switch ( type )
1329  {
1330  case QGis::WKBPoint:
1331  case QGis::WKBPoint25D:
1332  return QGis::Point;
1333 
1334  case QGis::WKBLineString:
1336  return QGis::Line;
1337 
1338  case QGis::WKBPolygon:
1339  case QGis::WKBPolygon25D:
1340  return QGis::Polygon;
1341 
1342  case QGis::WKBMultiPoint:
1344  return QGis::Point;
1345 
1348  return QGis::Line;
1349 
1350  case QGis::WKBMultiPolygon:
1352  return QGis::Polygon;
1353 
1354  case QGis::WKBNoGeometry:
1355  return QGis::NoGeometry;
1356  }
1357  QgsDebugMsg( QString( "Data Provider Geometry type is not recognised, is %1" ).arg( type ) );
1358  }
1359  else
1360  {
1361  QgsDebugMsg( "pointer to mDataProvider is null" );
1362  }
1363 
1364  // We shouldn't get here, and if we have, other things are likely to
1365  // go wrong. Code that uses the type() return value should be
1366  // rewritten to cope with a value of QGis::Unknown. To make this
1367  // need known, the following message is printed every time we get
1368  // here.
1369  QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
1370 
1371  return QGis::UnknownGeometry;
1372 }
1373 
1375 {
1377  return ( t != QGis::NoGeometry && t != QGis::UnknownGeometry );
1378 }
1379 
1381 {
1382  return ( QGis::WkbType )( mWkbType );
1383 }
1384 
1386 {
1387  if ( mSelectedFeatureIds.size() == 0 ) //no selected features
1388  {
1389  return QgsRectangle( 0, 0, 0, 0 );
1390  }
1391 
1392  QgsRectangle r, retval;
1393 
1394 
1395  select( QgsAttributeList(), QgsRectangle(), true );
1396 
1397  retval.setMinimal();
1398 
1399  QgsFeature fet;
1400  while ( nextFeature( fet ) )
1401  {
1402  if ( mSelectedFeatureIds.contains( fet.id() ) )
1403  {
1404  if ( fet.geometry() )
1405  {
1406  r = fet.geometry()->boundingBox();
1407  retval.combineExtentWith( &r );
1408  }
1409  }
1410  }
1411 
1412  if ( retval.width() == 0.0 || retval.height() == 0.0 )
1413  {
1414  // If all of the features are at the one point, buffer the
1415  // rectangle a bit. If they are all at zero, do something a bit
1416  // more crude.
1417 
1418  if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
1419  retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
1420  {
1421  retval.set( -1.0, -1.0, 1.0, 1.0 );
1422  }
1423  }
1424 
1425  return retval;
1426 }
1427 
1428 
1429 
1431 {
1432  if ( !mDataProvider )
1433  {
1434  QgsDebugMsg( "invoked with null mDataProvider" );
1435  return 0;
1436  }
1437 
1438  return mDataProvider->featureCount();
1439 }
1440 
1442 {
1443  return -1;
1444 }
1445 
1447 {
1448  if ( !hasGeometryType() )
1449  return;
1450 
1452 
1453  if ( !mDataProvider )
1454  QgsDebugMsg( "invoked with null mDataProvider" );
1455 
1456  if ( mDeletedFeatureIds.isEmpty() && mChangedGeometries.isEmpty() )
1457  {
1458  // get the extent of the layer from the provider
1459  // but only when there are some features already
1460  if ( mDataProvider->featureCount() != 0 )
1461  {
1464  }
1465 
1466  for ( QgsFeatureList::iterator it = mAddedFeatures.begin(); it != mAddedFeatures.end(); it++ )
1467  {
1468  QgsRectangle r = it->geometry()->boundingBox();
1470  }
1471  }
1472  else
1473  {
1474  select( QgsAttributeList(), QgsRectangle(), true );
1475 
1476  QgsFeature fet;
1477  while ( nextFeature( fet ) )
1478  {
1479  if ( fet.geometry() )
1480  {
1481  QgsRectangle bb = fet.geometry()->boundingBox();
1483  }
1484  }
1485  }
1486 
1488  {
1489  // special case when there are no features in provider nor any added
1490  mLayerExtent = QgsRectangle(); // use rectangle with zero coordinates
1491  }
1492 
1493  // Send this (hopefully) up the chain to the map canvas
1494  emit recalculateExtents();
1495 }
1496 
1498 {
1499  if ( ! mDataProvider )
1500  {
1501  QgsDebugMsg( "invoked with null mDataProvider" );
1502  return 0;
1503  }
1504  return mDataProvider->subsetString();
1505 }
1506 
1507 bool QgsVectorLayer::setSubsetString( QString subset )
1508 {
1509  if ( ! mDataProvider )
1510  {
1511  QgsDebugMsg( "invoked with null mDataProvider" );
1512  return false;
1513  }
1514 
1515  bool res = mDataProvider->setSubsetString( subset );
1516 
1517  // get the updated data source string from the provider
1519  updateExtents();
1520 
1521  if ( res )
1522  setCacheImage( 0 );
1523 
1524  return res;
1525 }
1526 
1528 {
1529  if ( mDataProvider && ( all || ( mFetchAttributes.size() > 0 && mJoinBuffer->containsFetchJoins() ) ) )
1530  {
1531  int index = 0;
1533  mJoinBuffer->updateFeatureAttributes( f, index, all );
1534  }
1535 
1536 
1537  // do not update when we aren't in editing mode
1538  if ( !mEditable )
1539  return;
1540 
1541  if ( mChangedAttributeValues.contains( f.id() ) )
1542  {
1543  const QgsAttributeMap &map = mChangedAttributeValues[f.id()];
1544  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); it++ )
1545  f.changeAttribute( it.key(), it.value() );
1546  }
1547 
1548  // remove all attributes that will disappear
1549  QgsAttributeMap map = f.attributeMap();
1550  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); it++ )
1551  if ( !mUpdatedFields.contains( it.key() ) )
1552  f.deleteAttribute( it.key() );
1553 
1554  // null/add all attributes that were added, but don't exist in the feature yet
1555  for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
1556  if ( !map.contains( it.key() ) && ( all || mFetchAttributes.contains( it.key() ) ) )
1557  f.changeAttribute( it.key(), QVariant( QString::null ) );
1558 }
1559 
1560 void QgsVectorLayer::addJoinedFeatureAttributes( QgsFeature& f, const QgsVectorJoinInfo& joinInfo, const QString& joinFieldName,
1561  const QVariant& joinValue, const QgsAttributeList& attributes, int attributeIndexOffset )
1562 {
1563  const QHash< QString, QgsAttributeMap>& memoryCache = joinInfo.cachedAttributes;
1564  if ( !memoryCache.isEmpty() ) //use join memory cache
1565  {
1566  QgsAttributeMap featureAttributes = memoryCache.value( joinValue.toString() );
1567  bool found = !featureAttributes.isEmpty();
1568  QgsAttributeList::const_iterator attIt = attributes.constBegin();
1569  for ( ; attIt != attributes.constEnd(); ++attIt )
1570  {
1571  if ( found )
1572  {
1573  f.addAttribute( *attIt + attributeIndexOffset, featureAttributes.value( *attIt ) );
1574  }
1575  else
1576  {
1577  f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
1578  }
1579  }
1580  }
1581  else //work with subset string
1582  {
1583  QgsVectorLayer* joinLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
1584  if ( !joinLayer )
1585  {
1586  return;
1587  }
1588 
1589  //no memory cache, query the joined values by setting substring
1590  QString subsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
1591  QString bkSubsetString = subsetString;
1592  if ( !subsetString.isEmpty() )
1593  {
1594  subsetString.append( " AND " );
1595  }
1596 
1597  subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
1598  joinLayer->dataProvider()->setSubsetString( subsetString, false );
1599 
1600  //select (no geometry)
1601  joinLayer->select( attributes, QgsRectangle(), false, false );
1602 
1603  //get first feature
1604  QgsFeature fet;
1605  if ( joinLayer->nextFeature( fet ) )
1606  {
1607  QgsAttributeMap attMap = fet.attributeMap();
1608  QgsAttributeMap::const_iterator attIt = attMap.constBegin();
1609  for ( ; attIt != attMap.constEnd(); ++attIt )
1610  {
1611  f.addAttribute( attIt.key() + attributeIndexOffset, attIt.value() );
1612  }
1613  }
1614  else //no suitable join feature found, insert invalid variants
1615  {
1616  QgsAttributeList::const_iterator attIt = attributes.constBegin();
1617  for ( ; attIt != attributes.constEnd(); ++attIt )
1618  {
1619  f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
1620  }
1621  }
1622 
1623  joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
1624  }
1625 }
1626 
1628 {
1629  if ( mChangedGeometries.contains( f.id() ) )
1630  f.setGeometry( mChangedGeometries[f.id()] );
1631 }
1632 
1633 
1634 void QgsVectorLayer::select( QgsAttributeList attributes, QgsRectangle rect, bool fetchGeometries, bool useIntersect )
1635 {
1636  if ( !mDataProvider )
1637  return;
1638 
1639  mFetching = true;
1640  mFetchRect = rect;
1641  mFetchAttributes = attributes;
1642  mFetchGeometry = fetchGeometries;
1644  QgsAttributeList targetJoinFieldList;
1645 
1646  if ( mEditable )
1647  {
1650  }
1651 
1652  //look in the normal features of the provider
1653  if ( mFetchAttributes.size() > 0 )
1654  {
1655  if ( mEditable || mJoinBuffer->containsJoins() )
1656  {
1657  QgsAttributeList joinFields;
1658 
1659  int maxProviderIndex = 0;
1660  if ( mDataProvider )
1661  {
1663  }
1664 
1665  mJoinBuffer->select( mFetchAttributes, joinFields, maxProviderIndex );
1666  QgsAttributeList::const_iterator joinFieldIt = joinFields.constBegin();
1667  for ( ; joinFieldIt != joinFields.constEnd(); ++joinFieldIt )
1668  {
1669  if ( !mFetchAttributes.contains( *joinFieldIt ) )
1670  {
1671  mFetchAttributes.append( *joinFieldIt );
1672  }
1673  }
1674 
1675  //detect which fields are from the provider
1676  mFetchProvAttributes.clear();
1677  for ( QgsAttributeList::iterator it = mFetchAttributes.begin(); it != mFetchAttributes.end(); it++ )
1678  {
1679  if ( mDataProvider->fields().contains( *it ) )
1680  {
1681  mFetchProvAttributes << *it;
1682  }
1683  }
1684 
1685  mDataProvider->select( mFetchProvAttributes, rect, fetchGeometries, useIntersect );
1686  }
1687  else
1688  {
1689  mDataProvider->select( mFetchAttributes, rect, fetchGeometries, useIntersect );
1690  }
1691  }
1692  else //we don't need any attributes at all
1693  {
1694  mDataProvider->select( QgsAttributeList(), rect, fetchGeometries, useIntersect );
1695  }
1696 }
1697 
1699 {
1700  if ( !mFetching )
1701  return false;
1702 
1703  if ( mEditable )
1704  {
1705  if ( !mFetchRect.isEmpty() )
1706  {
1707  // check if changed geometries are in rectangle
1709  {
1710  int fid = mFetchChangedGeomIt.key();
1711 
1712  if ( mFetchConsidered.contains( fid ) )
1713  // skip deleted features
1714  continue;
1715 
1716  mFetchConsidered << fid;
1717 
1718  if ( !mFetchChangedGeomIt->intersects( mFetchRect ) )
1719  // skip changed geometries not in rectangle and don't check again
1720  continue;
1721 
1722  f.setFeatureId( fid );
1723  f.setValid( true );
1724 
1725  if ( mFetchGeometry )
1726  f.setGeometry( mFetchChangedGeomIt.value() );
1727 
1728  if ( mFetchAttributes.size() > 0 )
1729  {
1730  if ( fid < 0 )
1731  {
1732  // fid<0 => in mAddedFeatures
1733  bool found = false;
1734 
1735  for ( QgsFeatureList::iterator it = mAddedFeatures.begin(); it != mAddedFeatures.end(); it++ )
1736  {
1737  if ( fid == it->id() )
1738  {
1739  found = true;
1740  f.setAttributeMap( it->attributeMap() );
1742  break;
1743  }
1744  }
1745 
1746  if ( !found )
1747  QgsDebugMsg( QString( "No attributes for the added feature %1 found" ).arg( f.id() ) );
1748  }
1749  else
1750  {
1751  // retrieve attributes from provider
1752  QgsFeature tmp;
1753  mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
1754  updateFeatureAttributes( tmp );
1755  f.setAttributeMap( tmp.attributeMap() );
1756  }
1757  }
1758 
1759  // return complete feature
1761  return true;
1762  }
1763 
1764  // no more changed geometries
1765  }
1766 
1768  {
1769  int fid = mFetchAddedFeaturesIt->id();
1770 
1771  if ( mFetchConsidered.contains( fid ) )
1772  // must have changed geometry outside rectangle
1773  continue;
1774 
1775  if ( !mFetchRect.isEmpty() &&
1776  mFetchAddedFeaturesIt->geometry() &&
1777  !mFetchAddedFeaturesIt->geometry()->intersects( mFetchRect ) )
1778  // skip added features not in rectangle
1779  continue;
1780 
1781  f.setFeatureId( fid );
1782  f.setValid( true );
1783 
1784  if ( mFetchGeometry )
1785  f.setGeometry( *mFetchAddedFeaturesIt->geometry() );
1786 
1787  if ( mFetchAttributes.size() > 0 )
1788  {
1789  f.setAttributeMap( mFetchAddedFeaturesIt->attributeMap() );
1791  }
1792 
1794  return true;
1795  }
1796 
1797  // no more added features
1798  }
1799 
1800  while ( dataProvider()->nextFeature( f ) )
1801  {
1802  if ( mFetchConsidered.contains( f.id() ) )
1803  {
1804  continue;
1805  }
1806  if ( mFetchAttributes.size() > 0 )
1807  {
1808  updateFeatureAttributes( f ); //check joined attributes / changed attributes
1809  }
1810  return true;
1811  }
1812 
1813  mFetching = false;
1814  return false;
1815 }
1816 
1817 bool QgsVectorLayer::featureAtId( int featureId, QgsFeature& f, bool fetchGeometries, bool fetchAttributes )
1818 {
1819  if ( !mDataProvider )
1820  return false;
1821 
1822  if ( mDeletedFeatureIds.contains( featureId ) )
1823  return false;
1824 
1825  if ( fetchGeometries && mChangedGeometries.contains( featureId ) )
1826  {
1827  f.setFeatureId( featureId );
1828  f.setValid( true );
1829  f.setGeometry( mChangedGeometries[featureId] );
1830 
1831  if ( fetchAttributes )
1832  {
1833  if ( featureId < 0 )
1834  {
1835  // featureId<0 => in mAddedFeatures
1836  bool found = false;
1837 
1838  for ( QgsFeatureList::iterator it = mAddedFeatures.begin(); it != mAddedFeatures.end(); it++ )
1839  {
1840  if ( featureId != it->id() )
1841  {
1842  found = true;
1843  f.setAttributeMap( it->attributeMap() );
1844  break;
1845  }
1846  }
1847 
1848  if ( !found )
1849  QgsDebugMsg( QString( "No attributes for the added feature %1 found" ).arg( f.id() ) );
1850  }
1851  else
1852  {
1853  // retrieve attributes from provider
1854  QgsFeature tmp;
1855  mDataProvider->featureAtId( featureId, tmp, false, mDataProvider->attributeIndexes() );
1856  f.setAttributeMap( tmp.attributeMap() );
1857  }
1858  updateFeatureAttributes( f, true );
1859  }
1860  return true;
1861  }
1862 
1863  //added features
1864  for ( QgsFeatureList::iterator iter = mAddedFeatures.begin(); iter != mAddedFeatures.end(); ++iter )
1865  {
1866  if ( iter->id() == featureId )
1867  {
1868  f.setFeatureId( iter->id() );
1869  f.setValid( true );
1870  if ( fetchGeometries )
1871  f.setGeometry( *iter->geometry() );
1872 
1873  if ( fetchAttributes )
1874  f.setAttributeMap( iter->attributeMap() );
1875 
1876  return true;
1877  }
1878  }
1879 
1880  // regular features
1881  if ( fetchAttributes )
1882  {
1883  if ( mDataProvider->featureAtId( featureId, f, fetchGeometries, mDataProvider->attributeIndexes() ) )
1884  {
1885  updateFeatureAttributes( f, true );
1886  return true;
1887  }
1888  }
1889  else
1890  {
1891  if ( mDataProvider->featureAtId( featureId, f, fetchGeometries, QgsAttributeList() ) )
1892  {
1893  return true;
1894  }
1895  }
1896  return false;
1897 }
1898 
1899 bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
1900 {
1901  static int addedIdLowWaterMark = -1;
1902 
1903  if ( !mDataProvider )
1904  {
1905  return false;
1906  }
1907 
1909  {
1910  return false;
1911  }
1912 
1913  if ( !isEditable() )
1914  {
1915  return false;
1916  }
1917 
1918  //assign a temporary id to the feature (use negative numbers)
1919  addedIdLowWaterMark--;
1920 
1921  QgsDebugMsg( "Assigned feature id " + QString::number( addedIdLowWaterMark ) );
1922 
1923  // Force a feature ID (to keep other functions in QGIS happy,
1924  // providers will use their own new feature ID when we commit the new feature)
1925  // and add to the known added features.
1926  f.setFeatureId( addedIdLowWaterMark );
1927  editFeatureAdd( f );
1928 
1929  if ( f.geometry() )
1930  mCachedGeometries[f.id()] = *f.geometry();
1931 
1932  setModified( true );
1933 
1934  if ( alsoUpdateExtent )
1935  {
1936  updateExtents();
1937  }
1938 
1939  emit featureAdded( f.id() );
1940 
1941  return true;
1942 }
1943 
1944 
1945 bool QgsVectorLayer::insertVertex( double x, double y, int atFeatureId, int beforeVertex )
1946 {
1947  if ( !hasGeometryType() )
1948  return false;
1949 
1950  if ( !mEditable )
1951  {
1952  return false;
1953  }
1954 
1955  if ( mDataProvider )
1956  {
1957  QgsGeometry geometry;
1958  if ( !mChangedGeometries.contains( atFeatureId ) )
1959  {
1960  // first time this geometry has changed since last commit
1961  if ( !mCachedGeometries.contains( atFeatureId ) )
1962  {
1963  return false;
1964  }
1965  geometry = mCachedGeometries[atFeatureId];
1966  //mChangedGeometries[atFeatureId] = mCachedGeometries[atFeatureId];
1967  }
1968  else
1969  {
1970  geometry = mChangedGeometries[atFeatureId];
1971  }
1972  geometry.insertVertex( x, y, beforeVertex );
1973  mCachedGeometries[atFeatureId] = geometry;
1974  editGeometryChange( atFeatureId, geometry );
1975 
1976  setModified( true, true ); // only geometry was changed
1977 
1978  return true;
1979  }
1980  return false;
1981 }
1982 
1983 
1984 bool QgsVectorLayer::moveVertex( double x, double y, int atFeatureId, int atVertex )
1985 {
1986  if ( !hasGeometryType() )
1987  return false;
1988 
1989  if ( !mEditable )
1990  {
1991  return false;
1992  }
1993 
1994  if ( mDataProvider )
1995  {
1996  QgsGeometry geometry;
1997  if ( !mChangedGeometries.contains( atFeatureId ) )
1998  {
1999  // first time this geometry has changed since last commit
2000  if ( !mCachedGeometries.contains( atFeatureId ) )
2001  {
2002  return false;
2003  }
2004  geometry = mCachedGeometries[atFeatureId];
2005  //mChangedGeometries[atFeatureId] = mCachedGeometries[atFeatureId];
2006  }
2007  else
2008  {
2009  geometry = mChangedGeometries[atFeatureId];
2010  }
2011 
2012  geometry.moveVertex( x, y, atVertex );
2013  mCachedGeometries[atFeatureId] = geometry;
2014  editGeometryChange( atFeatureId, geometry );
2015 
2016  setModified( true, true ); // only geometry was changed
2017 
2018  return true;
2019  }
2020  return false;
2021 }
2022 
2023 
2024 bool QgsVectorLayer::deleteVertex( int atFeatureId, int atVertex )
2025 {
2026  if ( !hasGeometryType() )
2027  return false;
2028 
2029  if ( !mEditable )
2030  {
2031  return false;
2032  }
2033 
2034  if ( mDataProvider )
2035  {
2036  QgsGeometry geometry;
2037  if ( !mChangedGeometries.contains( atFeatureId ) )
2038  {
2039  // first time this geometry has changed since last commit
2040  if ( !mCachedGeometries.contains( atFeatureId ) )
2041  {
2042  return false;
2043  }
2044  geometry = mCachedGeometries[atFeatureId];
2045  }
2046  else
2047  {
2048  geometry = mChangedGeometries[atFeatureId];
2049  }
2050 
2051  if ( !geometry.deleteVertex( atVertex ) )
2052  {
2053  return false;
2054  }
2055  mCachedGeometries[atFeatureId] = geometry;
2056  editGeometryChange( atFeatureId, geometry );
2057 
2058  setModified( true, true ); // only geometry was changed
2059 
2060  return true;
2061  }
2062  return false;
2063 }
2064 
2065 
2067 {
2069  {
2070  return false;
2071  }
2072 
2073  if ( !isEditable() )
2074  {
2075  return false;
2076  }
2077 
2078  if ( mSelectedFeatureIds.size() == 0 )
2079  return true;
2080 
2081  while ( mSelectedFeatureIds.size() > 0 )
2082  {
2083  int fid = *mSelectedFeatureIds.begin();
2084  deleteFeature( fid ); // removes from selection
2085  }
2086 
2087  // invalidate cache
2088  setCacheImage( 0 );
2089 
2090  emit selectionChanged();
2091 
2092  triggerRepaint();
2093  updateExtents();
2094 
2095  return true;
2096 }
2097 
2098 int QgsVectorLayer::addRing( const QList<QgsPoint>& ring )
2099 {
2100  if ( !hasGeometryType() )
2101  return 5;
2102 
2103  int addRingReturnCode = 5; //default: return code for 'ring not inserted'
2104  double xMin, yMin, xMax, yMax;
2105  QgsRectangle bBox;
2106 
2107  if ( boundingBoxFromPointList( ring, xMin, yMin, xMax, yMax ) == 0 )
2108  {
2109  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
2110  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
2111  }
2112  else
2113  {
2114  return 3; //ring not valid
2115  }
2116 
2117  select( QgsAttributeList(), bBox, true, true );
2118 
2119  QgsFeature f;
2120  while ( nextFeature( f ) )
2121  {
2122  addRingReturnCode = f.geometry()->addRing( ring );
2123  if ( addRingReturnCode == 0 )
2124  {
2125  editGeometryChange( f.id(), *f.geometry() );
2126 
2127  setModified( true, true );
2128  break;
2129  }
2130  }
2131 
2132  return addRingReturnCode;
2133 }
2134 
2135 int QgsVectorLayer::addIsland( const QList<QgsPoint>& ring )
2136 {
2137  if ( !hasGeometryType() )
2138  return 6;
2139 
2140  //number of selected features must be 1
2141 
2142  if ( mSelectedFeatureIds.size() < 1 )
2143  {
2144  QgsDebugMsg( "Number of selected features <1" );
2145  return 4;
2146  }
2147  else if ( mSelectedFeatureIds.size() > 1 )
2148  {
2149  QgsDebugMsg( "Number of selected features >1" );
2150  return 5;
2151  }
2152 
2153  int selectedFeatureId = *mSelectedFeatureIds.constBegin();
2154 
2155  //look if geometry of selected feature already contains geometry changes
2156  QgsGeometryMap::iterator changedIt = mChangedGeometries.find( selectedFeatureId );
2157  if ( changedIt != mChangedGeometries.end() )
2158  {
2159  QgsGeometry geom = *changedIt;
2160  int returnValue = geom.addIsland( ring );
2161  editGeometryChange( selectedFeatureId, geom );
2162  mCachedGeometries[selectedFeatureId] = geom;
2163  return returnValue;
2164  }
2165 
2166  //look if id of selected feature belongs to an added feature
2167 #if 0
2168  for ( QgsFeatureList::iterator addedIt = mAddedFeatures.begin(); addedIt != mAddedFeatures.end(); ++addedIt )
2169  {
2170  if ( addedIt->id() == selectedFeatureId )
2171  {
2172  return addedIt->geometry()->addIsland( ring );
2173  mCachedGeometries[selectedFeatureId] = *addedIt->geometry();
2174  }
2175  }
2176 #endif
2177 
2178  //is the feature contained in the view extent (mCachedGeometries) ?
2179  QgsGeometryMap::iterator cachedIt = mCachedGeometries.find( selectedFeatureId );
2180  if ( cachedIt != mCachedGeometries.end() )
2181  {
2182  int errorCode = cachedIt->addIsland( ring );
2183  if ( errorCode == 0 )
2184  {
2185  editGeometryChange( selectedFeatureId, *cachedIt );
2186  mCachedGeometries[selectedFeatureId] = *cachedIt;
2187  setModified( true, true );
2188  }
2189  return errorCode;
2190  }
2191  else //maybe the selected feature has been moved outside the visible area and therefore is not contained in mCachedGeometries
2192  {
2193  QgsFeature f;
2194  QgsGeometry* fGeom = 0;
2195  if ( featureAtId( selectedFeatureId, f, true, false ) )
2196  {
2197  fGeom = f.geometryAndOwnership();
2198  if ( fGeom )
2199  {
2200  int errorCode = fGeom->addIsland( ring );
2201  editGeometryChange( selectedFeatureId, *fGeom );
2202  setModified( true, true );
2203  delete fGeom;
2204  return errorCode;
2205  }
2206  }
2207  }
2208 
2209  return 6; //geometry not found
2210 }
2211 
2212 int QgsVectorLayer::translateFeature( int featureId, double dx, double dy )
2213 {
2214  if ( !hasGeometryType() )
2215  return 1;
2216 
2217  //look if geometry of selected feature already contains geometry changes
2218  QgsGeometryMap::iterator changedIt = mChangedGeometries.find( featureId );
2219  if ( changedIt != mChangedGeometries.end() )
2220  {
2221  QgsGeometry geom = *changedIt;
2222  int errorCode = geom.translate( dx, dy );
2223  editGeometryChange( featureId, geom );
2224  return errorCode;
2225  }
2226 
2227  //look if id of selected feature belongs to an added feature
2228 #if 0
2229  for ( QgsFeatureList::iterator addedIt = mAddedFeatures.begin(); addedIt != mAddedFeatures.end(); ++addedIt )
2230  {
2231  if ( addedIt->id() == featureId )
2232  {
2233  return addedIt->geometry()->translate( dx, dy );
2234  }
2235  }
2236 #endif
2237 
2238  //else look in mCachedGeometries to make access faster
2239  QgsGeometryMap::iterator cachedIt = mCachedGeometries.find( featureId );
2240  if ( cachedIt != mCachedGeometries.end() )
2241  {
2242  int errorCode = cachedIt->translate( dx, dy );
2243  if ( errorCode == 0 )
2244  {
2245  editGeometryChange( featureId, *cachedIt );
2246  setModified( true, true );
2247  }
2248  return errorCode;
2249  }
2250 
2251  //else get the geometry from provider (may be slow)
2252  QgsFeature f;
2253  if ( mDataProvider && mDataProvider->featureAtId( featureId, f, true ) )
2254  {
2255  if ( f.geometry() )
2256  {
2257  QgsGeometry translateGeom( *( f.geometry() ) );
2258  int errorCode = translateGeom.translate( dx, dy );
2259  if ( errorCode == 0 )
2260  {
2261  editGeometryChange( featureId, translateGeom );
2262  setModified( true, true );
2263  }
2264  return errorCode;
2265  }
2266  }
2267  return 1; //geometry not found
2268 }
2269 
2270 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
2271 {
2272  if ( !hasGeometryType() )
2273  return 4;
2274 
2275  QgsFeatureList newFeatures; //store all the newly created features
2276  double xMin, yMin, xMax, yMax;
2277  QgsRectangle bBox; //bounding box of the split line
2278  int returnCode = 0;
2279  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
2280  int numberOfSplittedFeatures = 0;
2281 
2282  QgsFeatureList featureList;
2283  const QgsFeatureIds selectedIds = selectedFeaturesIds();
2284 
2285  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
2286  {
2287  featureList = selectedFeatures();
2288  }
2289  else //else consider all the feature that intersect the bounding box of the split line
2290  {
2291  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
2292  {
2293  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
2294  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
2295  }
2296  else
2297  {
2298  return 1;
2299  }
2300 
2301  if ( bBox.isEmpty() )
2302  {
2303  //if the bbox is a line, try to make a square out of it
2304  if ( bBox.width() == 0.0 && bBox.height() > 0 )
2305  {
2306  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
2307  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
2308  }
2309  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
2310  {
2311  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
2312  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
2313  }
2314  else
2315  {
2316  return 2;
2317  }
2318  }
2319 
2320  select( pendingAllAttributesList(), bBox, true, true );
2321 
2322  QgsFeature f;
2323  while ( nextFeature( f ) )
2324  featureList << QgsFeature( f );
2325  }
2326 
2327  QgsFeatureList::iterator select_it = featureList.begin();
2328  for ( ; select_it != featureList.end(); ++select_it )
2329  {
2330  QList<QgsGeometry*> newGeometries;
2331  QList<QgsPoint> topologyTestPoints;
2332  QgsGeometry* newGeometry = 0;
2333  splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
2334  if ( splitFunctionReturn == 0 )
2335  {
2336  //change this geometry
2337  editGeometryChange( select_it->id(), *( select_it->geometry() ) );
2338  //update of cached geometries is necessary because we use addTopologicalPoints() later
2339  mCachedGeometries[select_it->id()] = *( select_it->geometry() );
2340 
2341  //insert new features
2342  for ( int i = 0; i < newGeometries.size(); ++i )
2343  {
2344  newGeometry = newGeometries.at( i );
2345  QgsFeature newFeature;
2346  newFeature.setGeometry( newGeometry );
2347  newFeature.setAttributeMap( select_it->attributeMap() );
2348  newFeatures.append( newFeature );
2349  }
2350 
2351  setModified( true, true );
2352  if ( topologicalEditing )
2353  {
2354  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
2355  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
2356  {
2357  addTopologicalPoints( *topol_it );
2358  }
2359  }
2360  ++numberOfSplittedFeatures;
2361  }
2362  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
2363  {
2364  returnCode = splitFunctionReturn;
2365  }
2366  }
2367 
2368  if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
2369  {
2370  //There is a selection but no feature has been split.
2371  //Maybe user forgot that only the selected features are split
2372  returnCode = 4;
2373  }
2374 
2375 
2376  //now add the new features to this vectorlayer
2377  addFeatures( newFeatures, false );
2378 
2379  return returnCode;
2380 }
2381 
2383 {
2384  if ( !hasGeometryType() )
2385  return 1;
2386 
2387  int returnValue = 0;
2388 
2389  //first test if geom really has type polygon or multipolygon
2390  if ( geom->type() != QGis::Polygon )
2391  {
2392  return 1;
2393  }
2394 
2395  //get bounding box of geom
2396  QgsRectangle geomBBox = geom->boundingBox();
2397 
2398  //get list of features that intersect this bounding box
2399  select( QgsAttributeList(), geomBBox, true, true );
2400 
2401  QgsFeature f;
2402  while ( nextFeature( f ) )
2403  {
2404  //call geometry->makeDifference for each feature
2405  QgsGeometry *currentGeom = f.geometry();
2406  if ( currentGeom )
2407  {
2408  if ( geom->makeDifference( currentGeom ) != 0 )
2409  {
2410  returnValue = 2;
2411  }
2412  }
2413  }
2414  return returnValue;
2415 }
2416 
2418 {
2419  if ( !hasGeometryType() )
2420  return 1;
2421 
2422  if ( !geom )
2423  {
2424  return 1;
2425  }
2426 
2427  int returnVal = 0;
2428 
2429  QGis::WkbType wkbType = geom->wkbType();
2430 
2431  switch ( wkbType )
2432  {
2433  //line
2435  case QGis::WKBLineString:
2436  {
2437  QgsPolyline theLine = geom->asPolyline();
2438  QgsPolyline::const_iterator line_it = theLine.constBegin();
2439  for ( ; line_it != theLine.constEnd(); ++line_it )
2440  {
2441  if ( addTopologicalPoints( *line_it ) != 0 )
2442  {
2443  returnVal = 2;
2444  }
2445  }
2446  break;
2447  }
2448 
2449  //multiline
2452  {
2453  QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
2454  QgsPolyline currentPolyline;
2455 
2456  for ( int i = 0; i < theMultiLine.size(); ++i )
2457  {
2458  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
2459  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
2460  {
2461  if ( addTopologicalPoints( *line_it ) != 0 )
2462  {
2463  returnVal = 2;
2464  }
2465  }
2466  }
2467  break;
2468  }
2469 
2470  //polygon
2471  case QGis::WKBPolygon25D:
2472  case QGis::WKBPolygon:
2473  {
2474  QgsPolygon thePolygon = geom->asPolygon();
2475  QgsPolyline currentRing;
2476 
2477  for ( int i = 0; i < thePolygon.size(); ++i )
2478  {
2479  currentRing = thePolygon.at( i );
2480  QgsPolyline::const_iterator line_it = currentRing.constBegin();
2481  for ( ; line_it != currentRing.constEnd(); ++line_it )
2482  {
2483  if ( addTopologicalPoints( *line_it ) != 0 )
2484  {
2485  returnVal = 2;
2486  }
2487  }
2488  }
2489  break;
2490  }
2491 
2492  //multipolygon
2494  case QGis::WKBMultiPolygon:
2495  {
2496  QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
2497  QgsPolygon currentPolygon;
2498  QgsPolyline currentRing;
2499 
2500  for ( int i = 0; i < theMultiPolygon.size(); ++i )
2501  {
2502  currentPolygon = theMultiPolygon.at( i );
2503  for ( int j = 0; j < currentPolygon.size(); ++j )
2504  {
2505  currentRing = currentPolygon.at( j );
2506  QgsPolyline::const_iterator line_it = currentRing.constBegin();
2507  for ( ; line_it != currentRing.constEnd(); ++line_it )
2508  {
2509  if ( addTopologicalPoints( *line_it ) != 0 )
2510  {
2511  returnVal = 2;
2512  }
2513  }
2514  }
2515  }
2516  break;
2517  }
2518  default:
2519  break;
2520  }
2521  return returnVal;
2522 }
2523 
2525 {
2526  if ( !hasGeometryType() )
2527  return 1;
2528 
2529  QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
2530  //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
2531  QMultiMap<double, QgsSnappingResult> vertexSnapResults;
2532 
2533  QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
2534 
2535  //work with a tolerance because coordinate projection may introduce some rounding
2536  double threshold = 0.0000001;
2537  if ( mCRS && mCRS->mapUnits() == QGis::Meters )
2538  {
2539  threshold = 0.001;
2540  }
2541  else if ( mCRS && mCRS->mapUnits() == QGis::Feet )
2542  {
2543  threshold = 0.0001;
2544  }
2545 
2546 
2547  if ( snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
2548  {
2549  return 2;
2550  }
2551 
2552  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
2553  QMultiMap<double, QgsSnappingResult>::const_iterator vertex_snap_it;
2554  for ( ; snap_it != snapResults.constEnd(); ++snap_it )
2555  {
2556  //test if p is already a vertex of this geometry. If yes, don't insert it
2557  bool vertexAlreadyExists = false;
2558  if ( snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
2559  {
2560  continue;
2561  }
2562 
2563  vertex_snap_it = vertexSnapResults.constBegin();
2564  for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
2565  {
2566  if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
2567  {
2568  vertexAlreadyExists = true;
2569  }
2570  }
2571 
2572  if ( !vertexAlreadyExists )
2573  {
2574  filteredSnapResults.push_back( *snap_it );
2575  }
2576  }
2577  insertSegmentVerticesForSnap( filteredSnapResults );
2578  return 0;
2579 }
2580 
2582 {
2583  return mLabel;
2584 }
2585 
2587 {
2588  return mLabel;
2589 }
2590 
2592 {
2593  mLabelOn = on;
2594 }
2595 
2597 {
2598  return mLabelOn;
2599 }
2600 
2602 {
2603  if ( !mDataProvider )
2604  {
2605  return false;
2606  }
2607 
2608  // allow editing if provider supports any of the capabilities
2610  {
2611  return false;
2612  }
2613 
2614  if ( mReadOnly )
2615  {
2616  return false;
2617  }
2618 
2619  if ( mEditable )
2620  {
2621  // editing already underway
2622  return false;
2623  }
2624 
2625  mEditable = true;
2626 
2627  mAddedAttributeIds.clear();
2628  mDeletedAttributeIds.clear();
2629  updateFieldMap();
2630 
2631  for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
2632  if ( it.key() > mMaxUpdatedIndex )
2633  mMaxUpdatedIndex = it.key();
2634 
2635  emit editingStarted();
2636 
2637  return true;
2638 }
2639 
2640 bool QgsVectorLayer::readXml( QDomNode & layer_node )
2641 {
2642  QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
2643 
2644  //process provider key
2645  QDomNode pkeyNode = layer_node.namedItem( "provider" );
2646 
2647  if ( pkeyNode.isNull() )
2648  {
2649  mProviderKey = "";
2650  }
2651  else
2652  {
2653  QDomElement pkeyElt = pkeyNode.toElement();
2654  mProviderKey = pkeyElt.text();
2655  }
2656 
2657  // determine type of vector layer
2658  if ( ! mProviderKey.isNull() )
2659  {
2660  // if the provider string isn't empty, then we successfully
2661  // got the stored provider
2662  }
2663  else if ( mDataSource.contains( "dbname=" ) )
2664  {
2665  mProviderKey = "postgres";
2666  }
2667  else
2668  {
2669  mProviderKey = "ogr";
2670  }
2671 
2672  if ( ! setDataProvider( mProviderKey ) )
2673  {
2674  return false;
2675  }
2676 
2677  QDomElement pkeyElem = pkeyNode.toElement();
2678  if ( !pkeyElem.isNull() )
2679  {
2680  QString encodingString = pkeyElem.attribute( "encoding" );
2681  if ( !encodingString.isEmpty() )
2682  {
2683  mDataProvider->setEncoding( encodingString );
2684  }
2685  }
2686 
2687  //load vector joins
2688  if ( !mJoinBuffer )
2689  {
2691  }
2692  mJoinBuffer->readXml( layer_node );
2693 
2694  updateFieldMap();
2695 
2696  QString errorMsg;
2697  if ( !readSymbology( layer_node, errorMsg ) )
2698  {
2699  return false;
2700  }
2701 
2702  return mValid; // should be true if read successfully
2703 
2704 } // void QgsVectorLayer::readXml
2705 
2706 
2707 
2708 bool QgsVectorLayer::setDataProvider( QString const & provider )
2709 {
2710  // XXX should I check for and possibly delete any pre-existing providers?
2711  // XXX How often will that scenario occur?
2712 
2713  mProviderKey = provider; // XXX is this necessary? Usually already set
2714  // XXX when execution gets here.
2715 
2716  //XXX - This was a dynamic cast but that kills the Windows
2717  // version big-time with an abnormal termination error
2718  mDataProvider =
2720 
2721  if ( mDataProvider )
2722  {
2723  QgsDebugMsg( "Instantiated the data provider plugin" );
2724 
2726  if ( mValid )
2727  {
2728 
2729  // TODO: Check if the provider has the capability to send fullExtentCalculated
2730  connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
2731 
2732  // get the extent
2734 
2735  // show the extent
2736  QString s = mbr.toString();
2737  QgsDebugMsg( "Extent of layer: " + s );
2738  // store the extent
2743 
2744  // get and store the feature type
2746 
2747  // look at the fields in the layer and set the primary
2748  // display field using some real fuzzy logic
2749  setDisplayField();
2750 
2751  if ( mProviderKey == "postgres" )
2752  {
2753  QgsDebugMsg( "Beautifying layer name " + name() );
2754 
2755  // adjust the display name for postgres layers
2756  QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
2757  if ( reg.indexIn( name() ) >= 0 )
2758  {
2759  QStringList stuff = reg.capturedTexts();
2760  QString lName = stuff[1];
2761 
2762  const QMap<QString, QgsMapLayer*> &layers = QgsMapLayerRegistry::instance()->mapLayers();
2763 
2764  QMap<QString, QgsMapLayer*>::const_iterator it;
2765  for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; it++ )
2766  ;
2767 
2768  if ( it != layers.constEnd() && stuff.size() > 2 )
2769  {
2770  lName += "." + stuff[2].mid( 2, stuff[2].length() - 3 );
2771  }
2772 
2773  if ( !lName.isEmpty() )
2774  setLayerName( lName );
2775  }
2776 
2777  QgsDebugMsg( "Beautified layer name " + name() );
2778 
2779  // deal with unnecessary schema qualification to make v.in.ogr happy
2781  }
2782  else if ( mProviderKey == "osm" )
2783  {
2784  // make sure that the "observer" has been removed from URI to avoid crashes
2786  }
2787 
2788  // label
2789  mLabel = new QgsLabel( mDataProvider->fields() );
2790  mLabelOn = false;
2791  }
2792  else
2793  {
2794  QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
2795  return false;
2796  }
2797  }
2798  else
2799  {
2800  QgsDebugMsg( " unable to get data provider" );
2801 
2802  return false;
2803  }
2804 
2805  return true;
2806 
2807 } // QgsVectorLayer:: setDataProvider
2808 
2809 
2810 
2811 
2812 /* virtual */
2813 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
2814  QDomDocument & document )
2815 {
2816  // first get the layer element so that we can append the type attribute
2817 
2818  QDomElement mapLayerNode = layer_node.toElement();
2819 
2820  if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
2821  {
2822  QgsDebugMsg( "can't find <maplayer>" );
2823  return false;
2824  }
2825 
2826  mapLayerNode.setAttribute( "type", "vector" );
2827 
2828  // set the geometry type
2829  mapLayerNode.setAttribute( "geometry", QGis::qgisVectorGeometryType[geometryType()] );
2830 
2831  // add provider node
2832  if ( mDataProvider )
2833  {
2834  QDomElement provider = document.createElement( "provider" );
2835  provider.setAttribute( "encoding", mDataProvider->encoding() );
2836  QDomText providerText = document.createTextNode( providerType() );
2837  provider.appendChild( providerText );
2838  layer_node.appendChild( provider );
2839  }
2840 
2841  //save joins
2842  mJoinBuffer->writeXml( layer_node, document );
2843 
2844  // renderer specific settings
2845  QString errorMsg;
2846  return writeSymbology( layer_node, document, errorMsg );
2847 } // bool QgsVectorLayer::writeXml
2848 
2849 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
2850 {
2851  if ( hasGeometryType() )
2852  {
2853  // try renderer v2 first
2854  QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
2855  if ( !rendererElement.isNull() )
2856  {
2857  // using renderer v2
2858  setUsingRendererV2( true );
2859 
2860  QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
2861  if ( r == NULL )
2862  return false;
2863 
2864  setRendererV2( r );
2865  }
2866  else
2867  {
2868  // using renderer v1
2869  setUsingRendererV2( false );
2870 
2871  // create and bind a renderer to this layer
2872 
2873  QDomNode singlenode = node.namedItem( "singlesymbol" );
2874  QDomNode graduatednode = node.namedItem( "graduatedsymbol" );
2875  QDomNode continuousnode = node.namedItem( "continuoussymbol" );
2876  QDomNode uniquevaluenode = node.namedItem( "uniquevalue" );
2877 
2878  QgsRenderer * renderer = 0;
2879  int returnCode = 1;
2880 
2881  if ( !singlenode.isNull() )
2882  {
2883  renderer = new QgsSingleSymbolRenderer( geometryType() );
2884  returnCode = renderer->readXML( singlenode, *this );
2885  }
2886  else if ( !graduatednode.isNull() )
2887  {
2888  renderer = new QgsGraduatedSymbolRenderer( geometryType() );
2889  returnCode = renderer->readXML( graduatednode, *this );
2890  }
2891  else if ( !continuousnode.isNull() )
2892  {
2893  renderer = new QgsContinuousColorRenderer( geometryType() );
2894  returnCode = renderer->readXML( continuousnode, *this );
2895  }
2896  else if ( !uniquevaluenode.isNull() )
2897  {
2898  renderer = new QgsUniqueValueRenderer( geometryType() );
2899  returnCode = renderer->readXML( uniquevaluenode, *this );
2900  }
2901 
2902  if ( !renderer )
2903  {
2904  errorMessage = tr( "Unknown renderer" );
2905  return false;
2906  }
2907 
2908  if ( returnCode == 1 )
2909  {
2910  errorMessage = tr( "No renderer object" ); delete renderer; return false;
2911  }
2912  else if ( returnCode == 2 )
2913  {
2914  errorMessage = tr( "Classification field not found" ); delete renderer; return false;
2915  }
2916 
2917  mRenderer = renderer;
2918  }
2919 
2920  // get and set the display field if it exists.
2921  QDomNode displayFieldNode = node.namedItem( "displayfield" );
2922  if ( !displayFieldNode.isNull() )
2923  {
2924  QDomElement e = displayFieldNode.toElement();
2925  setDisplayField( e.text() );
2926  }
2927 
2928  // use scale dependent visibility flag
2929  QDomElement e = node.toElement();
2930  mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
2931  mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
2932  mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
2933 
2934  //also restore custom properties (for labeling-ng)
2935  readCustomProperties( node, "labeling" );
2936 
2937  // Test if labeling is on or off
2938  QDomNode labelnode = node.namedItem( "label" );
2939  QDomElement element = labelnode.toElement();
2940  int hasLabelsEnabled = element.text().toInt();
2941  if ( hasLabelsEnabled < 1 )
2942  {
2943  enableLabels( false );
2944  }
2945  else
2946  {
2947  enableLabels( true );
2948  }
2949 
2950  QDomNode labelattributesnode = node.namedItem( "labelattributes" );
2951 
2952  if ( !labelattributesnode.isNull() )
2953  {
2954  QgsDebugMsg( "calling readXML" );
2955  mLabel->readXML( labelattributesnode );
2956  }
2957 
2958  //diagram renderer and diagram layer settings
2959  delete mDiagramRenderer; mDiagramRenderer = 0;
2960  QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
2961  if ( !singleCatDiagramElem.isNull() )
2962  {
2964  mDiagramRenderer->readXML( singleCatDiagramElem );
2965  }
2966  QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
2967  if ( !linearDiagramElem.isNull() )
2968  {
2970  mDiagramRenderer->readXML( linearDiagramElem );
2971  }
2972 
2973  if ( mDiagramRenderer )
2974  {
2975  QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
2976  if ( !diagramSettingsElem.isNull() )
2977  {
2979  mDiagramLayerSettings->readXML( diagramSettingsElem );
2980  }
2981  }
2982  }
2983 
2984  // process the attribute actions
2985  mActions->readXML( node );
2986 
2987  mEditTypes.clear();
2988  QDomNode editTypesNode = node.namedItem( "edittypes" );
2989  if ( !editTypesNode.isNull() )
2990  {
2991  QDomNodeList editTypeNodes = editTypesNode.childNodes();
2992 
2993  for ( int i = 0; i < editTypeNodes.size(); i++ )
2994  {
2995  QDomNode editTypeNode = editTypeNodes.at( i );
2996  QDomElement editTypeElement = editTypeNode.toElement();
2997 
2998  QString name = editTypeElement.attribute( "name" );
2999  if ( fieldNameIndex( name ) < -1 )
3000  continue;
3001 
3002  EditType editType = ( EditType ) editTypeElement.attribute( "type" ).toInt();
3003  mEditTypes.insert( name, editType );
3004 
3005  if ( editType == ValueMap && editTypeNode.hasChildNodes() )
3006  {
3007  mValueMaps.insert( name, QMap<QString, QVariant>() );
3008 
3009  QDomNodeList valueMapNodes = editTypeNode.childNodes();
3010  for ( int j = 0; j < valueMapNodes.size(); j++ )
3011  {
3012  QDomElement value = valueMapNodes.at( j ).toElement();
3013  mValueMaps[ name ].insert( value.attribute( "key" ), value.attribute( "value" ) );
3014  }
3015  }
3016  else if ( editType == EditRange || editType == SliderRange )
3017  {
3018  QVariant min = editTypeElement.attribute( "min" );
3019  QVariant max = editTypeElement.attribute( "max" );
3020  QVariant step = editTypeElement.attribute( "step" );
3021 
3022  mRanges[ name ] = RangeData( min, max, step );
3023  }
3024  else if ( editType == CheckBox )
3025  {
3026  mCheckedStates[ name ] = QPair<QString, QString>( editTypeElement.attribute( "checked" ), editTypeElement.attribute( "unchecked" ) );
3027  }
3028  }
3029  }
3030 
3031  QDomNode editFormNode = node.namedItem( "editform" );
3032  if ( !editFormNode.isNull() )
3033  {
3034  QDomElement e = editFormNode.toElement();
3035  mEditForm = QgsProject::instance()->readPath( e.text() );
3036  }
3037 
3038  QDomNode editFormInitNode = node.namedItem( "editforminit" );
3039  if ( !editFormInitNode.isNull() )
3040  {
3041  mEditFormInit = editFormInitNode.toElement().text();
3042  }
3043 
3044  QDomNode annotationFormNode = node.namedItem( "annotationform" );
3045  if ( !annotationFormNode.isNull() )
3046  {
3047  QDomElement e = annotationFormNode.toElement();
3049  }
3050 
3051  mAttributeAliasMap.clear();
3052  QDomNode aliasesNode = node.namedItem( "aliases" );
3053  if ( !aliasesNode.isNull() )
3054  {
3055  QDomElement aliasElem;
3056  QString name;
3057 
3058  QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
3059  for ( int i = 0; i < aliasNodeList.size(); ++i )
3060  {
3061  aliasElem = aliasNodeList.at( i ).toElement();
3062 
3063  QString field;
3064  if ( aliasElem.hasAttribute( "field" ) )
3065  {
3066  field = aliasElem.attribute( "field" );
3067  }
3068  else
3069  {
3070  int index = aliasElem.attribute( "index" ).toInt();
3071 
3072  if ( pendingFields().contains( index ) )
3073  field = pendingFields()[ index ].name();
3074  }
3075 
3076  mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
3077  }
3078  }
3079 
3080  return true;
3081 }
3082 
3083 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
3084 {
3085  QDomElement mapLayerNode = node.toElement();
3086 
3087  if ( hasGeometryType() )
3088  {
3089  if ( mUsingRendererV2 )
3090  {
3091  QDomElement rendererElement = mRendererV2->save( doc );
3092  node.appendChild( rendererElement );
3093  }
3094  else
3095  {
3096  // use scale dependent visibility flag
3097  mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
3098  mapLayerNode.setAttribute( "minLabelScale", mLabel->minScale() );
3099  mapLayerNode.setAttribute( "maxLabelScale", mLabel->maxScale() );
3100 
3101  //classification field(s)
3103  const QgsFieldMap providerFields = mDataProvider->fields();
3104  for ( QgsAttributeList::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
3105  {
3106  QDomElement classificationElement = doc.createElement( "classificationattribute" );
3107  QDomText classificationText = doc.createTextNode( providerFields[*it].name() );
3108  classificationElement.appendChild( classificationText );
3109  node.appendChild( classificationElement );
3110  }
3111 
3112  // renderer settings
3113  const QgsRenderer * myRenderer = renderer();
3114  if ( myRenderer )
3115  {
3116  if ( !myRenderer->writeXML( node, doc, *this ) )
3117  {
3118  errorMessage = tr( "renderer failed to save" );
3119  return false;
3120  }
3121  }
3122  else
3123  {
3124  QgsDebugMsg( "no renderer" );
3125  errorMessage = tr( "no renderer" );
3126  return false;
3127  }
3128  }
3129 
3130  //save customproperties (for labeling ng)
3131  writeCustomProperties( node, doc );
3132 
3133  // add the display field
3134  QDomElement dField = doc.createElement( "displayfield" );
3135  QDomText dFieldText = doc.createTextNode( displayField() );
3136  dField.appendChild( dFieldText );
3137  node.appendChild( dField );
3138 
3139  // add label node
3140  QDomElement labelElem = doc.createElement( "label" );
3141  QDomText labelText = doc.createTextNode( "" );
3142 
3143  if ( hasLabelsEnabled() )
3144  {
3145  labelText.setData( "1" );
3146  }
3147  else
3148  {
3149  labelText.setData( "0" );
3150  }
3151  labelElem.appendChild( labelText );
3152 
3153  node.appendChild( labelElem );
3154 
3155  // Now we get to do all that all over again for QgsLabel
3156 
3157  QString fieldname = mLabel->labelField( QgsLabel::Text );
3158  if ( fieldname != "" )
3159  {
3160  dField = doc.createElement( "labelfield" );
3161  dFieldText = doc.createTextNode( fieldname );
3162  dField.appendChild( dFieldText );
3163  node.appendChild( dField );
3164  }
3165 
3166  mLabel->writeXML( node, doc );
3167 
3168  if ( mDiagramRenderer )
3169  {
3170  mDiagramRenderer->writeXML( mapLayerNode, doc );
3171  if ( mDiagramLayerSettings )
3172  mDiagramLayerSettings->writeXML( mapLayerNode, doc );
3173  }
3174  }
3175 
3176  //edit types
3177  if ( mEditTypes.size() > 0 )
3178  {
3179  QDomElement editTypesElement = doc.createElement( "edittypes" );
3180 
3181  for ( QMap<QString, EditType>::const_iterator it = mEditTypes.begin(); it != mEditTypes.end(); ++it )
3182  {
3183  QDomElement editTypeElement = doc.createElement( "edittype" );
3184  editTypeElement.setAttribute( "name", it.key() );
3185  editTypeElement.setAttribute( "type", it.value() );
3186 
3187  switch (( EditType ) it.value() )
3188  {
3189  case ValueMap:
3190  if ( mValueMaps.contains( it.key() ) )
3191  {
3192  const QMap<QString, QVariant> &map = mValueMaps[ it.key()];
3193 
3194  for ( QMap<QString, QVariant>::const_iterator vmit = map.begin(); vmit != map.end(); vmit++ )
3195  {
3196  QDomElement value = doc.createElement( "valuepair" );
3197  value.setAttribute( "key", vmit.key() );
3198  value.setAttribute( "value", vmit.value().toString() );
3199  editTypeElement.appendChild( value );
3200  }
3201  }
3202  break;
3203 
3204  case EditRange:
3205  case SliderRange:
3206  case DialRange:
3207  if ( mRanges.contains( it.key() ) )
3208  {
3209  editTypeElement.setAttribute( "min", mRanges[ it.key()].mMin.toString() );
3210  editTypeElement.setAttribute( "max", mRanges[ it.key()].mMax.toString() );
3211  editTypeElement.setAttribute( "step", mRanges[ it.key()].mStep.toString() );
3212  }
3213  break;
3214 
3215  case CheckBox:
3216  if ( mCheckedStates.contains( it.key() ) )
3217  {
3218  editTypeElement.setAttribute( "checked", mCheckedStates[ it.key()].first );
3219  editTypeElement.setAttribute( "unchecked", mCheckedStates[ it.key()].second );
3220  }
3221  break;
3222 
3223  case LineEdit:
3224  case UniqueValues:
3225  case UniqueValuesEditable:
3226  case Classification:
3227  case FileName:
3228  case Hidden:
3229  case TextEdit:
3230  case Calendar:
3231  case Enumeration:
3232  case Immutable:
3233  break;
3234  }
3235 
3236  editTypesElement.appendChild( editTypeElement );
3237  }
3238 
3239  node.appendChild( editTypesElement );
3240  }
3241 
3242  QDomElement efField = doc.createElement( "editform" );
3243  QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( mEditForm ) );
3244  efField.appendChild( efText );
3245  node.appendChild( efField );
3246 
3247  QDomElement efiField = doc.createElement( "editforminit" );
3248  QDomText efiText = doc.createTextNode( mEditFormInit );
3249  efiField.appendChild( efiText );
3250  node.appendChild( efiField );
3251 
3252  QDomElement afField = doc.createElement( "annotationform" );
3253  QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
3254  afField.appendChild( afText );
3255  node.appendChild( afField );
3256 
3257  //attribute aliases
3258  if ( mAttributeAliasMap.size() > 0 )
3259  {
3260  QDomElement aliasElem = doc.createElement( "aliases" );
3261  QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
3262  for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
3263  {
3264  int idx = fieldNameIndex( a_it.key() );
3265  if ( idx < 0 )
3266  continue;
3267 
3268  QDomElement aliasEntryElem = doc.createElement( "alias" );
3269  aliasEntryElem.setAttribute( "field", a_it.key() );
3270  aliasEntryElem.setAttribute( "index", idx );
3271  aliasEntryElem.setAttribute( "name", a_it.value() );
3272  aliasElem.appendChild( aliasEntryElem );
3273  }
3274  node.appendChild( aliasElem );
3275  }
3276 
3277  // add attribute actions
3278  mActions->writeXML( node, doc );
3279 
3280  //save vector overlays (e.g. diagrams)
3281  QList<QgsVectorOverlay*>::const_iterator overlay_it = mOverlays.constBegin();
3282  for ( ; overlay_it != mOverlays.constEnd(); ++overlay_it )
3283  {
3284  if ( *overlay_it )
3285  {
3286  ( *overlay_it )->writeXML( mapLayerNode, doc );
3287  }
3288  }
3289 
3290  return true;
3291 }
3292 
3293 
3295 {
3296  if ( !mEditable || !mDataProvider || !hasGeometryType() )
3297  {
3298  return false;
3299  }
3300 
3301  editGeometryChange( fid, *geom );
3302  mCachedGeometries[fid] = *geom;
3303  setModified( true, true );
3304  return true;
3305 }
3306 
3307 
3308 bool QgsVectorLayer::changeAttributeValue( int fid, int field, QVariant value, bool emitSignal )
3309 {
3310  if ( !isEditable() )
3311  return false;
3312 
3313  editAttributeChange( fid, field, value );
3314  setModified( true, false );
3315 
3316  if ( emitSignal )
3317  emit attributeValueChanged( fid, field, value );
3318 
3319  return true;
3320 }
3321 
3323 {
3324  if ( !isEditable() )
3325  return false;
3326 
3327  if ( field.name().isEmpty() )
3328  return false;
3329 
3330  for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
3331  {
3332  if ( it.value().name() == field.name() )
3333  return false;
3334  }
3335 
3336  if ( !mDataProvider->supportedType( field ) )
3337  return false;
3338 
3339  mMaxUpdatedIndex++;
3340 
3341  if ( mActiveCommand != NULL )
3342  {
3344  }
3345 
3346  mUpdatedFields.insert( mMaxUpdatedIndex, field );
3348 
3349  setModified( true, false );
3350 
3352 
3353  return true;
3354 }
3355 
3356 bool QgsVectorLayer::addAttribute( QString name, QString type )
3357 {
3358  const QList< QgsVectorDataProvider::NativeType > &types = mDataProvider->nativeTypes();
3359 
3360  int i;
3361  for ( i = 0; i < types.size() && types[i].mTypeName != type; i++ )
3362  ;
3363 
3364  return i < types.size() && addAttribute( QgsField( name, types[i].mType, type ) );
3365 }
3366 
3367 void QgsVectorLayer::addAttributeAlias( int attIndex, QString aliasString )
3368 {
3369  if ( !pendingFields().contains( attIndex ) )
3370  return;
3371 
3372  QString name = pendingFields()[ attIndex ].name();
3373 
3374  mAttributeAliasMap.insert( name, aliasString );
3375  emit layerModified( false );
3376 }
3377 
3378 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
3379 {
3380  if ( !pendingFields().contains( attributeIndex ) )
3381  return "";
3382 
3383  QString name = pendingFields()[ attributeIndex ].name();
3384 
3385  return mAttributeAliasMap.value( name, "" );
3386 }
3387 
3388 QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
3389 {
3390  QString displayName = attributeAlias( attributeIndex );
3391  if ( displayName.isEmpty() )
3392  {
3393  const QgsFieldMap& fields = pendingFields();
3394  QgsFieldMap::const_iterator fieldIt = fields.find( attributeIndex );
3395  if ( fieldIt != fields.constEnd() )
3396  {
3397  displayName = fieldIt->name();
3398  }
3399  }
3400  return displayName;
3401 }
3402 
3404 {
3405  if ( !isEditable() )
3406  return false;
3407 
3408  if ( mDeletedAttributeIds.contains( index ) )
3409  return false;
3410 
3411  if ( !mAddedAttributeIds.contains( index ) &&
3412  !mDataProvider->fields().contains( index ) )
3413  return false;
3414 
3415  if ( mActiveCommand != NULL )
3416  {
3418  }
3419 
3420  mDeletedAttributeIds.insert( index );
3421  mAddedAttributeIds.remove( index );
3422  mUpdatedFields.remove( index );
3423 
3424  setModified( true, false );
3425 
3426  emit attributeDeleted( index );
3427 
3428  return true;
3429 }
3430 
3432 {
3433  if ( !isEditable() )
3434  return false;
3435 
3436  if ( mDeletedFeatureIds.contains( fid ) )
3437  return true;
3438 
3439  mSelectedFeatureIds.remove( fid ); // remove it from selection
3440  editFeatureDelete( fid );
3441 
3442  setModified( true, false );
3443 
3444  emit featureDeleted( fid );
3445 
3446  return true;
3447 }
3448 
3450 {
3451  return mUpdatedFields;
3452 }
3453 
3455 {
3456  return mUpdatedFields.keys();
3457 }
3458 
3460 {
3461  return mDataProvider->featureCount()
3462  + mAddedFeatures.size()
3463  - mDeletedFeatureIds.size();
3464 }
3465 
3467 {
3468  bool success = true;
3469 
3470  //clear the cache image so markers don't appear anymore on next draw
3471  setCacheImage( 0 );
3472 
3473  mCommitErrors.clear();
3474 
3475  if ( !mDataProvider )
3476  {
3477  mCommitErrors << tr( "ERROR: no provider" );
3478  return false;
3479  }
3480 
3481  if ( !isEditable() )
3482  {
3483  mCommitErrors << tr( "ERROR: layer not editable" );
3484  return false;
3485  }
3486 
3487  int cap = mDataProvider->capabilities();
3488 
3489  //
3490  // delete attributes
3491  //
3492  bool attributesChanged = false;
3493  if ( mDeletedAttributeIds.size() > 0 )
3494  {
3496  {
3497  mCommitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
3498 
3500 
3501  mDeletedAttributeIds.clear();
3502  attributesChanged = true;
3503  }
3504  else
3505  {
3506  mCommitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
3507  success = false;
3508  }
3509  }
3510 
3511  //
3512  // add attributes
3513  //
3514  if ( mAddedAttributeIds.size() > 0 )
3515  {
3516  QList<QgsField> addedAttributes;
3517  for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.constBegin(); it != mAddedAttributeIds.constEnd(); it++ )
3518  {
3519  addedAttributes << mUpdatedFields[*it];
3520  }
3521 
3522 
3523  if (( cap & QgsVectorDataProvider::AddAttributes ) && mDataProvider->addAttributes( addedAttributes ) )
3524  {
3525  mCommitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributeIds.size() );
3526 
3527  emit committedAttributesAdded( id(), addedAttributes );
3528 
3529  mAddedAttributeIds.clear();
3530  attributesChanged = true;
3531  }
3532  else
3533  {
3534  mCommitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributeIds.size() );
3535  success = false;
3536  }
3537  }
3538 
3539  //
3540  // remap changed and attributes of added features
3541  //
3542  bool attributeChangesOk = true;
3543  if ( attributesChanged )
3544  {
3545  // map updates field indexes to names
3546  QMap<int, QString> src;
3547  for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
3548  {
3549  src[ it.key()] = it.value().name();
3550  }
3551 
3552  int maxAttrIdx = -1;
3553  const QgsFieldMap &pFields = mDataProvider->fields();
3554 
3555  // map provider table names to field indexes
3556  QMap<QString, int> dst;
3557  for ( QgsFieldMap::const_iterator it = pFields.begin(); it != pFields.end(); it++ )
3558  {
3559  dst[ it.value().name()] = it.key();
3560  if ( it.key() > maxAttrIdx )
3561  maxAttrIdx = it.key();
3562  }
3563 
3564  // if adding attributes failed add fields that are now missing
3565  // (otherwise we'll loose updates when doing the remapping)
3566  if ( mAddedAttributeIds.size() > 0 )
3567  {
3568  for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.constBegin(); it != mAddedAttributeIds.constEnd(); it++ )
3569  {
3570  QString name = mUpdatedFields[ *it ].name();
3571  if ( dst.contains( name ) )
3572  {
3573  // it's there => so we don't need to add it anymore
3574  mAddedAttributeIds.remove( *it );
3575  mCommitErrors << tr( "SUCCESS: attribute %1 was added." ).arg( name );
3576  }
3577  else
3578  {
3579  // field not there => put it behind the existing attributes
3580  dst[ name ] = ++maxAttrIdx;
3581  attributeChangesOk = false; // don't try attribute updates - they'll fail.
3582  mCommitErrors << tr( "ERROR: attribute %1 not added" ).arg( name );
3583  }
3584  }
3585  }
3586 
3587  // map updated fields to provider fields
3588  QMap<int, int> remap;
3589  for ( QMap<int, QString>::const_iterator it = src.begin(); it != src.end(); it++ )
3590  {
3591  if ( dst.contains( it.value() ) )
3592  {
3593  remap[ it.key()] = dst[ it.value()];
3594  }
3595  }
3596 
3597  // remap changed attributes
3598  for ( QgsChangedAttributesMap::iterator fit = mChangedAttributeValues.begin(); fit != mChangedAttributeValues.end(); fit++ )
3599  {
3600  QgsAttributeMap &src = fit.value();
3601  QgsAttributeMap dst;
3602 
3603  for ( QgsAttributeMap::const_iterator it = src.begin(); it != src.end(); it++ )
3604  {
3605  if ( remap.contains( it.key() ) )
3606  {
3607  dst[ remap[it.key()] ] = it.value();
3608  }
3609  }
3610  src = dst;
3611  }
3612 
3613  // remap features of added attributes
3614  for ( QgsFeatureList::iterator fit = mAddedFeatures.begin(); fit != mAddedFeatures.end(); fit++ )
3615  {
3616  const QgsAttributeMap &src = fit->attributeMap();
3617  QgsAttributeMap dst;
3618 
3619  for ( QgsAttributeMap::const_iterator it = src.begin(); it != src.end(); it++ )
3620  if ( remap.contains( it.key() ) )
3621  dst[ remap[it.key()] ] = it.value();
3622 
3623  fit->setAttributeMap( dst );
3624  }
3625 
3626  QgsFieldMap attributes;
3627 
3628  // update private field map
3629  for ( QMap<int, int>::iterator it = remap.begin(); it != remap.end(); it++ )
3630  attributes[ it.value()] = mUpdatedFields[ it.key()];
3631 
3632  mUpdatedFields = attributes;
3633  }
3634 
3635  if ( attributeChangesOk )
3636  {
3637  //
3638  // change attributes
3639  //
3640  if ( mChangedAttributeValues.size() > 0 )
3641  {
3643  {
3644  mCommitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
3645 
3647 
3648  mChangedAttributeValues.clear();
3649  }
3650  else
3651  {
3652  mCommitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
3653  success = false;
3654  }
3655  }
3656 
3657  //
3658  // add features
3659  //
3660  if ( mAddedFeatures.size() > 0 )
3661  {
3662  for ( int i = 0; i < mAddedFeatures.size(); i++ )
3663  {
3664  QgsFeature &f = mAddedFeatures[i];
3665 
3666  if ( mDeletedFeatureIds.contains( f.id() ) )
3667  {
3668  mDeletedFeatureIds.remove( f.id() );
3669 
3670  if ( mChangedGeometries.contains( f.id() ) )
3671  mChangedGeometries.remove( f.id() );
3672 
3673  mAddedFeatures.removeAt( i-- );
3674  continue;
3675  }
3676 
3677  if ( mChangedGeometries.contains( f.id() ) )
3678  {
3679  f.setGeometry( mChangedGeometries.take( f.id() ) );
3680  }
3681  }
3682 
3684  {
3685  mCommitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", mAddedFeatures.size() );
3686 
3687  emit committedFeaturesAdded( id(), mAddedFeatures );
3688 
3689  mAddedFeatures.clear();
3690  }
3691  else
3692  {
3693  mCommitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
3694  success = false;
3695  }
3696  }
3697  }
3698 
3699  //
3700  // update geometries
3701  //
3702  if ( mChangedGeometries.size() > 0 )
3703  {
3705  {
3706  mCommitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
3707 
3709 
3710  mChangedGeometries.clear();
3711  }
3712  else
3713  {
3714  mCommitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
3715  success = false;
3716  }
3717  }
3718 
3719  //
3720  // delete features
3721  //
3722  if ( mDeletedFeatureIds.size() > 0 )
3723  {
3725  {
3726  mCommitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
3727  for ( QgsFeatureIds::const_iterator it = mDeletedFeatureIds.begin(); it != mDeletedFeatureIds.end(); it++ )
3728  {
3729  mChangedAttributeValues.remove( *it );
3730  mChangedGeometries.remove( *it );
3731  }
3732 
3734 
3735  mDeletedFeatureIds.clear();
3736  }
3737  else
3738  {
3739  mCommitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
3740  success = false;
3741  }
3742  }
3743 
3745 
3746  if ( success )
3747  {
3748  mEditable = false;
3749  setModified( false );
3750  undoStack()->clear();
3751  emit editingStopped();
3752  }
3753 
3754  updateFieldMap();
3756  QgsDebugMsg( "result:\n " + mCommitErrors.join( "\n " ) );
3757 
3758  return success;
3759 }
3760 
3761 const QStringList &QgsVectorLayer::commitErrors()
3762 {
3763  return mCommitErrors;
3764 }
3765 
3767 {
3768  if ( !isEditable() )
3769  {
3770  return false;
3771  }
3772 
3773  if ( isModified() )
3774  {
3775  while ( undoStack()->canUndo() )
3776  {
3777  undoStack()->undo();
3778  }
3779 
3780  Q_ASSERT( mAddedAttributeIds.isEmpty() );
3781  Q_ASSERT( mDeletedAttributeIds.isEmpty() );
3782  Q_ASSERT( mChangedAttributeValues.isEmpty() );
3783  Q_ASSERT( mChangedGeometries.isEmpty() );
3784  Q_ASSERT( mAddedFeatures.isEmpty() );
3785 
3786  updateFieldMap();
3787  }
3788 
3790 
3791  mEditable = false;
3792  emit editingStopped();
3793 
3794  setModified( false );
3795  // invalidate the cache so the layer updates properly to show its original
3796  // after the rollback
3797  setCacheImage( 0 );
3798  return true;
3799 }
3800 
3802 {
3803  // TODO: check whether features with these ID exist
3804  mSelectedFeatureIds = ids;
3805 
3806  // invalidate cache
3807  setCacheImage( 0 );
3808 
3809  emit selectionChanged();
3810 }
3811 
3813 {
3814  return mSelectedFeatureIds.size();
3815 }
3816 
3818 {
3819  return mSelectedFeatureIds;
3820 }
3821 
3822 
3824 {
3825  if ( !mDataProvider )
3826  {
3827  return QgsFeatureList();
3828  }
3829 
3830  QgsFeatureList features;
3831 
3834 
3835  for ( QgsFeatureIds::iterator it = mSelectedFeatureIds.begin(); it != mSelectedFeatureIds.end(); ++it )
3836  {
3837  QgsFeature feat;
3838 
3839  bool selectionIsAddedFeature = false;
3840 
3841  // Check this selected item against the uncommitted added features
3842  for ( QgsFeatureList::iterator iter = mAddedFeatures.begin(); iter != mAddedFeatures.end(); ++iter )
3843  {
3844  if ( *it == iter->id() )
3845  {
3846  feat = QgsFeature( *iter );
3847  selectionIsAddedFeature = true;
3848  break;
3849  }
3850  }
3851 
3852  // if the geometry is not newly added, get it from provider
3853  if ( !selectionIsAddedFeature )
3854  {
3855  mDataProvider->featureAtId( *it, feat, true, allAttrs );
3856  }
3857 
3858  updateFeatureAttributes( feat );
3859  updateFeatureGeometry( feat );
3860 
3861  features << feat;
3862  } // for each selected
3863 
3864  return features;
3865 }
3866 
3867 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
3868 {
3869  if ( !mDataProvider )
3870  {
3871  return false;
3872  }
3873 
3875  {
3876  return false;
3877  }
3878 
3879  if ( !isEditable() )
3880  {
3881  return false;
3882  }
3883 
3884  if ( makeSelected )
3885  {
3886  mSelectedFeatureIds.clear();
3887  }
3888 
3889  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
3890  {
3891  addFeature( *iter );
3892 
3893  if ( makeSelected )
3894  {
3895  mSelectedFeatureIds.insert( iter->id() );
3896  }
3897  }
3898 
3899  updateExtents();
3900 
3901  if ( makeSelected )
3902  {
3903  // invalidate cache
3904  setCacheImage( 0 );
3905 
3906  emit selectionChanged();
3907  }
3908 
3909  return true;
3910 }
3911 
3912 
3914 {
3915  if ( !hasGeometryType() )
3916  return false;
3917 
3918  const QgsVectorLayer* vl = qobject_cast<const QgsVectorLayer *>( &other );
3919 
3920  // exit if both vectorlayer are the same
3921  if ( this == vl )
3922  {
3923  return false;
3924  }
3925 
3926  if ( !vl )
3927  {
3928  return false;
3929  }
3930  delete mRenderer;
3931 
3932  QgsRenderer* r = vl->mRenderer;
3933  if ( r )
3934  {
3935  mRenderer = r->clone();
3936  return true;
3937  }
3938  else
3939  {
3940  return false;
3941  }
3942 }
3943 
3945 {
3946  // vector layers are symbology compatible if they have the same type, the same sequence of numerical/ non numerical fields and the same field names
3947 
3948  const QgsVectorLayer* otherVectorLayer = qobject_cast<const QgsVectorLayer *>( &other );
3949  if ( otherVectorLayer )
3950  {
3951  if ( otherVectorLayer->type() != type() )
3952  {
3953  return false;
3954  }
3955 
3956  const QgsFieldMap& fieldsThis = mDataProvider->fields();
3957  const QgsFieldMap& fieldsOther = otherVectorLayer ->mDataProvider->fields();
3958 
3959  if ( fieldsThis.size() != fieldsOther.size() )
3960  {
3961  return false;
3962  }
3963 
3964  // TODO: fill two sets with the numerical types for both layers
3965 
3966  uint fieldsThisSize = fieldsThis.size();
3967 
3968  for ( uint i = 0; i < fieldsThisSize; ++i )
3969  {
3970  if ( fieldsThis[i].name() != fieldsOther[i].name() ) // field names need to be the same
3971  {
3972  return false;
3973  }
3974  // TODO: compare types of the fields
3975  }
3976  return true; // layers are symbology compatible if the code reaches this point
3977  }
3978  return false;
3979 }
3980 
3981 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
3982 {
3983  if ( !hasGeometryType() )
3984  return false;
3985 
3986  QMultiMap<double, QgsSnappingResult> snapResults;
3987  int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
3988 
3989  if ( result != 0 )
3990  {
3991  return false;
3992  }
3993 
3994  if ( snapResults.size() < 1 )
3995  {
3996  return false;
3997  }
3998 
3999  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
4000  point.setX( snap_it.value().snappedVertex.x() );
4001  point.setY( snap_it.value().snappedVertex.y() );
4002  return true;
4003 }
4004 
4005 
4006 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
4007  QMultiMap<double, QgsSnappingResult>& snappingResults,
4008  QgsSnapper::SnappingType snap_to )
4009 {
4010  if ( !hasGeometryType() )
4011  return 1;
4012 
4013  if ( snappingTolerance <= 0 || !mDataProvider )
4014  {
4015  return 1;
4016  }
4017 
4018  QList<QgsFeature> featureList;
4019  QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
4020  startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
4021  double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
4022 
4023  int n = 0;
4024  QgsFeature f;
4025 
4026  if ( mCachedGeometriesRect.contains( searchRect ) )
4027  {
4028  QgsGeometryMap::iterator it = mCachedGeometries.begin();
4029  for ( ; it != mCachedGeometries.end() ; ++it )
4030  {
4031  QgsGeometry* g = &( it.value() );
4032  if ( g->boundingBox().intersects( searchRect ) )
4033  {
4034  snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
4035  ++n;
4036  }
4037  }
4038  }
4039  else
4040  {
4041  // snapping outside cached area
4042 
4043  select( QgsAttributeList(), searchRect, true, true );
4044 
4045  while ( nextFeature( f ) )
4046  {
4047  snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
4048  ++n;
4049  }
4050  }
4051 
4052  return n == 0 ? 2 : 0;
4053 }
4054 
4055 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint, int featureId, QgsGeometry* geom, double sqrSnappingTolerance,
4056  QMultiMap<double, QgsSnappingResult>& snappingResults, QgsSnapper::SnappingType snap_to ) const
4057 {
4058  if ( !geom )
4059  {
4060  return;
4061  }
4062 
4063  int atVertex, beforeVertex, afterVertex;
4064  double sqrDistVertexSnap, sqrDistSegmentSnap;
4065  QgsPoint snappedPoint;
4066  QgsSnappingResult snappingResultVertex;
4067  QgsSnappingResult snappingResultSegment;
4068 
4069  if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
4070  {
4071  snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
4072  if ( sqrDistVertexSnap < sqrSnappingTolerance )
4073  {
4074  snappingResultVertex.snappedVertex = snappedPoint;
4075  snappingResultVertex.snappedVertexNr = atVertex;
4076  snappingResultVertex.beforeVertexNr = beforeVertex;
4077  if ( beforeVertex != -1 ) // make sure the vertex is valid
4078  {
4079  snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
4080  }
4081  snappingResultVertex.afterVertexNr = afterVertex;
4082  if ( afterVertex != -1 ) // make sure the vertex is valid
4083  {
4084  snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
4085  }
4086  snappingResultVertex.snappedAtGeometry = featureId;
4087  snappingResultVertex.layer = this;
4088  snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
4089  return;
4090  }
4091  }
4092  if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
4093  {
4094  if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
4095  {
4096  sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex );
4097 
4098  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
4099  {
4100  snappingResultSegment.snappedVertex = snappedPoint;
4101  snappingResultSegment.snappedVertexNr = -1;
4102  snappingResultSegment.beforeVertexNr = afterVertex - 1;
4103  snappingResultSegment.afterVertexNr = afterVertex;
4104  snappingResultSegment.snappedAtGeometry = featureId;
4105  snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
4106  snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
4107  snappingResultSegment.layer = this;
4108  snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
4109  }
4110  }
4111  }
4112 
4113 }
4114 
4115 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
4116 {
4117  if ( !hasGeometryType() )
4118  return 1;
4119 
4120  int returnval = 0;
4121  QgsPoint layerPoint;
4122 
4123  QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
4124  for ( ; it != snapResults.constEnd(); ++it )
4125  {
4126  if ( it->snappedVertexNr == -1 ) // segment snap
4127  {
4128  layerPoint = it->snappedVertex;
4129  if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
4130  {
4131  returnval = 3;
4132  }
4133  }
4134  }
4135  return returnval;
4136 }
4137 
4138 int QgsVectorLayer::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
4139 {
4140  if ( list.size() < 1 )
4141  {
4142  return 1;
4143  }
4144 
4149 
4150  for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
4151  {
4152  if ( it->x() < xmin )
4153  {
4154  xmin = it->x();
4155  }
4156  if ( it->x() > xmax )
4157  {
4158  xmax = it->x();
4159  }
4160  if ( it->y() < ymin )
4161  {
4162  ymin = it->y();
4163  }
4164  if ( it->y() > ymax )
4165  {
4166  ymax = it->y();
4167  }
4168  }
4169 
4170  return 0;
4171 }
4172 
4174 {
4175  QSettings settings;
4176  QString markerTypeString = settings.value( "/qgis/digitizing/marker_style", "Cross" ).toString();
4177  if ( markerTypeString == "Cross" )
4178  {
4179  return QgsVectorLayer::Cross;
4180  }
4181  else if ( markerTypeString == "SemiTransparentCircle" )
4182  {
4184  }
4185  else
4186  {
4187  return QgsVectorLayer::NoMarker;
4188  }
4189 }
4190 
4192 {
4193  QSettings settings;
4194  return settings.value( "/qgis/digitizing/marker_size", 3 ).toInt();
4195 }
4196 
4198  QgsFeature& fet,
4199  QImage * marker )
4200 {
4201  QPainter *p = renderContext.painter();
4202  // Only have variables, etc outside the switch() statement that are
4203  // used in all cases of the statement (otherwise they may get
4204  // executed, but never used, in a bit of code where performance is
4205  // critical).
4206  if ( ! fet.isValid() )
4207  {
4208  return;
4209  }
4210 
4211  QgsGeometry* geom = fet.geometry();
4212  if ( !geom )
4213  {
4214  return;
4215  }
4216  unsigned char* feature = geom->asWkb();
4217 
4218  QGis::WkbType wkbType = geom->wkbType();
4219 
4220  switch ( wkbType )
4221  {
4222  case QGis::WKBPoint:
4223  case QGis::WKBPoint25D:
4224  {
4225  double x = *(( double * )( feature + 5 ) );
4226  double y = *(( double * )( feature + 5 + sizeof( double ) ) );
4227 
4228  transformPoint( x, y, &renderContext.mapToPixel(), renderContext.coordinateTransform() );
4229  if ( qAbs( x ) > QgsClipper::MAX_X ||
4230  qAbs( y ) > QgsClipper::MAX_Y )
4231  {
4232  break;
4233  }
4234 
4235  //QPointF pt(x - (marker->width()/2), y - (marker->height()/2));
4236  QPointF pt( x * renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
4237  y * renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
4238 
4239  p->save();
4240  //p->scale(markerScaleFactor,markerScaleFactor);
4241  p->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
4242  p->drawImage( pt, *marker );
4243  p->restore();
4244 
4245  break;
4246  }
4247  case QGis::WKBMultiPoint:
4249  {
4250  unsigned char *ptr = feature + 5;
4251  unsigned int nPoints = *(( int* )ptr );
4252  ptr += 4;
4253 
4254  p->save();
4255  //p->scale(markerScaleFactor, markerScaleFactor);
4256  p->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
4257 
4258  for ( register unsigned int i = 0; i < nPoints; ++i )
4259  {
4260  ptr += 5;
4261  double x = *(( double * ) ptr );
4262  ptr += sizeof( double );
4263  double y = *(( double * ) ptr );
4264  ptr += sizeof( double );
4265 
4266  if ( wkbType == QGis::WKBMultiPoint25D ) // ignore Z value
4267  ptr += sizeof( double );
4268 
4269  transformPoint( x, y, &renderContext.mapToPixel(), renderContext.coordinateTransform() );
4270  //QPointF pt(x - (marker->width()/2), y - (marker->height()/2));
4271  //QPointF pt(x/markerScaleFactor - (marker->width()/2), y/markerScaleFactor - (marker->height()/2));
4272  QPointF pt( x * renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
4273  y * renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
4274  //QPointF pt( x, y );
4275 
4276  // Work around a +/- 32768 limitation on coordinates
4277  if ( qAbs( x ) <= QgsClipper::MAX_X &&
4278  qAbs( y ) <= QgsClipper::MAX_Y )
4279  p->drawImage( pt, *marker );
4280  }
4281  p->restore();
4282 
4283  break;
4284  }
4285  case QGis::WKBLineString:
4287  {
4288  drawLineString( feature, renderContext );
4289  break;
4290  }
4293  {
4294  unsigned char* ptr = feature + 5;
4295  unsigned int numLineStrings = *(( int* )ptr );
4296  ptr = feature + 9;
4297 
4298  for ( register unsigned int jdx = 0; jdx < numLineStrings; jdx++ )
4299  {
4300  ptr = drawLineString( ptr, renderContext );
4301  }
4302  break;
4303  }
4304  case QGis::WKBPolygon:
4305  case QGis::WKBPolygon25D:
4306  {
4307  drawPolygon( feature, renderContext );
4308  break;
4309  }
4310  case QGis::WKBMultiPolygon:
4312  {
4313  unsigned char *ptr = feature + 5;
4314  unsigned int numPolygons = *(( int* )ptr );
4315  ptr = feature + 9;
4316  for ( register unsigned int kdx = 0; kdx < numPolygons; kdx++ )
4317  ptr = drawPolygon( ptr, renderContext );
4318  break;
4319  }
4320  default:
4321  QgsDebugMsg( "Unknown WkbType ENCOUNTERED" );
4322  break;
4323  }
4324 }
4325 
4326 
4327 
4329 {
4330  QgsDebugMsg( "----- Computing Coordinate System" );
4331 
4332  //
4333  // Get the layers project info and set up the QgsCoordinateTransform
4334  // for this layer
4335  //
4336 
4337  // get CRS directly from provider
4338  *mCRS = mDataProvider->crs();
4339 
4340  //QgsCoordinateReferenceSystem provides a mechanism for FORCE a srs to be valid
4341  //which is inolves falling back to system, project or user selected
4342  //defaults if the srs is not properly intialised.
4343  //we only nee to do that if the srs is not alreay valid
4344  if ( !mCRS->isValid() )
4345  {
4346  if ( hasGeometryType() )
4347  {
4348  mCRS->setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
4349  mCRS->validate();
4350  }
4351  else
4352  {
4354  }
4355  }
4356 }
4357 
4358 // Convenience function to transform the given point
4360  double& x, double& y,
4361  const QgsMapToPixel* mtp,
4362  const QgsCoordinateTransform* ct )
4363 {
4364  // transform the point
4365  if ( ct )
4366  {
4367  double z = 0;
4368  ct->transformInPlace( x, y, z );
4369  }
4370 
4371  // transform from projected coordinate system to pixel
4372  // position on map canvas
4373  mtp->transformInPlace( x, y );
4374 }
4375 
4377  std::vector<double>& x, std::vector<double>& y, std::vector<double>& z,
4378  QgsRenderContext &renderContext )
4379 {
4380  // transform the point
4381  if ( renderContext.coordinateTransform() )
4382  renderContext.coordinateTransform()->transformInPlace( x, y, z );
4383 
4384  // transform from projected coordinate system to pixel
4385  // position on map canvas
4386  renderContext.mapToPixel().transformInPlace( x, y );
4387 }
4388 
4389 
4390 const QString QgsVectorLayer::displayField() const
4391 {
4392  return mDisplayField;
4393 }
4394 
4396 {
4397  return ( mEditable && mDataProvider );
4398 }
4399 
4401 {
4402  return mReadOnly;
4403 }
4404 
4405 bool QgsVectorLayer::setReadOnly( bool readonly )
4406 {
4407  // exit if the layer is in editing mode
4408  if ( readonly && mEditable )
4409  return false;
4410 
4411  mReadOnly = readonly;
4412  return true;
4413 }
4414 
4416 {
4417  return mModified;
4418 }
4419 
4420 void QgsVectorLayer::setModified( bool modified, bool onlyGeometry )
4421 {
4422  mModified = modified;
4423  emit layerModified( onlyGeometry );
4424 }
4425 
4427 {
4428  const QgsFieldMap &fields = pendingFields();
4429  if ( fields.contains( idx ) && mEditTypes.contains( fields[idx].name() ) )
4430  return mEditTypes[ fields[idx].name()];
4431  else
4432  return LineEdit;
4433 }
4434 
4436 {
4437  const QgsFieldMap &fields = pendingFields();
4438  if ( fields.contains( idx ) )
4439  mEditTypes[ fields[idx].name()] = type;
4440 }
4441 
4443 {
4444  return mEditForm;
4445 }
4446 
4448 {
4449  mEditForm = ui;
4450 }
4451 
4452 void QgsVectorLayer::setAnnotationForm( const QString& ui )
4453 {
4454  mAnnotationForm = ui;
4455 }
4456 
4458 {
4459  return mEditFormInit;
4460 }
4461 
4462 void QgsVectorLayer::setEditFormInit( QString function )
4463 {
4464  mEditFormInit = function;
4465 }
4466 
4467 QMap< QString, QVariant > &QgsVectorLayer::valueMap( int idx )
4468 {
4469  const QgsFieldMap &fields = pendingFields();
4470 
4471  // FIXME: throw an exception!?
4472  if ( !fields.contains( idx ) )
4473  {
4474  QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
4475  }
4476 
4477  if ( !mValueMaps.contains( fields[idx].name() ) )
4478  mValueMaps[ fields[idx].name()] = QMap<QString, QVariant>();
4479 
4480  return mValueMaps[ fields[idx].name()];
4481 }
4482 
4484 {
4485  const QgsFieldMap &fields = pendingFields();
4486 
4487  // FIXME: throw an exception!?
4488  if ( fields.contains( idx ) )
4489  {
4490  QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
4491  }
4492 
4493  if ( !mRanges.contains( fields[idx].name() ) )
4494  mRanges[ fields[idx].name()] = RangeData();
4495 
4496  return mRanges[ fields[idx].name()];
4497 }
4498 
4500 {
4501  mOverlays.push_back( overlay );
4502 }
4503 
4504 void QgsVectorLayer::removeOverlay( const QString& typeName )
4505 {
4506  for ( int i = mOverlays.size() - 1; i >= 0; --i )
4507  {
4508  if ( mOverlays.at( i )->typeName() == typeName )
4509  {
4510  mOverlays.removeAt( i );
4511  }
4512  }
4513 }
4514 
4515 void QgsVectorLayer::vectorOverlays( QList<QgsVectorOverlay*>& overlayList )
4516 {
4517  overlayList = mOverlays;
4518 }
4519 
4521 {
4522  QList<QgsVectorOverlay*>::iterator it = mOverlays.begin();
4523  for ( ; it != mOverlays.end(); ++it )
4524  {
4525  if (( *it )->typeName() == typeName )
4526  {
4527  return *it;
4528  }
4529  }
4530  return 0; //not found
4531 }
4532 
4533 
4535 {
4536  return mRendererV2;
4537 }
4539 {
4540  if ( !hasGeometryType() )
4541  return;
4542 
4543  delete mRendererV2;
4544  mRendererV2 = r;
4545 }
4547 {
4548  return mUsingRendererV2;
4549 }
4550 void QgsVectorLayer::setUsingRendererV2( bool usingRendererV2 )
4551 {
4552  if ( !hasGeometryType() )
4553  return;
4554 
4555  mUsingRendererV2 = usingRendererV2;
4556 }
4557 
4558 
4559 void QgsVectorLayer::editGeometryChange( int featureId, QgsGeometry& geometry )
4560 {
4561  if ( mActiveCommand != NULL )
4562  {
4563  mActiveCommand->storeGeometryChange( featureId, mChangedGeometries[ featureId ], geometry );
4564  }
4565  mChangedGeometries[ featureId ] = geometry;
4566 }
4567 
4568 
4570 {
4571  if ( mActiveCommand != NULL )
4572  {
4573  mActiveCommand->storeFeatureAdd( feature );
4574  }
4575  mAddedFeatures.append( feature );
4576 }
4577 
4579 {
4580  if ( mActiveCommand != NULL )
4581  {
4582  mActiveCommand->storeFeatureDelete( featureId );
4583  }
4584  mDeletedFeatureIds.insert( featureId );
4585 }
4586 
4587 void QgsVectorLayer::editAttributeChange( int featureId, int field, QVariant value )
4588 {
4589  if ( mActiveCommand != NULL )
4590  {
4591  QVariant original;
4592  bool isFirstChange = true;
4593  if ( featureId < 0 )
4594  {
4595  // work with added feature
4596  for ( int i = 0; i < mAddedFeatures.size(); i++ )
4597  {
4598  if ( mAddedFeatures[i].id() == featureId && mAddedFeatures[i].attributeMap().contains( field ) )
4599  {
4600  original = mAddedFeatures[i].attributeMap()[field];
4601  isFirstChange = false;
4602  break;
4603  }
4604  }
4605  }
4606  else
4607  {
4608  if ( mChangedAttributeValues.contains( featureId ) && mChangedAttributeValues[featureId].contains( field ) )
4609  {
4610  original = mChangedAttributeValues[featureId][field];
4611  isFirstChange = false;
4612  }
4613  }
4614  mActiveCommand->storeAttributeChange( featureId, field, original, value, isFirstChange );
4615  }
4616 
4617  if ( featureId >= 0 )
4618  {
4619  // changed attribute of existing feature
4620  if ( !mChangedAttributeValues.contains( featureId ) )
4621  {
4622  mChangedAttributeValues.insert( featureId, QgsAttributeMap() );
4623  }
4624 
4625  mChangedAttributeValues[featureId].insert( field, value );
4626  }
4627  else
4628  {
4629  // updated added feature
4630  for ( int i = 0; i < mAddedFeatures.size(); i++ )
4631  {
4632  if ( mAddedFeatures[i].id() == featureId )
4633  {
4634  mAddedFeatures[i].changeAttribute( field, value );
4635  break;
4636  }
4637  }
4638  }
4639 }
4640 
4642 {
4643  if ( mActiveCommand == NULL )
4644  {
4645  mActiveCommand = new QgsUndoCommand( this, text );
4646  }
4647 }
4648 
4650 {
4651  if ( mActiveCommand != NULL )
4652  {
4653  undoStack()->push( mActiveCommand );
4654  mActiveCommand = NULL;
4655  }
4656 
4657 }
4658 
4660 {
4661  if ( mActiveCommand != NULL )
4662  {
4664  delete mActiveCommand;
4665  mActiveCommand = NULL;
4666  }
4667 
4668 }
4669 
4671 {
4672  QMap<int, QgsUndoCommand::GeometryChangeEntry>& geometryChange = cmd->mGeometryChange;
4673  QgsFeatureIds& deletedFeatureIdChange = cmd->mDeletedFeatureIdChange;
4674  QgsFeatureList& addedFeatures = cmd->mAddedFeatures;
4675  QMap<int, QgsUndoCommand::AttributeChanges>& attributeChange = cmd->mAttributeChange;
4676  QgsFieldMap& addedAttributes = cmd->mAddedAttributes;
4677  QgsFieldMap& deletedAttributes = cmd->mDeletedAttributes;
4678 
4679 
4680  // geometry changes
4681  QMap<int, QgsUndoCommand::GeometryChangeEntry>::iterator it = geometryChange.begin();
4682  for ( ; it != geometryChange.end(); ++it )
4683  {
4684  if ( it.value().target == NULL )
4685  {
4686  mChangedGeometries.remove( it.key() );
4687  }
4688  else
4689  {
4690  mChangedGeometries[it.key()] = *( it.value().target );
4691  }
4692  }
4693 
4694  // deleted features
4695  QgsFeatureIds::iterator delIt = deletedFeatureIdChange.begin();
4696  for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
4697  {
4698  mDeletedFeatureIds.insert( *delIt );
4699  emit featureDeleted( *delIt );
4700  }
4701 
4702  // added features
4703  QgsFeatureList::iterator addIt = addedFeatures.begin();
4704  for ( ; addIt != addedFeatures.end(); ++addIt )
4705  {
4706  mAddedFeatures.append( *addIt );
4707  emit featureAdded( addIt->id() );
4708  }
4709 
4710  // changed attributes
4711  QMap<int, QgsUndoCommand::AttributeChanges>::iterator attrFeatIt = attributeChange.begin();
4712  for ( ; attrFeatIt != attributeChange.end(); ++attrFeatIt )
4713  {
4714  int fid = attrFeatIt.key();
4715  // for every changed attribute in feature
4716  QMap<int, QgsUndoCommand::AttributeChangeEntry>::iterator attrChIt = attrFeatIt.value().begin();
4717  for ( ; attrChIt != attrFeatIt.value().end(); ++attrChIt )
4718  {
4719  if ( fid >= 0 )
4720  {
4721  // existing feature
4722  if ( attrChIt.value().target.isNull() )
4723  {
4724  mChangedAttributeValues[fid].remove( attrChIt.key() );
4725  if ( mChangedAttributeValues[fid].isEmpty() )
4726  mChangedAttributeValues.remove( fid );
4727  }
4728  else
4729  {
4730  mChangedAttributeValues[fid][attrChIt.key()] = attrChIt.value().target;
4731  }
4732  }
4733  else
4734  {
4735  // added feature
4736  for ( int i = 0; i < mAddedFeatures.size(); i++ )
4737  {
4738  if ( mAddedFeatures[i].id() == fid )
4739  {
4740  mAddedFeatures[i].changeAttribute( attrChIt.key(), attrChIt.value().target );
4741  break;
4742  }
4743  }
4744  }
4745  emit attributeValueChanged( fid, attrChIt.key(), attrChIt.value().target );
4746  }
4747  }
4748 
4749  // added attributes
4750  QgsFieldMap::iterator attrIt = addedAttributes.begin();
4751  for ( ; attrIt != addedAttributes.end(); ++attrIt )
4752  {
4753  int attrIndex = attrIt.key();
4754  mAddedAttributeIds.insert( attrIndex );
4755  mUpdatedFields.insert( attrIndex, attrIt.value() );
4756  emit attributeAdded( attrIndex );
4757  }
4758 
4759  // deleted attributes
4760  QgsFieldMap::iterator dAttrIt = deletedAttributes.begin();
4761  for ( ; dAttrIt != deletedAttributes.end(); ++dAttrIt )
4762  {
4763  int attrIndex = dAttrIt.key();
4764  mDeletedAttributeIds.insert( attrIndex );
4765  mUpdatedFields.remove( attrIndex );
4766  emit attributeDeleted( attrIndex );
4767  }
4768  setModified( true );
4769 
4770  // it's not ideal to trigger refresh from here
4771  triggerRepaint();
4772 }
4773 
4775 {
4776  QMap<int, QgsUndoCommand::GeometryChangeEntry>& geometryChange = cmd->mGeometryChange;
4777  QgsFeatureIds& deletedFeatureIdChange = cmd->mDeletedFeatureIdChange;
4778  QgsFeatureList& addedFeatures = cmd->mAddedFeatures;
4779  QMap<int, QgsUndoCommand::AttributeChanges>& attributeChange = cmd->mAttributeChange;
4780  QgsFieldMap& addedAttributes = cmd->mAddedAttributes;
4781  QgsFieldMap& deletedAttributes = cmd->mDeletedAttributes;
4782 
4783  // deleted attributes
4784  QgsFieldMap::iterator dAttrIt = deletedAttributes.begin();
4785  for ( ; dAttrIt != deletedAttributes.end(); ++dAttrIt )
4786  {
4787  int attrIndex = dAttrIt.key();
4788  mDeletedAttributeIds.remove( attrIndex );
4789  mUpdatedFields.insert( attrIndex, dAttrIt.value() );
4790  emit attributeAdded( attrIndex );
4791  }
4792 
4793  // added attributes
4794  QgsFieldMap::iterator attrIt = addedAttributes.begin();
4795  for ( ; attrIt != addedAttributes.end(); ++attrIt )
4796  {
4797  int attrIndex = attrIt.key();
4798  mAddedAttributeIds.remove( attrIndex );
4799  mUpdatedFields.remove( attrIndex );
4800  emit attributeDeleted( attrIndex );
4801  }
4802 
4803  // geometry changes
4804  QMap<int, QgsUndoCommand::GeometryChangeEntry>::iterator it = geometryChange.begin();
4805  for ( ; it != geometryChange.end(); ++it )
4806  {
4807  if ( it.value().original == NULL )
4808  {
4809  mChangedGeometries.remove( it.key() );
4810  }
4811  else
4812  {
4813  mChangedGeometries[it.key()] = *( it.value().original );
4814  }
4815  }
4816 
4817  // deleted features
4818  QgsFeatureIds::iterator delIt = deletedFeatureIdChange.begin();
4819  for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
4820  {
4821  mDeletedFeatureIds.remove( *delIt );
4822  emit featureAdded( *delIt );
4823  }
4824 
4825  // added features
4826  QgsFeatureList::iterator addIt = addedFeatures.begin();
4827  for ( ; addIt != addedFeatures.end(); ++addIt )
4828  {
4829  QgsFeatureList::iterator addedIt = mAddedFeatures.begin();
4830  for ( ; addedIt != mAddedFeatures.end(); ++addedIt )
4831  {
4832  if ( addedIt->id() == addIt->id() )
4833  {
4834  mAddedFeatures.erase( addedIt );
4835  emit featureDeleted( addIt->id() );
4836  break; // feature was found so move to next one
4837  }
4838  }
4839  }
4840 
4841  // updated attributes
4842  QMap<int, QgsUndoCommand::AttributeChanges>::iterator attrFeatIt = attributeChange.begin();
4843  for ( ; attrFeatIt != attributeChange.end(); ++attrFeatIt )
4844  {
4845  int fid = attrFeatIt.key();
4846  QMap<int, QgsUndoCommand::AttributeChangeEntry>::iterator attrChIt = attrFeatIt.value().begin();
4847  for ( ; attrChIt != attrFeatIt.value().end(); ++attrChIt )
4848  {
4849  if ( fid >= 0 )
4850  {
4851  if ( attrChIt.value().isFirstChange )
4852  {
4853  mChangedAttributeValues[fid].remove( attrChIt.key() );
4854  if ( mChangedAttributeValues[fid].isEmpty() )
4855  mChangedAttributeValues.remove( fid );
4856  }
4857  else
4858  {
4859  mChangedAttributeValues[fid][attrChIt.key()] = attrChIt.value().original;
4860  }
4861  }
4862  else
4863  {
4864  // added feature TODO:
4865  for ( int i = 0; i < mAddedFeatures.size(); i++ )
4866  {
4867  if ( mAddedFeatures[i].id() == fid )
4868  {
4869  mAddedFeatures[i].changeAttribute( attrChIt.key(), attrChIt.value().original );
4870  break;
4871  }
4872  }
4873  }
4874  QVariant original = attrChIt.value().original;
4875  if ( attrChIt.value().isFirstChange )
4876  {
4877  QgsFeature tmp;
4878  mDataProvider->featureAtId( fid, tmp, false, QgsAttributeList() << attrChIt.key() );
4879  original = tmp.attributeMap()[ attrChIt.key()];
4880  }
4881  emit attributeValueChanged( fid, attrChIt.key(), original );
4882  }
4883  }
4884  setModified( true );
4885 
4886  // it's not ideal to trigger refresh from here
4887  triggerRepaint();
4888 }
4889 
4890 void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
4891 {
4892  const QgsFieldMap &fields = pendingFields();
4893  if ( fields.contains( idx ) )
4894  mCheckedStates[ fields[idx].name()] = QPair<QString, QString>( checked, unchecked );
4895 }
4896 
4897 QPair<QString, QString> QgsVectorLayer::checkedState( int idx )
4898 {
4899  const QgsFieldMap &fields = pendingFields();
4900  if ( fields.contains( idx ) && mCheckedStates.contains( fields[idx].name() ) )
4901  return mCheckedStates[ fields[idx].name()];
4902  else
4903  return QPair<QString, QString>( "1", "0" );
4904 }
4905 
4906 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
4907 {
4908  const QgsFieldMap &theFields = pendingFields();
4909 
4910  for ( QgsFieldMap::const_iterator it = theFields.constBegin(); it != theFields.constEnd(); ++it )
4911  {
4912  if ( QString::compare( it->name(), fieldName, Qt::CaseInsensitive ) == 0 )
4913  {
4914  return it.key();
4915  }
4916  }
4917  return -1;
4918 }
4919 
4921 {
4922  mJoinBuffer->addJoin( joinInfo );
4923  updateFieldMap();
4924 }
4925 
4926 void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
4927 {
4928  removeJoin( theLayerId );
4929 }
4930 
4931 void QgsVectorLayer::removeJoin( const QString& joinLayerId )
4932 {
4933  mJoinBuffer->removeJoin( joinLayerId );
4934  updateFieldMap();
4935 }
4936 
4937 const QList< QgsVectorJoinInfo >& QgsVectorLayer::vectorJoins() const
4938 {
4939  return mJoinBuffer->vectorJoins();
4940 }
4941 
4943 {
4944  //first backup mAddedAttributes
4945  QgsFieldMap bkAddedAttributes;
4946  QgsAttributeIds::const_iterator attIdIt = mAddedAttributeIds.constBegin();
4947  for ( ; attIdIt != mAddedAttributeIds.constEnd(); ++attIdIt )
4948  {
4949  bkAddedAttributes.insert( *attIdIt, mUpdatedFields.value( *attIdIt ) );
4950  }
4951 
4953  if ( mDataProvider )
4954  {
4956  }
4957 
4958  int currentMaxIndex = 0; //maximum index of current layer
4959  if ( !QgsVectorLayerJoinBuffer::maximumIndex( mUpdatedFields, currentMaxIndex ) )
4960  {
4961  return;
4962  }
4963 
4964  mMaxUpdatedIndex = currentMaxIndex;
4965 
4966  //joined fields
4967  if ( mJoinBuffer->containsJoins() )
4968  {
4970  }
4971 
4972  //insert added attributes after provider fields and joined fields
4973  mAddedAttributeIds.clear();
4974  QgsFieldMap::const_iterator fieldIt = bkAddedAttributes.constBegin();
4975  for ( ; fieldIt != bkAddedAttributes.constEnd(); ++fieldIt )
4976  {
4977  ++mMaxUpdatedIndex;
4978  mUpdatedFields.insert( mMaxUpdatedIndex, fieldIt.value() );
4980 
4981  //go through the changed attributes map and adapt indices of added attributes
4982  for ( int i = 0; i < mChangedAttributeValues.size(); ++i )
4983  {
4985  }
4986 
4987  //go through added features and adapt attribute maps
4988  QgsFeatureList::iterator featureIt = mAddedFeatures.begin();
4989  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
4990  {
4991  QgsAttributeMap attMap = featureIt->attributeMap();
4992  updateAttributeMapIndex( attMap, fieldIt.key(), mMaxUpdatedIndex );
4993  featureIt->setAttributeMap( attMap );
4994  }
4995  }
4996 
4997  //remove deleted attributes
4998  QgsAttributeIds::const_iterator deletedIt = mDeletedAttributeIds.constBegin();
4999  for ( ; deletedIt != mDeletedAttributeIds.constEnd(); ++deletedIt )
5000  {
5001  mUpdatedFields.remove( *deletedIt );
5002  }
5003 }
5004 
5006 {
5007  if ( mJoinBuffer->containsJoins() )
5008  {
5010  }
5011 }
5012 
5013 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
5014 {
5015  uniqueValues.clear();
5016  if ( !mDataProvider )
5017  {
5018  return;
5019  }
5020 
5021  int maxProviderIndex;
5023 
5024  if ( index <= maxProviderIndex && !mEditable ) //a provider field
5025  {
5026  return mDataProvider->uniqueValues( index, uniqueValues, limit );
5027  }
5028  else // a joined field?
5029  {
5030  if ( mJoinBuffer )
5031  {
5032  int indexOffset; //offset between layer index and joined provider index
5033  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
5034  if ( join )
5035  {
5037  if ( vl && vl->dataProvider() )
5038  {
5039  return vl->dataProvider()->uniqueValues( index - indexOffset, uniqueValues, limit );
5040  }
5041  }
5042  }
5043  }
5044 
5045 
5046  //the layer is editable, but in certain cases it can still be avoided going through all features
5047  if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
5048  {
5049  return mDataProvider->uniqueValues( index, uniqueValues, limit );
5050  }
5051 
5052  //we need to go through each feature
5053  QgsAttributeList attList;
5054  attList << index;
5055 
5056  select( attList, QgsRectangle(), false, false );
5057 
5058  QgsFeature f;
5059  QVariant currentValue;
5060  QHash<QString, QVariant> val;
5061  while ( nextFeature( f ) )
5062  {
5063  currentValue = f.attributeMap()[index];
5064  val.insert( currentValue.toString(), currentValue );
5065  if ( limit >= 0 && val.size() >= limit )
5066  {
5067  break;
5068  }
5069  }
5070 
5071  uniqueValues = val.values();
5072 }
5073 
5074 QVariant QgsVectorLayer::minimumValue( int index )
5075 {
5076  if ( !mDataProvider )
5077  {
5078  return QVariant();
5079  }
5080 
5081  int maxProviderIndex;
5083 
5084  if ( index <= maxProviderIndex && !mEditable ) //a provider field
5085  {
5086  return mDataProvider->minimumValue( index );
5087  }
5088  else // a joined field?
5089  {
5090  int indexOffset; //offset between layer index and joined provider index
5091  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
5092  if ( join )
5093  {
5095  if ( vl )
5096  {
5097  return vl->minimumValue( index );
5098  }
5099  }
5100  }
5101 
5102  //the layer is editable, but in certain cases it can still be avoided going through all features
5103  if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
5104  {
5105  return mDataProvider->minimumValue( index );
5106  }
5107 
5108  //we need to go through each feature
5109  QgsAttributeList attList;
5110  attList << index;
5111 
5112  select( attList, QgsRectangle(), false, false );
5113 
5114  QgsFeature f;
5116  double currentValue = 0;
5117  while ( nextFeature( f ) )
5118  {
5119  currentValue = f.attributeMap()[index].toDouble();
5120  if ( currentValue < minimumValue )
5121  {
5122  minimumValue = currentValue;
5123  }
5124  }
5125  return QVariant( minimumValue );
5126 }
5127 
5128 QVariant QgsVectorLayer::maximumValue( int index )
5129 {
5130  if ( !mDataProvider )
5131  {
5132  return QVariant();
5133  }
5134 
5135  int maxProviderIndex;
5137 
5138  if ( index <= maxProviderIndex && !mEditable ) //a provider field
5139  {
5140  return mDataProvider->maximumValue( index );
5141  }
5142  else // a joined field?
5143  {
5144  int indexOffset; //offset between layer index and joined provider index
5145  const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
5146  if ( join )
5147  {
5149  if ( vl )
5150  {
5151  return vl->maximumValue( index );
5152  }
5153  }
5154  }
5155 
5156  //the layer is editable, but in certain cases it can still be avoided going through all features
5157  if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
5158  {
5159  return mDataProvider->maximumValue( index );
5160  }
5161 
5162  //we need to go through each feature
5163  QgsAttributeList attList;
5164  attList << index;
5165 
5166  select( attList, QgsRectangle(), false, false );
5167 
5168  QgsFeature f;
5170  double currentValue = 0;
5171  while ( nextFeature( f ) )
5172  {
5173  currentValue = f.attributeMap()[index].toDouble();
5174  if ( currentValue > maximumValue )
5175  {
5176  maximumValue = currentValue;
5177  }
5178  }
5179  return QVariant( maximumValue );
5180 }
5181 
5183 {
5184  mRendererV2->stopRender( rendererContext );
5185  if ( selRenderer )
5186  {
5187  selRenderer->stopRender( rendererContext );
5188  delete selRenderer;
5189  }
5190 }
5191 
5192 void QgsVectorLayer::updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const
5193 {
5194  QgsAttributeMap::const_iterator it = map.find( oldIndex );
5195  if ( it == map.constEnd() )
5196  {
5197  return;
5198  }
5199 
5200  map.insert( newIndex, it.value() );
5201  map.remove( oldIndex );
5202 }
5203 
5204 void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling )
5205 {
5206  if ( !rendererContext.labelingEngine() )
5207  return;
5208 
5209  QSet<int> attrIndex;
5210  if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
5211  {
5212  QSet<int>::const_iterator attIt = attrIndex.constBegin();
5213  for ( ; attIt != attrIndex.constEnd(); ++attIt )
5214  {
5215  if ( !attributes.contains( *attIt ) )
5216  {
5217  attributes << *attIt;
5218  }
5219  }
5220  labeling = true;
5221  }
5222 
5223  //register diagram layers
5225  {
5227  rendererContext.labelingEngine()->addDiagramLayer( this, mDiagramLayerSettings );
5228  //add attributes needed by the diagram renderer
5229  QList<int> att = mDiagramRenderer->diagramAttributes();
5230  QList<int>::const_iterator attIt = att.constBegin();
5231  for ( ; attIt != att.constEnd(); ++attIt )
5232  {
5233  if ( !attributes.contains( *attIt ) )
5234  {
5235  attributes << *attIt;
5236  }
5237  }
5238  //and the ones needed for data defined diagram positions
5239  if ( mDiagramLayerSettings->xPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->xPosColumn ) )
5240  {
5241  attributes << mDiagramLayerSettings->xPosColumn;
5242  }
5243  if ( mDiagramLayerSettings->yPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->yPosColumn ) )
5244  {
5245  attributes << mDiagramLayerSettings->yPosColumn;
5246  }
5247  }
5248 }
5249 
5251 {
5252  if ( !mDiagramLayerSettings )
5254  *mDiagramLayerSettings = s;
5255 }