Quantum GIS API Documentation  1.7.4
src/core/qgsvectorlayer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                                qgsvectorlayer.cpp
00003                               --------------------
00004           begin                : Oct 29, 2003
00005           copyright            : (C) 2003 by Gary E.Sherman
00006           email                : sherman at mrcc.com
00007 
00008   This class implements a generic means to display vector layers. The features
00009   and attributes are read from the data store using a "data provider" plugin.
00010   QgsVectorLayer can be used with any data store for which an appropriate
00011   plugin is available.
00012 
00013 ***************************************************************************/
00014 
00015 /***************************************************************************
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  ***************************************************************************/
00023 /*  $Id$ */
00024 
00025 #include <cfloat>
00026 #include <cstring>
00027 #include <climits>
00028 #include <cmath>
00029 #include <iosfwd>
00030 #include <limits>
00031 #include <memory>
00032 #include <set>
00033 #include <sstream>
00034 #include <utility>
00035 
00036 #include <QImage>
00037 #include <QPainter>
00038 #include <QPainterPath>
00039 #include <QPolygonF>
00040 #include <QSettings>
00041 #include <QString>
00042 #include <QDomNode>
00043 
00044 #include "qgsvectorlayer.h"
00045 
00046 // renderers
00047 #include "qgscontinuouscolorrenderer.h"
00048 #include "qgsgraduatedsymbolrenderer.h"
00049 #include "qgsrenderer.h"
00050 #include "qgssinglesymbolrenderer.h"
00051 #include "qgsuniquevaluerenderer.h"
00052 
00053 #include "qgsattributeaction.h"
00054 
00055 #include "qgis.h" //for globals
00056 #include "qgsapplication.h"
00057 #include "qgscoordinatetransform.h"
00058 #include "qgsfeature.h"
00059 #include "qgsfield.h"
00060 #include "qgsgeometry.h"
00061 #include "qgslabel.h"
00062 #include "qgslogger.h"
00063 #include "qgsmaptopixel.h"
00064 #include "qgspoint.h"
00065 #include "qgsproviderregistry.h"
00066 #include "qgsrectangle.h"
00067 #include "qgsrendercontext.h"
00068 #include "qgscoordinatereferencesystem.h"
00069 #include "qgsvectordataprovider.h"
00070 #include "qgsvectorlayerjoinbuffer.h"
00071 #include "qgsvectorlayerundocommand.h"
00072 #include "qgsvectoroverlay.h"
00073 #include "qgsmaplayerregistry.h"
00074 #include "qgsclipper.h"
00075 #include "qgsproject.h"
00076 
00077 #include "qgsrendererv2.h"
00078 #include "qgssymbolv2.h"
00079 #include "qgssymbollayerv2.h"
00080 #include "qgssinglesymbolrendererv2.h"
00081 #include "qgsdiagramrendererv2.h"
00082 
00083 #ifdef TESTPROVIDERLIB
00084 #include <dlfcn.h>
00085 #endif
00086 
00087 
00088 static const char * const ident_ = "$Id$";
00089 
00090 // typedef for the QgsDataProvider class factory
00091 typedef QgsDataProvider * create_it( const QString* uri );
00092 
00093 
00094 
00095 QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
00096                                 QString baseName,
00097                                 QString providerKey,
00098                                 bool loadDefaultStyleFlag )
00099     : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
00100     , mUpdateThreshold( 0 )     // XXX better default value?
00101     , mDataProvider( NULL )
00102     , mProviderKey( providerKey )
00103     , mEditable( false )
00104     , mReadOnly( false )
00105     , mModified( false )
00106     , mMaxUpdatedIndex( -1 )
00107     , mActiveCommand( NULL )
00108     , mRenderer( 0 )
00109     , mRendererV2( NULL )
00110     , mUsingRendererV2( false )
00111     , mLabel( 0 )
00112     , mLabelOn( false )
00113     , mVertexMarkerOnlyForSelection( false )
00114     , mFetching( false )
00115     , mJoinBuffer( 0 )
00116     , mDiagramRenderer( 0 )
00117     , mDiagramLayerSettings( 0 )
00118 {
00119   mActions = new QgsAttributeAction( this );
00120 
00121   // if we're given a provider type, try to create and bind one to this layer
00122   if ( ! mProviderKey.isEmpty() )
00123   {
00124     setDataProvider( mProviderKey );
00125   }
00126   if ( mValid )
00127   {
00128     // Always set crs
00129     setCoordinateSystem();
00130 
00131     QSettings settings;
00132     //Changed to default to true as of QGIS 1.7
00133     if ( settings.value( "/qgis/use_symbology_ng", true ).toBool() && hasGeometryType() )
00134     {
00135       // using symbology-ng!
00136       setUsingRendererV2( true );
00137     }
00138 
00139     // check if there is a default style / propertysheet defined
00140     // for this layer and if so apply it
00141     bool defaultLoadedFlag = false;
00142     if ( loadDefaultStyleFlag )
00143     {
00144       loadDefaultStyle( defaultLoadedFlag );
00145     }
00146 
00147     // if the default style failed to load or was disabled use some very basic defaults
00148     if ( !defaultLoadedFlag && hasGeometryType() )
00149     {
00150       // add single symbol renderer
00151       if ( mUsingRendererV2 )
00152       {
00153         setRendererV2( QgsFeatureRendererV2::defaultRenderer( geometryType() ) );
00154       }
00155       else
00156       {
00157         QgsSingleSymbolRenderer *renderer = new QgsSingleSymbolRenderer( geometryType() );
00158         setRenderer( renderer );
00159       }
00160     }
00161 
00162     mJoinBuffer = new QgsVectorLayerJoinBuffer();
00163 
00164     connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
00165     updateFieldMap();
00166 
00167     // Get the update threshold from user settings. We
00168     // do this only on construction to avoid the penality of
00169     // fetching this each time the layer is drawn. If the user
00170     // changes the threshold from the preferences dialog, it will
00171     // have no effect on existing layers
00172     // TODO: load this setting somewhere else [MD]
00173     //QSettings settings;
00174     //mUpdateThreshold = settings.readNumEntry("Map/updateThreshold", 1000);
00175   }
00176 } // QgsVectorLayer ctor
00177 
00178 
00179 
00180 QgsVectorLayer::~QgsVectorLayer()
00181 {
00182   QgsDebugMsg( "entered." );
00183 
00184   emit layerDeleted();
00185 
00186   mValid = false;
00187 
00188   delete mRenderer;
00189   delete mDataProvider;
00190   delete mJoinBuffer;
00191   delete mLabel;
00192   delete mDiagramLayerSettings;
00193 
00194   // Destroy any cached geometries and clear the references to them
00195   deleteCachedGeometries();
00196 
00197   delete mActions;
00198 
00199   //delete remaining overlays
00200 
00201   QList<QgsVectorOverlay*>::iterator overlayIt = mOverlays.begin();
00202   for ( ; overlayIt != mOverlays.end(); ++overlayIt )
00203   {
00204     delete *overlayIt;
00205   }
00206 }
00207 
00208 QString QgsVectorLayer::storageType() const
00209 {
00210   if ( mDataProvider )
00211   {
00212     return mDataProvider->storageType();
00213   }
00214   return 0;
00215 }
00216 
00217 
00218 QString QgsVectorLayer::capabilitiesString() const
00219 {
00220   if ( mDataProvider )
00221   {
00222     return mDataProvider->capabilitiesString();
00223   }
00224   return 0;
00225 }
00226 
00227 QString QgsVectorLayer::dataComment() const
00228 {
00229   if ( mDataProvider )
00230   {
00231     return mDataProvider->dataComment();
00232   }
00233   return QString();
00234 }
00235 
00236 
00237 QString QgsVectorLayer::providerType() const
00238 {
00239   return mProviderKey;
00240 }
00241 
00245 void QgsVectorLayer::setDisplayField( QString fldName )
00246 {
00247   if ( !hasGeometryType() )
00248     return;
00249 
00250   // If fldName is provided, use it as the display field, otherwise
00251   // determine the field index for the feature column of the identify
00252   // dialog. We look for fields containing "name" first and second for
00253   // fields containing "id". If neither are found, the first field
00254   // is used as the node.
00255   QString idxName = "";
00256   QString idxId = "";
00257 
00258   if ( !fldName.isEmpty() )
00259   {
00260     mDisplayField = fldName;
00261   }
00262   else
00263   {
00264     const QgsFieldMap &fields = pendingFields();
00265     int fieldsSize = fields.size();
00266 
00267     for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it )
00268     {
00269       QString fldName = it.value().name();
00270       QgsDebugMsg( "Checking field " + fldName + " of " + QString::number( fieldsSize ) + " total" );
00271 
00272       // Check the fields and keep the first one that matches.
00273       // We assume that the user has organized the data with the
00274       // more "interesting" field names first. As such, name should
00275       // be selected before oldname, othername, etc.
00276       if ( fldName.indexOf( "name", false ) > -1 )
00277       {
00278         if ( idxName.isEmpty() )
00279         {
00280           idxName = fldName;
00281         }
00282       }
00283       if ( fldName.indexOf( "descrip", false ) > -1 )
00284       {
00285         if ( idxName.isEmpty() )
00286         {
00287           idxName = fldName;
00288         }
00289       }
00290       if ( fldName.indexOf( "id", false ) > -1 )
00291       {
00292         if ( idxId.isEmpty() )
00293         {
00294           idxId = fldName;
00295         }
00296       }
00297     }
00298 
00299     //if there were no fields in the dbf just return - otherwise qgis segfaults!
00300     if ( fieldsSize == 0 )
00301       return;
00302 
00303     if ( idxName.length() > 0 )
00304     {
00305       mDisplayField = idxName;
00306     }
00307     else
00308     {
00309       if ( idxId.length() > 0 )
00310       {
00311         mDisplayField = idxId;
00312       }
00313       else
00314       {
00315         mDisplayField = fields[0].name();
00316       }
00317     }
00318 
00319   }
00320 }
00321 
00322 // NOTE this is a temporary method added by Tim to prevent label clipping
00323 // which was occurring when labeller was called in the main draw loop
00324 // This method will probably be removed again in the near future!
00325 void QgsVectorLayer::drawLabels( QgsRenderContext& rendererContext )
00326 {
00327   if ( !hasGeometryType() )
00328     return;
00329 
00330   QgsDebugMsg( "Starting draw of labels" );
00331 
00332   if (( mRenderer || mRendererV2 ) && mLabelOn &&
00333       ( !mLabel->scaleBasedVisibility() ||
00334         ( mLabel->minScale() <= rendererContext.rendererScale() &&
00335           rendererContext.rendererScale() <= mLabel->maxScale() ) ) )
00336   {
00337     QgsAttributeList attributes;
00338     if ( mRenderer )
00339     {
00340       attributes = mRenderer->classificationAttributes();
00341     }
00342     else if ( mRendererV2 )
00343     {
00344       foreach( QString attrName, mRendererV2->usedAttributes() )
00345       {
00346         int attrNum = fieldNameIndex( attrName );
00347         attributes.append( attrNum );
00348       }
00349       // make sure the renderer is ready for classification ("symbolForFeature")
00350       mRendererV2->startRender( rendererContext, this );
00351     }
00352 
00353     // Add fields required for labels
00354     mLabel->addRequiredFields( attributes );
00355 
00356     QgsDebugMsg( "Selecting features based on view extent" );
00357 
00358     int featureCount = 0;
00359 
00360     try
00361     {
00362       // select the records in the extent. The provider sets a spatial filter
00363       // and sets up the selection set for retrieval
00364       select( attributes, rendererContext.extent() );
00365 
00366       QgsFeature fet;
00367       while ( nextFeature( fet ) )
00368       {
00369         if (( mRenderer && mRenderer->willRenderFeature( &fet ) )
00370             || ( mRendererV2 && mRendererV2->symbolForFeature( fet ) != NULL ) )
00371         {
00372           bool sel = mSelectedFeatureIds.contains( fet.id() );
00373           mLabel->renderLabel( rendererContext, fet, sel, 0 );
00374         }
00375         featureCount++;
00376       }
00377     }
00378     catch ( QgsCsException &e )
00379     {
00380       Q_UNUSED( e );
00381       QgsDebugMsg( "Error projecting label locations" );
00382     }
00383 
00384     if ( mRendererV2 )
00385     {
00386       mRendererV2->stopRender( rendererContext );
00387     }
00388 
00389     QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
00390 
00391     // XXX Something in our draw event is triggering an additional draw event when resizing [TE 01/26/06]
00392     // XXX Calling this will begin processing the next draw event causing image havoc and recursion crashes.
00393     //qApp->processEvents();
00394 
00395   }
00396 }
00397 
00398 
00399 unsigned char *QgsVectorLayer::drawLineString( unsigned char *feature, QgsRenderContext &renderContext )
00400 {
00401   QPainter *p = renderContext.painter();
00402   unsigned char *ptr = feature + 5;
00403   unsigned int wkbType = *(( int* )( feature + 1 ) );
00404   unsigned int nPoints = *(( int* )ptr );
00405   ptr = feature + 9;
00406 
00407   bool hasZValue = ( wkbType == QGis::WKBLineString25D );
00408 
00409   std::vector<double> x( nPoints );
00410   std::vector<double> y( nPoints );
00411   std::vector<double> z( nPoints, 0.0 );
00412 
00413   // Extract the points from the WKB format into the x and y vectors.
00414   for ( register unsigned int i = 0; i < nPoints; ++i )
00415   {
00416     x[i] = *(( double * ) ptr );
00417     ptr += sizeof( double );
00418     y[i] = *(( double * ) ptr );
00419     ptr += sizeof( double );
00420 
00421     if ( hasZValue ) // ignore Z value
00422       ptr += sizeof( double );
00423   }
00424 
00425   // Transform the points into map coordinates (and reproject if
00426   // necessary)
00427 
00428   transformPoints( x, y, z, renderContext );
00429 
00430   // Work around a +/- 32768 limitation on coordinates
00431   // Look through the x and y coordinates and see if there are any
00432   // that need trimming. If one is found, there's no need to look at
00433   // the rest of them so end the loop at that point.
00434   for ( register unsigned int i = 0; i < nPoints; ++i )
00435   {
00436     if ( qAbs( x[i] ) > QgsClipper::MAX_X ||
00437          qAbs( y[i] ) > QgsClipper::MAX_Y )
00438     {
00439       QgsClipper::trimFeature( x, y, true ); // true = polyline
00440       nPoints = x.size(); // trimming may change nPoints.
00441       break;
00442     }
00443   }
00444 
00445   // set up QPolygonF class with transformed points
00446   QPolygonF pa( nPoints );
00447   for ( register unsigned int i = 0; i < nPoints; ++i )
00448   {
00449     pa[i].setX( x[i] );
00450     pa[i].setY( y[i] );
00451   }
00452 
00453   // The default pen gives bevelled joins between segements of the
00454   // polyline, which is good enough for the moment.
00455   //preserve a copy of the pen before we start fiddling with it
00456   QPen pen = p->pen(); // to be kept original
00457 
00458   //
00459   // experimental alpha transparency
00460   // 255 = opaque
00461   //
00462   QPen myTransparentPen = p->pen(); // store current pen
00463   QColor myColor = myTransparentPen.color();
00464   //only set transparency from layer level if renderer does not provide
00465   //transparency on class level
00466   if ( !mRenderer->usesTransparency() )
00467   {
00468     myColor.setAlpha( mTransparencyLevel );
00469   }
00470   myTransparentPen.setColor( myColor );
00471   p->setPen( myTransparentPen );
00472   p->drawPolyline( pa );
00473 
00474   // draw vertex markers if in editing mode, but only to the main canvas
00475   if ( mEditable && renderContext.drawEditingInformation() )
00476   {
00477 
00478     std::vector<double>::const_iterator xIt;
00479     std::vector<double>::const_iterator yIt;
00480     for ( xIt = x.begin(), yIt = y.begin(); xIt != x.end(); ++xIt, ++yIt )
00481     {
00482       drawVertexMarker( *xIt, *yIt, *p, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
00483     }
00484   }
00485 
00486   //restore the pen
00487   p->setPen( pen );
00488 
00489   return ptr;
00490 }
00491 
00492 unsigned char *QgsVectorLayer::drawPolygon( unsigned char *feature, QgsRenderContext &renderContext )
00493 {
00494   QPainter *p = renderContext.painter();
00495   typedef std::pair<std::vector<double>, std::vector<double> > ringType;
00496   typedef ringType* ringTypePtr;
00497   typedef std::vector<ringTypePtr> ringsType;
00498 
00499   // get number of rings in the polygon
00500   unsigned int numRings = *(( int* )( feature + 1 + sizeof( int ) ) );
00501 
00502   if ( numRings == 0 )  // sanity check for zero rings in polygon
00503     return feature + 9;
00504 
00505   unsigned int wkbType = *(( int* )( feature + 1 ) );
00506 
00507   bool hasZValue = ( wkbType == QGis::WKBPolygon25D );
00508 
00509   int total_points = 0;
00510 
00511   // A vector containing a pointer to a pair of double vectors.The
00512   // first vector in the pair contains the x coordinates, and the
00513   // second the y coordinates.
00514   ringsType rings;
00515 
00516   // Set pointer to the first ring
00517   unsigned char* ptr = feature + 1 + 2 * sizeof( int );
00518 
00519   for ( register unsigned int idx = 0; idx < numRings; idx++ )
00520   {
00521     unsigned int nPoints = *(( int* )ptr );
00522 
00523     ringTypePtr ring = new ringType( std::vector<double>( nPoints ), std::vector<double>( nPoints ) );
00524     ptr += 4;
00525 
00526     // create a dummy vector for the z coordinate
00527     std::vector<double> zVector( nPoints, 0.0 );
00528     // Extract the points from the WKB and store in a pair of
00529     // vectors.
00530     for ( register unsigned int jdx = 0; jdx < nPoints; jdx++ )
00531     {
00532       ring->first[jdx] = *(( double * ) ptr );
00533       ptr += sizeof( double );
00534       ring->second[jdx] = *(( double * ) ptr );
00535       ptr += sizeof( double );
00536 
00537       if ( hasZValue )
00538         ptr += sizeof( double );
00539     }
00540     // If ring has fewer than two points, what is it then?
00541     // Anyway, this check prevents a crash
00542     if ( nPoints < 1 )
00543     {
00544       QgsDebugMsg( "Ring has only " + QString::number( nPoints ) + " points! Skipping this ring." );
00545       continue;
00546     }
00547 
00548     transformPoints( ring->first, ring->second, zVector, renderContext );
00549 
00550     // Work around a +/- 32768 limitation on coordinates
00551     // Look through the x and y coordinates and see if there are any
00552     // that need trimming. If one is found, there's no need to look at
00553     // the rest of them so end the loop at that point.
00554     for ( register unsigned int i = 0; i < nPoints; ++i )
00555     {
00556       if ( qAbs( ring->first[i] ) > QgsClipper::MAX_X ||
00557            qAbs( ring->second[i] ) > QgsClipper::MAX_Y )
00558       {
00559         QgsClipper::trimFeature( ring->first, ring->second, false );
00560         break;
00561       }
00562     }
00563 
00564     // Don't bother keeping the ring if it has been trimmed out of
00565     // existence.
00566     if ( ring->first.size() == 0 )
00567       delete ring;
00568     else
00569     {
00570       rings.push_back( ring );
00571       total_points += ring->first.size();
00572     }
00573   }
00574 
00575   // Now we draw the polygons
00576 
00577   // use painter paths for drawing polygons with holes
00578   // when adding polygon to the path they invert the area
00579   // this means that adding inner rings to the path creates
00580   // holes in outer ring
00581   QPainterPath path; // OddEven fill rule by default
00582 
00583   // Only try to draw polygons if there is something to draw
00584   if ( total_points > 0 )
00585   {
00586     //preserve a copy of the brush and pen before we start fiddling with it
00587     QBrush brush = p->brush(); //to be kept as original
00588     QPen pen = p->pen(); // to be kept original
00589     //
00590     // experimental alpha transparency
00591     // 255 = opaque
00592     //
00593     QBrush myTransparentBrush = p->brush();
00594     QColor myColor = brush.color();
00595 
00596     //only set transparency from layer level if renderer does not provide
00597     //transparency on class level
00598     if ( !mRenderer->usesTransparency() )
00599     {
00600       myColor.setAlpha( mTransparencyLevel );
00601     }
00602     myTransparentBrush.setColor( myColor );
00603     QPen myTransparentPen = p->pen(); // store current pen
00604     myColor = myTransparentPen.color();
00605 
00606     //only set transparency from layer level if renderer does not provide
00607     //transparency on class level
00608     if ( !mRenderer->usesTransparency() )
00609     {
00610       myColor.setAlpha( mTransparencyLevel );
00611     }
00612     myTransparentPen.setColor( myColor );
00613 
00614     p->setBrush( myTransparentBrush );
00615     p->setPen( myTransparentPen );
00616 
00617     if ( numRings == 1 )
00618     {
00619       ringTypePtr r = rings[0];
00620       unsigned ringSize = r->first.size();
00621 
00622       QPolygonF pa( ringSize );
00623       for ( register unsigned int j = 0; j != ringSize; ++j )
00624       {
00625         pa[j].setX( r->first[j] );
00626         pa[j].setY( r->second[j] );
00627       }
00628       p->drawPolygon( pa );
00629 
00630       // draw vertex markers if in editing mode, but only to the main canvas
00631       if ( mEditable && renderContext.drawEditingInformation() )
00632       {
00633         for ( register unsigned int j = 0; j != ringSize; ++j )
00634         {
00635           drawVertexMarker( r->first[j], r->second[j], *p, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
00636         }
00637       }
00638 
00639       delete rings[0];
00640     }
00641     else
00642     {
00643       // Store size here and use it in the loop to avoid penalty of
00644       // multiple calls to size()
00645       int numRings = rings.size();
00646       for ( register int i = 0; i < numRings; ++i )
00647       {
00648         // Store the pointer in a variable with a short name so as to make
00649         // the following code easier to type and read.
00650         ringTypePtr r = rings[i];
00651         // only do this once to avoid penalty of additional calls
00652         unsigned ringSize = r->first.size();
00653 
00654         // Transfer points to the array of QPointF
00655         QPolygonF pa( ringSize );
00656         for ( register unsigned int j = 0; j != ringSize; ++j )
00657         {
00658           pa[j].setX( r->first[j] );
00659           pa[j].setY( r->second[j] );
00660         }
00661 
00662         path.addPolygon( pa );
00663 
00664         // Tidy up the pointed to pairs of vectors as we finish with them
00665         delete rings[i];
00666       }
00667 
00668 #if 0
00669       // A bit of code to aid in working out what values of
00670       // QgsClipper::minX, etc cause the X11 zoom bug.
00671       int largestX  = -std::numeric_limits<int>::max();
00672       int smallestX = std::numeric_limits<int>::max();
00673       int largestY  = -std::numeric_limits<int>::max();
00674       int smallestY = std::numeric_limits<int>::max();
00675 
00676       for ( int i = 0; i < pa.size(); ++i )
00677       {
00678         largestX  = qMax( largestX,  pa.point( i ).x() );
00679         smallestX = qMin( smallestX, pa.point( i ).x() );
00680         largestY  = qMax( largestY,  pa.point( i ).y() );
00681         smallestY = qMin( smallestY, pa.point( i ).y() );
00682       }
00683       QgsDebugMsg( QString( "Largest  X coordinate was %1" ).arg( largestX ) );
00684       QgsDebugMsg( QString( "Smallest X coordinate was %1" ).arg( smallestX ) );
00685       QgsDebugMsg( QString( "Largest  Y coordinate was %1" ).arg( largestY ) );
00686       QgsDebugMsg( QString( "Smallest Y coordinate was %1" ).arg( smallestY ) );
00687 #endif
00688 
00689       //
00690       // draw the polygon
00691       //
00692       p->drawPath( path );
00693 
00694       // draw vertex markers if in editing mode, but only to the main canvas
00695       if ( mEditable && renderContext.drawEditingInformation() )
00696       {
00697         for ( int i = 0; i < path.elementCount(); ++i )
00698         {
00699           const QPainterPath::Element & e = path.elementAt( i );
00700           drawVertexMarker( e.x, e.y, *p, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
00701         }
00702       }
00703     }
00704 
00705     //
00706     //restore brush and pen to original
00707     //
00708     p->setBrush( brush );
00709     p->setPen( pen );
00710 
00711   } // totalPoints > 0
00712 
00713   return ptr;
00714 }
00715 
00716 void QgsVectorLayer::drawRendererV2( QgsRenderContext& rendererContext, bool labeling )
00717 {
00718   if ( !hasGeometryType() )
00719     return;
00720 
00721   QSettings settings;
00722   bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
00723 
00724   mRendererV2->startRender( rendererContext, this );
00725 
00726 #ifndef Q_WS_MAC
00727   int featureCount = 0;
00728 #endif //Q_WS_MAC
00729 
00730   QgsFeature fet;
00731   while ( nextFeature( fet ) )
00732   {
00733     try
00734     {
00735       if ( rendererContext.renderingStopped() )
00736       {
00737         break;
00738       }
00739 
00740 #ifndef Q_WS_MAC //MH: disable this on Mac for now to avoid problems with resizing
00741       if ( mUpdateThreshold > 0 && 0 == featureCount % mUpdateThreshold )
00742       {
00743         emit screenUpdateRequested();
00744         // emit drawingProgress( featureCount, totalFeatures );
00745         qApp->processEvents();
00746       }
00747       else if ( featureCount % 1000 == 0 )
00748       {
00749         // emit drawingProgress( featureCount, totalFeatures );
00750         qApp->processEvents();
00751       }
00752 #endif //Q_WS_MAC
00753 
00754       bool sel = mSelectedFeatureIds.contains( fet.id() );
00755       bool drawMarker = ( mEditable && ( !vertexMarkerOnlyForSelection || sel ) );
00756 
00757       // render feature
00758       mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker );
00759 
00760       if ( mEditable )
00761       {
00762         // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
00763         mCachedGeometries[fet.id()] = *fet.geometry();
00764       }
00765 
00766       // labeling - register feature
00767       if ( mRendererV2->symbolForFeature( fet ) != NULL && rendererContext.labelingEngine() )
00768       {
00769         if ( labeling )
00770         {
00771           rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
00772         }
00773         if ( mDiagramRenderer )
00774         {
00775           rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
00776         }
00777       }
00778     }
00779     catch ( const QgsCsException &cse )
00780     {
00781       QgsDebugMsg( QString( "Failed to transform a point while drawing a feature of type '%1'. Ignoring this feature. %2" )
00782                    .arg( fet.typeName() ).arg( cse.what() ) );
00783     }
00784 #ifndef Q_WS_MAC
00785     ++featureCount;
00786 #endif //Q_WS_MAC
00787   }
00788 
00789 #ifndef Q_WS_MAC
00790   QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
00791 #endif
00792 }
00793 
00794 void QgsVectorLayer::drawRendererV2Levels( QgsRenderContext& rendererContext, bool labeling )
00795 {
00796   if ( !hasGeometryType() )
00797     return;
00798 
00799   QHash< QgsSymbolV2*, QList<QgsFeature> > features; // key = symbol, value = array of features
00800 
00801   QSettings settings;
00802   bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
00803 
00804   // startRender must be called before symbolForFeature() calls to make sure renderer is ready
00805   mRendererV2->startRender( rendererContext, this );
00806 
00807   QgsSingleSymbolRendererV2* selRenderer = NULL;
00808   if ( !mSelectedFeatureIds.isEmpty() )
00809   {
00810     selRenderer = new QgsSingleSymbolRendererV2( QgsSymbolV2::defaultSymbol( geometryType() ) );
00811     selRenderer->symbol()->setColor( QgsRenderer::selectionColor() );
00812     selRenderer->setVertexMarkerAppearance( currentVertexMarkerType(), currentVertexMarkerSize() );
00813     selRenderer->startRender( rendererContext, this );
00814   }
00815 
00816   // 1. fetch features
00817   QgsFeature fet;
00818 #ifndef Q_WS_MAC
00819   int featureCount = 0;
00820 #endif //Q_WS_MAC
00821   while ( nextFeature( fet ) )
00822   {
00823     if ( rendererContext.renderingStopped() )
00824     {
00825       stopRendererV2( rendererContext, selRenderer );
00826       return;
00827     }
00828 #ifndef Q_WS_MAC
00829     if ( featureCount % 1000 == 0 )
00830     {
00831       qApp->processEvents();
00832     }
00833 #endif //Q_WS_MAC
00834     QgsSymbolV2* sym = mRendererV2->symbolForFeature( fet );
00835     if ( !sym )
00836     {
00837       continue;
00838     }
00839 
00840     if ( !features.contains( sym ) )
00841     {
00842       features.insert( sym, QList<QgsFeature>() );
00843     }
00844     features[sym].append( fet );
00845 
00846     if ( mEditable )
00847     {
00848       // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
00849       mCachedGeometries[fet.id()] = *fet.geometry();
00850     }
00851 
00852     if ( sym && rendererContext.labelingEngine() )
00853     {
00854       if ( labeling )
00855       {
00856         rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
00857       }
00858       if ( mDiagramRenderer )
00859       {
00860         rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
00861       }
00862     }
00863 
00864 #ifndef Q_WS_MAC
00865     ++featureCount;
00866 #endif //Q_WS_MAC
00867   }
00868 
00869   // find out the order
00870   QgsSymbolV2LevelOrder levels;
00871   QgsSymbolV2List symbols = mRendererV2->symbols();
00872   for ( int i = 0; i < symbols.count(); i++ )
00873   {
00874     QgsSymbolV2* sym = symbols[i];
00875     for ( int j = 0; j < sym->symbolLayerCount(); j++ )
00876     {
00877       int level = sym->symbolLayer( j )->renderingPass();
00878       if ( level < 0 || level >= 1000 ) // ignore invalid levels
00879         continue;
00880       QgsSymbolV2LevelItem item( sym, j );
00881       while ( level >= levels.count() ) // append new empty levels
00882         levels.append( QgsSymbolV2Level() );
00883       levels[level].append( item );
00884     }
00885   }
00886 
00887   // 2. draw features in correct order
00888   for ( int l = 0; l < levels.count(); l++ )
00889   {
00890     QgsSymbolV2Level& level = levels[l];
00891     for ( int i = 0; i < level.count(); i++ )
00892     {
00893       QgsSymbolV2LevelItem& item = level[i];
00894       if ( !features.contains( item.symbol() ) )
00895       {
00896         QgsDebugMsg( "level item's symbol not found!" );
00897         continue;
00898       }
00899       int layer = item.layer();
00900       QList<QgsFeature>& lst = features[item.symbol()];
00901       QList<QgsFeature>::iterator fit;
00902 #ifndef Q_WS_MAC
00903       featureCount = 0;
00904 #endif //Q_WS_MAC
00905       for ( fit = lst.begin(); fit != lst.end(); ++fit )
00906       {
00907         if ( rendererContext.renderingStopped() )
00908         {
00909           stopRendererV2( rendererContext, selRenderer );
00910           return;
00911         }
00912 #ifndef Q_WS_MAC
00913         if ( featureCount % 1000 == 0 )
00914         {
00915           qApp->processEvents();
00916         }
00917 #endif //Q_WS_MAC
00918         bool sel = mSelectedFeatureIds.contains( fit->id() );
00919         // maybe vertex markers should be drawn only during the last pass...
00920         bool drawMarker = ( mEditable && ( !vertexMarkerOnlyForSelection || sel ) );
00921 
00922         try
00923         {
00924           mRendererV2->renderFeature( *fit, rendererContext, layer, sel, drawMarker );
00925         }
00926         catch ( const QgsCsException &cse )
00927         {
00928           QgsDebugMsg( QString( "Failed to transform a point while drawing a feature of type '%1'. Ignoring this feature. %2" )
00929                        .arg( fet.typeName() ).arg( cse.what() ) );
00930         }
00931 #ifndef Q_WS_MAC
00932         ++featureCount;
00933 #endif //Q_WS_MAC
00934       }
00935     }
00936   }
00937 
00938   stopRendererV2( rendererContext, selRenderer );
00939 }
00940 
00941 void QgsVectorLayer::reload()
00942 {
00943   if ( mDataProvider )
00944   {
00945     mDataProvider->reloadData();
00946   }
00947 }
00948 
00949 bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
00950 {
00951   if ( !hasGeometryType() )
00952     return true;
00953 
00954   //set update threshold before each draw to make sure the current setting is picked up
00955   QSettings settings;
00956   mUpdateThreshold = settings.value( "Map/updateThreshold", 0 ).toInt();
00957 
00958   if ( mUsingRendererV2 )
00959   {
00960     if ( mRendererV2 == NULL )
00961       return false;
00962 
00963     QgsDebugMsg( "rendering v2:\n" + mRendererV2->dump() );
00964 
00965     if ( mEditable )
00966     {
00967       // Destroy all cached geometries and clear the references to them
00968       deleteCachedGeometries();
00969       mCachedGeometriesRect = rendererContext.extent();
00970 
00971       // set editing vertex markers style
00972       mRendererV2->setVertexMarkerAppearance( currentVertexMarkerType(), currentVertexMarkerSize() );
00973     }
00974 
00975     QgsAttributeList attributes;
00976     foreach( QString attrName, mRendererV2->usedAttributes() )
00977     {
00978       int attrNum = fieldNameIndex( attrName );
00979       attributes.append( attrNum );
00980       QgsDebugMsg( "attrs: " + attrName + " - " + QString::number( attrNum ) );
00981     }
00982 
00983     bool labeling = false;
00984     //register label and diagram layer to the labeling engine
00985     prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
00986 
00987     select( attributes, rendererContext.extent() );
00988 
00989     if ( mRendererV2->usingSymbolLevels() )
00990       drawRendererV2Levels( rendererContext, labeling );
00991     else
00992       drawRendererV2( rendererContext, labeling );
00993 
00994     return true;
00995   }
00996 
00997   //draw ( p, viewExtent, theMapToPixelTransform, ct, drawingToEditingCanvas, 1., 1.);
00998 
00999   if ( mRenderer )
01000   {
01001     // painter is active (begin has been called
01002     /* Steps to draw the layer
01003        1. get the features in the view extent by SQL query
01004        2. read WKB for a feature
01005        3. transform
01006        4. draw
01007     */
01008 
01009     QPen pen;
01010     /*Pointer to a marker image*/
01011     QImage marker;
01012     //vertex marker type for selection
01013     QgsVectorLayer::VertexMarkerType vertexMarker = QgsVectorLayer::NoMarker;
01014     int vertexMarkerSize = 7;
01015 
01016     if ( mEditable )
01017     {
01018       // Destroy all cached geometries and clear the references to them
01019       deleteCachedGeometries();
01020       mCachedGeometriesRect = rendererContext.extent();
01021       vertexMarker = currentVertexMarkerType();
01022       vertexMarkerSize = currentVertexMarkerSize();
01023       mVertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
01024     }
01025 
01026     // int totalFeatures = pendingFeatureCount();
01027     int featureCount = 0;
01028     QgsFeature fet;
01029     QgsAttributeList attributes = mRenderer->classificationAttributes();
01030 
01031     bool labeling = false;
01032     prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
01033 
01034     select( attributes, rendererContext.extent() );
01035 
01036     try
01037     {
01038       while ( nextFeature( fet ) )
01039       {
01040 
01041         if ( rendererContext.renderingStopped() )
01042         {
01043           break;
01044         }
01045 
01046 #ifndef Q_WS_MAC //MH: disable this on Mac for now to avoid problems with resizing
01047         if ( mUpdateThreshold > 0 && 0 == featureCount % mUpdateThreshold )
01048         {
01049           emit screenUpdateRequested();
01050           // emit drawingProgress( featureCount, totalFeatures );
01051           qApp->processEvents();
01052         }
01053         else if ( featureCount % 1000 == 0 )
01054         {
01055           // emit drawingProgress( featureCount, totalFeatures );
01056           qApp->processEvents();
01057         }
01058 // #else
01059 //         Q_UNUSED( totalFeatures );
01060 #endif //Q_WS_MAC
01061 
01062         // check if feature is selected
01063         // only show selections of the current layer
01064         // TODO: create a mechanism to let layer know whether it's current layer or not [MD]
01065         bool sel = mSelectedFeatureIds.contains( fet.id() );
01066 
01067         mCurrentVertexMarkerType = QgsVectorLayer::NoMarker;
01068         mCurrentVertexMarkerSize = 7;
01069 
01070         if ( mEditable )
01071         {
01072           // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
01073           mCachedGeometries[fet.id()] = *fet.geometry();
01074 
01075           if ( !mVertexMarkerOnlyForSelection || sel )
01076           {
01077             mCurrentVertexMarkerType = vertexMarker;
01078             mCurrentVertexMarkerSize = vertexMarkerSize;
01079           }
01080         }
01081 
01082         //QgsDebugMsg(QString("markerScale before renderFeature(): %1").arg(markerScaleFactor));
01083         // markerScalerFactore reflects the wanted scaling of the marker
01084 
01085         double opacity = 1.0;
01086         if ( !mRenderer->usesTransparency() )
01087         {
01088           opacity = ( mTransparencyLevel * 1.0 ) / 255.0;
01089         }
01090         mRenderer->renderFeature( rendererContext, fet, &marker, sel, opacity );
01091 
01092         // markerScalerFactore now reflects the actual scaling of the marker that the render performed.
01093         //QgsDebugMsg(QString("markerScale after renderFeature(): %1").arg(markerScaleFactor));
01094 
01095         //double scale = rendererContext.scaleFactor() /  markerScaleFactor;
01096         drawFeature( rendererContext, fet, &marker );
01097 
01098         if ( mRenderer->willRenderFeature( &fet ) && rendererContext.labelingEngine() )
01099         {
01100           if ( labeling )
01101           {
01102             rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
01103           }
01104           if ( mDiagramRenderer )
01105           {
01106             rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
01107           }
01108         }
01109         ++featureCount;
01110       }
01111     }
01112     catch ( QgsCsException &cse )
01113     {
01114       QgsDebugMsg( QString( "Failed to transform a point while drawing a feature of type '%1'. Rendering stopped. %2" )
01115                    .arg( fet.typeName() ).arg( cse.what() ) );
01116       return false;
01117     }
01118 
01119     QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
01120   }
01121   else
01122   {
01123     QgsDebugMsg( "QgsRenderer is null" );
01124   }
01125 
01126   if ( mEditable )
01127   {
01128     QgsDebugMsg( QString( "Cached %1 geometries." ).arg( mCachedGeometries.count() ) );
01129   }
01130 
01131   return true; // Assume success always
01132 }
01133 
01134 void QgsVectorLayer::deleteCachedGeometries()
01135 {
01136   // Destroy any cached geometries
01137   mCachedGeometries.clear();
01138   mCachedGeometriesRect = QgsRectangle();
01139 }
01140 
01141 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int m )
01142 {
01143   if ( type == QgsVectorLayer::SemiTransparentCircle )
01144   {
01145     p.setPen( QColor( 50, 100, 120, 200 ) );
01146     p.setBrush( QColor( 200, 200, 210, 120 ) );
01147     p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
01148   }
01149   else if ( type == QgsVectorLayer::Cross )
01150   {
01151     p.setPen( QColor( 255, 0, 0 ) );
01152     p.drawLine( x - m, y + m, x + m, y - m );
01153     p.drawLine( x - m, y - m, x + m, y + m );
01154   }
01155 }
01156 
01157 void QgsVectorLayer::select( int number, bool emitSignal )
01158 {
01159   mSelectedFeatureIds.insert( number );
01160 
01161   if ( emitSignal )
01162   {
01163     // invalidate cache
01164     setCacheImage( 0 );
01165 
01166     emit selectionChanged();
01167   }
01168 }
01169 
01170 void QgsVectorLayer::deselect( int number, bool emitSignal )
01171 {
01172   mSelectedFeatureIds.remove( number );
01173 
01174   if ( emitSignal )
01175   {
01176     // invalidate cache
01177     setCacheImage( 0 );
01178 
01179     emit selectionChanged();
01180   }
01181 }
01182 
01183 void QgsVectorLayer::select( QgsRectangle & rect, bool lock )
01184 {
01185   // normalize the rectangle
01186   rect.normalize();
01187 
01188   if ( !lock )
01189   {
01190     removeSelection( false ); // don't emit signal
01191   }
01192 
01193   //select all the elements
01194   select( QgsAttributeList(), rect, false, true );
01195 
01196   QgsFeature f;
01197   while ( nextFeature( f ) )
01198   {
01199     select( f.id(), false ); // don't emit signal (not to redraw it everytime)
01200   }
01201 
01202   // invalidate cache
01203   setCacheImage( 0 );
01204 
01205   emit selectionChanged(); // now emit signal to redraw layer
01206 }
01207 
01208 void QgsVectorLayer::invertSelection()
01209 {
01210   // copy the ids of selected features to tmp
01211   QgsFeatureIds tmp = mSelectedFeatureIds;
01212 
01213   removeSelection( false ); // don't emit signal
01214 
01215   select( QgsAttributeList(), QgsRectangle(), false );
01216 
01217   QgsFeature fet;
01218   while ( nextFeature( fet ) )
01219   {
01220     select( fet.id(), false ); // don't emit signal
01221   }
01222 
01223   for ( QgsFeatureIds::iterator iter = tmp.begin(); iter != tmp.end(); ++iter )
01224   {
01225     mSelectedFeatureIds.remove( *iter );
01226   }
01227 
01228   // invalidate cache
01229   setCacheImage( 0 );
01230 
01231   emit selectionChanged();
01232 }
01233 
01234 void QgsVectorLayer::invertSelectionInRectangle( QgsRectangle & rect )
01235 {
01236   // normalize the rectangle
01237   rect.normalize();
01238 
01239   select( QgsAttributeList(), rect, false, true );
01240 
01241   QgsFeature fet;
01242   while ( nextFeature( fet ) )
01243   {
01244     if ( mSelectedFeatureIds.contains( fet.id() ) )
01245     {
01246       deselect( fet.id(), false ); // don't emit signal
01247     }
01248     else
01249     {
01250       select( fet.id(), false ); // don't emit signal
01251     }
01252   }
01253 
01254   // invalidate cache
01255   setCacheImage( 0 );
01256 
01257   emit selectionChanged();
01258 }
01259 
01260 void QgsVectorLayer::removeSelection( bool emitSignal )
01261 {
01262   if ( mSelectedFeatureIds.size() == 0 )
01263     return;
01264 
01265   mSelectedFeatureIds.clear();
01266 
01267   if ( emitSignal )
01268   {
01269     // invalidate cache
01270     setCacheImage( 0 );
01271 
01272     emit selectionChanged();
01273   }
01274 }
01275 
01276 void QgsVectorLayer::triggerRepaint()
01277 {
01278   emit repaintRequested();
01279 }
01280 
01281 QgsVectorDataProvider* QgsVectorLayer::dataProvider()
01282 {
01283   return mDataProvider;
01284 }
01285 
01286 const QgsVectorDataProvider* QgsVectorLayer::dataProvider() const
01287 {
01288   return mDataProvider;
01289 }
01290 
01291 void QgsVectorLayer::setProviderEncoding( const QString& encoding )
01292 {
01293   if ( mDataProvider )
01294   {
01295     mDataProvider->setEncoding( encoding );
01296   }
01297 }
01298 
01299 
01300 const QgsRenderer* QgsVectorLayer::renderer() const
01301 {
01302   return mRenderer;
01303 }
01304 
01305 void QgsVectorLayer::setRenderer( QgsRenderer * r )
01306 {
01307   if ( !hasGeometryType() )
01308     return;
01309 
01310   if ( r != mRenderer )
01311   {
01312     delete mRenderer;
01313     mRenderer = r;
01314   }
01315 }
01316 
01317 void QgsVectorLayer::setDiagramRenderer( QgsDiagramRendererV2* r )
01318 {
01319   delete mDiagramRenderer;
01320   mDiagramRenderer = r;
01321 }
01322 
01323 QGis::GeometryType QgsVectorLayer::geometryType() const
01324 {
01325   if ( mDataProvider )
01326   {
01327     int type = mDataProvider->geometryType();
01328     switch ( type )
01329     {
01330       case QGis::WKBPoint:
01331       case QGis::WKBPoint25D:
01332         return QGis::Point;
01333 
01334       case QGis::WKBLineString:
01335       case QGis::WKBLineString25D:
01336         return QGis::Line;
01337 
01338       case QGis::WKBPolygon:
01339       case QGis::WKBPolygon25D:
01340         return QGis::Polygon;
01341 
01342       case QGis::WKBMultiPoint:
01343       case QGis::WKBMultiPoint25D:
01344         return QGis::Point;
01345 
01346       case QGis::WKBMultiLineString:
01347       case QGis::WKBMultiLineString25D:
01348         return QGis::Line;
01349 
01350       case QGis::WKBMultiPolygon:
01351       case QGis::WKBMultiPolygon25D:
01352         return QGis::Polygon;
01353 
01354       case QGis::WKBNoGeometry:
01355         return QGis::NoGeometry;
01356     }
01357     QgsDebugMsg( QString( "Data Provider Geometry type is not recognised, is %1" ).arg( type ) );
01358   }
01359   else
01360   {
01361     QgsDebugMsg( "pointer to mDataProvider is null" );
01362   }
01363 
01364   // We shouldn't get here, and if we have, other things are likely to
01365   // go wrong. Code that uses the type() return value should be
01366   // rewritten to cope with a value of QGis::Unknown. To make this
01367   // need known, the following message is printed every time we get
01368   // here.
01369   QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
01370 
01371   return QGis::UnknownGeometry;
01372 }
01373 
01374 bool QgsVectorLayer::hasGeometryType() const
01375 {
01376   QGis::GeometryType t = geometryType();
01377   return ( t != QGis::NoGeometry && t != QGis::UnknownGeometry );
01378 }
01379 
01380 QGis::WkbType QgsVectorLayer::wkbType() const
01381 {
01382   return ( QGis::WkbType )( mWkbType );
01383 }
01384 
01385 QgsRectangle QgsVectorLayer::boundingBoxOfSelected()
01386 {
01387   if ( mSelectedFeatureIds.size() == 0 ) //no selected features
01388   {
01389     return QgsRectangle( 0, 0, 0, 0 );
01390   }
01391 
01392   QgsRectangle r, retval;
01393 
01394 
01395   select( QgsAttributeList(), QgsRectangle(), true );
01396 
01397   retval.setMinimal();
01398 
01399   QgsFeature fet;
01400   while ( nextFeature( fet ) )
01401   {
01402     if ( mSelectedFeatureIds.contains( fet.id() ) )
01403     {
01404       if ( fet.geometry() )
01405       {
01406         r = fet.geometry()->boundingBox();
01407         retval.combineExtentWith( &r );
01408       }
01409     }
01410   }
01411 
01412   if ( retval.width() == 0.0 || retval.height() == 0.0 )
01413   {
01414     // If all of the features are at the one point, buffer the
01415     // rectangle a bit. If they are all at zero, do something a bit
01416     // more crude.
01417 
01418     if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
01419          retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
01420     {
01421       retval.set( -1.0, -1.0, 1.0, 1.0 );
01422     }
01423   }
01424 
01425   return retval;
01426 }
01427 
01428 
01429 
01430 long QgsVectorLayer::featureCount() const
01431 {
01432   if ( !mDataProvider )
01433   {
01434     QgsDebugMsg( "invoked with null mDataProvider" );
01435     return 0;
01436   }
01437 
01438   return mDataProvider->featureCount();
01439 }
01440 
01441 long QgsVectorLayer::updateFeatureCount() const
01442 {
01443   return -1;
01444 }
01445 
01446 void QgsVectorLayer::updateExtents()
01447 {
01448   if ( !hasGeometryType() )
01449     return;
01450 
01451   mLayerExtent.setMinimal();
01452 
01453   if ( !mDataProvider )
01454     QgsDebugMsg( "invoked with null mDataProvider" );
01455 
01456   if ( mDeletedFeatureIds.isEmpty() && mChangedGeometries.isEmpty() )
01457   {
01458     // get the extent of the layer from the provider
01459     // but only when there are some features already
01460     if ( mDataProvider->featureCount() != 0 )
01461     {
01462       QgsRectangle r = mDataProvider->extent();
01463       mLayerExtent.combineExtentWith( &r );
01464     }
01465 
01466     for ( QgsFeatureList::iterator it = mAddedFeatures.begin(); it != mAddedFeatures.end(); it++ )
01467     {
01468       QgsRectangle r = it->geometry()->boundingBox();
01469       mLayerExtent.combineExtentWith( &r );
01470     }
01471   }
01472   else
01473   {
01474     select( QgsAttributeList(), QgsRectangle(), true );
01475 
01476     QgsFeature fet;
01477     while ( nextFeature( fet ) )
01478     {
01479       if ( fet.geometry() )
01480       {
01481         QgsRectangle bb = fet.geometry()->boundingBox();
01482         mLayerExtent.combineExtentWith( &bb );
01483       }
01484     }
01485   }
01486 
01487   if ( mLayerExtent.xMinimum() > mLayerExtent.xMaximum() && mLayerExtent.yMinimum() > mLayerExtent.yMaximum() )
01488   {
01489     // special case when there are no features in provider nor any added
01490     mLayerExtent = QgsRectangle(); // use rectangle with zero coordinates
01491   }
01492 
01493   // Send this (hopefully) up the chain to the map canvas
01494   emit recalculateExtents();
01495 }
01496 
01497 QString QgsVectorLayer::subsetString()
01498 {
01499   if ( ! mDataProvider )
01500   {
01501     QgsDebugMsg( "invoked with null mDataProvider" );
01502     return 0;
01503   }
01504   return mDataProvider->subsetString();
01505 }
01506 
01507 bool QgsVectorLayer::setSubsetString( QString subset )
01508 {
01509   if ( ! mDataProvider )
01510   {
01511     QgsDebugMsg( "invoked with null mDataProvider" );
01512     return false;
01513   }
01514 
01515   bool res = mDataProvider->setSubsetString( subset );
01516 
01517   // get the updated data source string from the provider
01518   mDataSource = mDataProvider->dataSourceUri();
01519   updateExtents();
01520 
01521   if ( res )
01522     setCacheImage( 0 );
01523 
01524   return res;
01525 }
01526 
01527 void QgsVectorLayer::updateFeatureAttributes( QgsFeature &f, bool all )
01528 {
01529   if ( mDataProvider && ( all || ( mFetchAttributes.size() > 0 && mJoinBuffer->containsFetchJoins() ) ) )
01530   {
01531     int index = 0;
01532     QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), index );
01533     mJoinBuffer->updateFeatureAttributes( f, index, all );
01534   }
01535 
01536 
01537   // do not update when we aren't in editing mode
01538   if ( !mEditable )
01539     return;
01540 
01541   if ( mChangedAttributeValues.contains( f.id() ) )
01542   {
01543     const QgsAttributeMap &map = mChangedAttributeValues[f.id()];
01544     for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); it++ )
01545       f.changeAttribute( it.key(), it.value() );
01546   }
01547 
01548   // remove all attributes that will disappear
01549   QgsAttributeMap map = f.attributeMap();
01550   for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); it++ )
01551     if ( !mUpdatedFields.contains( it.key() ) )
01552       f.deleteAttribute( it.key() );
01553 
01554   // null/add all attributes that were added, but don't exist in the feature yet
01555   for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
01556     if ( !map.contains( it.key() ) && ( all || mFetchAttributes.contains( it.key() ) ) )
01557       f.changeAttribute( it.key(), QVariant( QString::null ) );
01558 }
01559 
01560 void QgsVectorLayer::addJoinedFeatureAttributes( QgsFeature& f, const QgsVectorJoinInfo& joinInfo, const QString& joinFieldName,
01561     const QVariant& joinValue, const QgsAttributeList& attributes, int attributeIndexOffset )
01562 {
01563   const QHash< QString, QgsAttributeMap>& memoryCache = joinInfo.cachedAttributes;
01564   if ( !memoryCache.isEmpty() ) //use join memory cache
01565   {
01566     QgsAttributeMap featureAttributes = memoryCache.value( joinValue.toString() );
01567     bool found = !featureAttributes.isEmpty();
01568     QgsAttributeList::const_iterator attIt = attributes.constBegin();
01569     for ( ; attIt != attributes.constEnd(); ++attIt )
01570     {
01571       if ( found )
01572       {
01573         f.addAttribute( *attIt + attributeIndexOffset, featureAttributes.value( *attIt ) );
01574       }
01575       else
01576       {
01577         f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
01578       }
01579     }
01580   }
01581   else //work with subset string
01582   {
01583     QgsVectorLayer* joinLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
01584     if ( !joinLayer )
01585     {
01586       return;
01587     }
01588 
01589     //no memory cache, query the joined values by setting substring
01590     QString subsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
01591     QString bkSubsetString = subsetString;
01592     if ( !subsetString.isEmpty() )
01593     {
01594       subsetString.append( " AND " );
01595     }
01596 
01597     subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
01598     joinLayer->dataProvider()->setSubsetString( subsetString, false );
01599 
01600     //select (no geometry)
01601     joinLayer->select( attributes, QgsRectangle(), false, false );
01602 
01603     //get first feature
01604     QgsFeature fet;
01605     if ( joinLayer->nextFeature( fet ) )
01606     {
01607       QgsAttributeMap attMap = fet.attributeMap();
01608       QgsAttributeMap::const_iterator attIt = attMap.constBegin();
01609       for ( ; attIt != attMap.constEnd(); ++attIt )
01610       {
01611         f.addAttribute( attIt.key() + attributeIndexOffset, attIt.value() );
01612       }
01613     }
01614     else //no suitable join feature found, insert invalid variants
01615     {
01616       QgsAttributeList::const_iterator attIt = attributes.constBegin();
01617       for ( ; attIt != attributes.constEnd(); ++attIt )
01618       {
01619         f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
01620       }
01621     }
01622 
01623     joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
01624   }
01625 }
01626 
01627 void QgsVectorLayer::updateFeatureGeometry( QgsFeature &f )
01628 {
01629   if ( mChangedGeometries.contains( f.id() ) )
01630     f.setGeometry( mChangedGeometries[f.id()] );
01631 }
01632 
01633 
01634 void QgsVectorLayer::select( QgsAttributeList attributes, QgsRectangle rect, bool fetchGeometries, bool useIntersect )
01635 {
01636   if ( !mDataProvider )
01637     return;
01638 
01639   mFetching        = true;
01640   mFetchRect       = rect;
01641   mFetchAttributes = attributes;
01642   mFetchGeometry   = fetchGeometries;
01643   mFetchConsidered = mDeletedFeatureIds;
01644   QgsAttributeList targetJoinFieldList;
01645 
01646   if ( mEditable )
01647   {
01648     mFetchAddedFeaturesIt = mAddedFeatures.begin();
01649     mFetchChangedGeomIt = mChangedGeometries.begin();
01650   }
01651 
01652   //look in the normal features of the provider
01653   if ( mFetchAttributes.size() > 0 )
01654   {
01655     if ( mEditable || mJoinBuffer->containsJoins() )
01656     {
01657       QgsAttributeList joinFields;
01658 
01659       int maxProviderIndex = 0;
01660       if ( mDataProvider )
01661       {
01662         QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), maxProviderIndex );
01663       }
01664 
01665       mJoinBuffer->select( mFetchAttributes, joinFields, maxProviderIndex );
01666       QgsAttributeList::const_iterator joinFieldIt = joinFields.constBegin();
01667       for ( ; joinFieldIt != joinFields.constEnd(); ++joinFieldIt )
01668       {
01669         if ( !mFetchAttributes.contains( *joinFieldIt ) )
01670         {
01671           mFetchAttributes.append( *joinFieldIt );
01672         }
01673       }
01674 
01675       //detect which fields are from the provider
01676       mFetchProvAttributes.clear();
01677       for ( QgsAttributeList::iterator it = mFetchAttributes.begin(); it != mFetchAttributes.end(); it++ )
01678       {
01679         if ( mDataProvider->fields().contains( *it ) )
01680         {
01681           mFetchProvAttributes << *it;
01682         }
01683       }
01684 
01685       mDataProvider->select( mFetchProvAttributes, rect, fetchGeometries, useIntersect );
01686     }
01687     else
01688     {
01689       mDataProvider->select( mFetchAttributes, rect, fetchGeometries, useIntersect );
01690     }
01691   }
01692   else //we don't need any attributes at all
01693   {
01694     mDataProvider->select( QgsAttributeList(), rect, fetchGeometries, useIntersect );
01695   }
01696 }
01697 
01698 bool QgsVectorLayer::nextFeature( QgsFeature &f )
01699 {
01700   if ( !mFetching )
01701     return false;
01702 
01703   if ( mEditable )
01704   {
01705     if ( !mFetchRect.isEmpty() )
01706     {
01707       // check if changed geometries are in rectangle
01708       for ( ; mFetchChangedGeomIt != mChangedGeometries.end(); mFetchChangedGeomIt++ )
01709       {
01710         int fid = mFetchChangedGeomIt.key();
01711 
01712         if ( mFetchConsidered.contains( fid ) )
01713           // skip deleted features
01714           continue;
01715 
01716         mFetchConsidered << fid;
01717 
01718         if ( !mFetchChangedGeomIt->intersects( mFetchRect ) )
01719           // skip changed geometries not in rectangle and don't check again
01720           continue;
01721 
01722         f.setFeatureId( fid );
01723         f.setValid( true );
01724 
01725         if ( mFetchGeometry )
01726           f.setGeometry( mFetchChangedGeomIt.value() );
01727 
01728         if ( mFetchAttributes.size() > 0 )
01729         {
01730           if ( fid < 0 )
01731           {
01732             // fid<0 => in mAddedFeatures
01733             bool found = false;
01734 
01735             for ( QgsFeatureList::iterator it = mAddedFeatures.begin(); it != mAddedFeatures.end(); it++ )
01736             {
01737               if ( fid == it->id() )
01738               {
01739                 found = true;
01740                 f.setAttributeMap( it->attributeMap() );
01741                 updateFeatureAttributes( f );
01742                 break;
01743               }
01744             }
01745 
01746             if ( !found )
01747               QgsDebugMsg( QString( "No attributes for the added feature %1 found" ).arg( f.id() ) );
01748           }
01749           else
01750           {
01751             // retrieve attributes from provider
01752             QgsFeature tmp;
01753             mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
01754             updateFeatureAttributes( tmp );
01755             f.setAttributeMap( tmp.attributeMap() );
01756           }
01757         }
01758 
01759         // return complete feature
01760         mFetchChangedGeomIt++;
01761         return true;
01762       }
01763 
01764       // no more changed geometries
01765     }
01766 
01767     for ( ; mFetchAddedFeaturesIt != mAddedFeatures.end(); mFetchAddedFeaturesIt++ )
01768     {
01769       int fid = mFetchAddedFeaturesIt->id();
01770 
01771       if ( mFetchConsidered.contains( fid ) )
01772         // must have changed geometry outside rectangle
01773         continue;
01774 
01775       if ( !mFetchRect.isEmpty() &&
01776            mFetchAddedFeaturesIt->geometry() &&
01777            !mFetchAddedFeaturesIt->geometry()->intersects( mFetchRect ) )
01778         // skip added features not in rectangle
01779         continue;
01780 
01781       f.setFeatureId( fid );
01782       f.setValid( true );
01783 
01784       if ( mFetchGeometry )
01785         f.setGeometry( *mFetchAddedFeaturesIt->geometry() );
01786 
01787       if ( mFetchAttributes.size() > 0 )
01788       {
01789         f.setAttributeMap( mFetchAddedFeaturesIt->attributeMap() );
01790         updateFeatureAttributes( f );
01791       }
01792 
01793       mFetchAddedFeaturesIt++;
01794       return true;
01795     }
01796 
01797     // no more added features
01798   }
01799 
01800   while ( dataProvider()->nextFeature( f ) )
01801   {
01802     if ( mFetchConsidered.contains( f.id() ) )
01803     {
01804       continue;
01805     }
01806     if ( mFetchAttributes.size() > 0 )
01807     {
01808       updateFeatureAttributes( f ); //check joined attributes / changed attributes
01809     }
01810     return true;
01811   }
01812 
01813   mFetching = false;
01814   return false;
01815 }
01816 
01817 bool QgsVectorLayer::featureAtId( int featureId, QgsFeature& f, bool fetchGeometries, bool fetchAttributes )
01818 {
01819   if ( !mDataProvider )
01820     return false;
01821 
01822   if ( mDeletedFeatureIds.contains( featureId ) )
01823     return false;
01824 
01825   if ( fetchGeometries && mChangedGeometries.contains( featureId ) )
01826   {
01827     f.setFeatureId( featureId );
01828     f.setValid( true );
01829     f.setGeometry( mChangedGeometries[featureId] );
01830 
01831     if ( fetchAttributes )
01832     {
01833       if ( featureId < 0 )
01834       {
01835         // featureId<0 => in mAddedFeatures
01836         bool found = false;
01837 
01838         for ( QgsFeatureList::iterator it = mAddedFeatures.begin(); it != mAddedFeatures.end(); it++ )
01839         {
01840           if ( featureId != it->id() )
01841           {
01842             found = true;
01843             f.setAttributeMap( it->attributeMap() );
01844             break;
01845           }
01846         }
01847 
01848         if ( !found )
01849           QgsDebugMsg( QString( "No attributes for the added feature %1 found" ).arg( f.id() ) );
01850       }
01851       else
01852       {
01853         // retrieve attributes from provider
01854         QgsFeature tmp;
01855         mDataProvider->featureAtId( featureId, tmp, false, mDataProvider->attributeIndexes() );
01856         f.setAttributeMap( tmp.attributeMap() );
01857       }
01858       updateFeatureAttributes( f, true );
01859     }
01860     return true;
01861   }
01862 
01863   //added features
01864   for ( QgsFeatureList::iterator iter = mAddedFeatures.begin(); iter != mAddedFeatures.end(); ++iter )
01865   {
01866     if ( iter->id() == featureId )
01867     {
01868       f.setFeatureId( iter->id() );
01869       f.setValid( true );
01870       if ( fetchGeometries )
01871         f.setGeometry( *iter->geometry() );
01872 
01873       if ( fetchAttributes )
01874         f.setAttributeMap( iter->attributeMap() );
01875 
01876       return true;
01877     }
01878   }
01879 
01880   // regular features
01881   if ( fetchAttributes )
01882   {
01883     if ( mDataProvider->featureAtId( featureId, f, fetchGeometries, mDataProvider->attributeIndexes() ) )
01884     {
01885       updateFeatureAttributes( f, true );
01886       return true;
01887     }
01888   }
01889   else
01890   {
01891     if ( mDataProvider->featureAtId( featureId, f, fetchGeometries, QgsAttributeList() ) )
01892     {
01893       return true;
01894     }
01895   }
01896   return false;
01897 }
01898 
01899 bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
01900 {
01901   static int addedIdLowWaterMark = -1;
01902 
01903   if ( !mDataProvider )
01904   {
01905     return false;
01906   }
01907 
01908   if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) )
01909   {
01910     return false;
01911   }
01912 
01913   if ( !isEditable() )
01914   {
01915     return false;
01916   }
01917 
01918   //assign a temporary id to the feature (use negative numbers)
01919   addedIdLowWaterMark--;
01920 
01921   QgsDebugMsg( "Assigned feature id " + QString::number( addedIdLowWaterMark ) );
01922 
01923   // Force a feature ID (to keep other functions in QGIS happy,
01924   // providers will use their own new feature ID when we commit the new feature)
01925   // and add to the known added features.
01926   f.setFeatureId( addedIdLowWaterMark );
01927   editFeatureAdd( f );
01928 
01929   if ( f.geometry() )
01930     mCachedGeometries[f.id()] = *f.geometry();
01931 
01932   setModified( true );
01933 
01934   if ( alsoUpdateExtent )
01935   {
01936     updateExtents();
01937   }
01938 
01939   emit featureAdded( f.id() );
01940 
01941   return true;
01942 }
01943 
01944 
01945 bool QgsVectorLayer::insertVertex( double x, double y, int atFeatureId, int beforeVertex )
01946 {
01947   if ( !hasGeometryType() )
01948     return false;
01949 
01950   if ( !mEditable )
01951   {
01952     return false;
01953   }
01954 
01955   if ( mDataProvider )
01956   {
01957     QgsGeometry geometry;
01958     if ( !mChangedGeometries.contains( atFeatureId ) )
01959     {
01960       // first time this geometry has changed since last commit
01961       if ( !mCachedGeometries.contains( atFeatureId ) )
01962       {
01963         return false;
01964       }
01965       geometry = mCachedGeometries[atFeatureId];
01966       //mChangedGeometries[atFeatureId] = mCachedGeometries[atFeatureId];
01967     }
01968     else
01969     {
01970       geometry = mChangedGeometries[atFeatureId];
01971     }
01972     geometry.insertVertex( x, y, beforeVertex );
01973     mCachedGeometries[atFeatureId] = geometry;
01974     editGeometryChange( atFeatureId, geometry );
01975 
01976     setModified( true, true ); // only geometry was changed
01977 
01978     return true;
01979   }
01980   return false;
01981 }
01982 
01983 
01984 bool QgsVectorLayer::moveVertex( double x, double y, int atFeatureId, int atVertex )
01985 {
01986   if ( !hasGeometryType() )
01987     return false;
01988 
01989   if ( !mEditable )
01990   {
01991     return false;
01992   }
01993 
01994   if ( mDataProvider )
01995   {
01996     QgsGeometry geometry;
01997     if ( !mChangedGeometries.contains( atFeatureId ) )
01998     {
01999       // first time this geometry has changed since last commit
02000       if ( !mCachedGeometries.contains( atFeatureId ) )
02001       {
02002         return false;
02003       }
02004       geometry = mCachedGeometries[atFeatureId];
02005       //mChangedGeometries[atFeatureId] = mCachedGeometries[atFeatureId];
02006     }
02007     else
02008     {
02009       geometry = mChangedGeometries[atFeatureId];
02010     }
02011 
02012     geometry.moveVertex( x, y, atVertex );
02013     mCachedGeometries[atFeatureId] = geometry;
02014     editGeometryChange( atFeatureId, geometry );
02015 
02016     setModified( true, true ); // only geometry was changed
02017 
02018     return true;
02019   }
02020   return false;
02021 }
02022 
02023 
02024 bool QgsVectorLayer::deleteVertex( int atFeatureId, int atVertex )
02025 {
02026   if ( !hasGeometryType() )
02027     return false;
02028 
02029   if ( !mEditable )
02030   {
02031     return false;
02032   }
02033 
02034   if ( mDataProvider )
02035   {
02036     QgsGeometry geometry;
02037     if ( !mChangedGeometries.contains( atFeatureId ) )
02038     {
02039       // first time this geometry has changed since last commit
02040       if ( !mCachedGeometries.contains( atFeatureId ) )
02041       {
02042         return false;
02043       }
02044       geometry = mCachedGeometries[atFeatureId];
02045     }
02046     else
02047     {
02048       geometry = mChangedGeometries[atFeatureId];
02049     }
02050 
02051     if ( !geometry.deleteVertex( atVertex ) )
02052     {
02053       return false;
02054     }
02055     mCachedGeometries[atFeatureId] = geometry;
02056     editGeometryChange( atFeatureId, geometry );
02057 
02058     setModified( true, true ); // only geometry was changed
02059 
02060     return true;
02061   }
02062   return false;
02063 }
02064 
02065 
02066 bool QgsVectorLayer::deleteSelectedFeatures()
02067 {
02068   if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
02069   {
02070     return false;
02071   }
02072 
02073   if ( !isEditable() )
02074   {
02075     return false;
02076   }
02077 
02078   if ( mSelectedFeatureIds.size() == 0 )
02079     return true;
02080 
02081   while ( mSelectedFeatureIds.size() > 0 )
02082   {
02083     int fid = *mSelectedFeatureIds.begin();
02084     deleteFeature( fid );  // removes from selection
02085   }
02086 
02087   // invalidate cache
02088   setCacheImage( 0 );
02089 
02090   emit selectionChanged();
02091 
02092   triggerRepaint();
02093   updateExtents();
02094 
02095   return true;
02096 }
02097 
02098 int QgsVectorLayer::addRing( const QList<QgsPoint>& ring )
02099 {
02100   if ( !hasGeometryType() )
02101     return 5;
02102 
02103   int addRingReturnCode = 5; //default: return code for 'ring not inserted'
02104   double xMin, yMin, xMax, yMax;
02105   QgsRectangle bBox;
02106 
02107   if ( boundingBoxFromPointList( ring, xMin, yMin, xMax, yMax ) == 0 )
02108   {
02109     bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
02110     bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
02111   }
02112   else
02113   {
02114     return 3; //ring not valid
02115   }
02116 
02117   select( QgsAttributeList(), bBox, true, true );
02118 
02119   QgsFeature f;
02120   while ( nextFeature( f ) )
02121   {
02122     addRingReturnCode = f.geometry()->addRing( ring );
02123     if ( addRingReturnCode == 0 )
02124     {
02125       editGeometryChange( f.id(), *f.geometry() );
02126 
02127       setModified( true, true );
02128       break;
02129     }
02130   }
02131 
02132   return addRingReturnCode;
02133 }
02134 
02135 int QgsVectorLayer::addIsland( const QList<QgsPoint>& ring )
02136 {
02137   if ( !hasGeometryType() )
02138     return 6;
02139 
02140   //number of selected features must be 1
02141 
02142   if ( mSelectedFeatureIds.size() < 1 )
02143   {
02144     QgsDebugMsg( "Number of selected features <1" );
02145     return 4;
02146   }
02147   else if ( mSelectedFeatureIds.size() > 1 )
02148   {
02149     QgsDebugMsg( "Number of selected features >1" );
02150     return 5;
02151   }
02152 
02153   int selectedFeatureId = *mSelectedFeatureIds.constBegin();
02154 
02155   //look if geometry of selected feature already contains geometry changes
02156   QgsGeometryMap::iterator changedIt = mChangedGeometries.find( selectedFeatureId );
02157   if ( changedIt != mChangedGeometries.end() )
02158   {
02159     QgsGeometry geom = *changedIt;
02160     int returnValue = geom.addIsland( ring );
02161     editGeometryChange( selectedFeatureId, geom );
02162     mCachedGeometries[selectedFeatureId] = geom;
02163     return returnValue;
02164   }
02165 
02166   //look if id of selected feature belongs to an added feature
02167 #if 0
02168   for ( QgsFeatureList::iterator addedIt = mAddedFeatures.begin(); addedIt != mAddedFeatures.end(); ++addedIt )
02169   {
02170     if ( addedIt->id() == selectedFeatureId )
02171     {
02172       return addedIt->geometry()->addIsland( ring );
02173       mCachedGeometries[selectedFeatureId] = *addedIt->geometry();
02174     }
02175   }
02176 #endif
02177 
02178   //is the feature contained in the view extent (mCachedGeometries) ?
02179   QgsGeometryMap::iterator cachedIt = mCachedGeometries.find( selectedFeatureId );
02180   if ( cachedIt != mCachedGeometries.end() )
02181   {
02182     int errorCode = cachedIt->addIsland( ring );
02183     if ( errorCode == 0 )
02184     {
02185       editGeometryChange( selectedFeatureId, *cachedIt );
02186       mCachedGeometries[selectedFeatureId] = *cachedIt;
02187       setModified( true, true );
02188     }
02189     return errorCode;
02190   }
02191   else //maybe the selected feature has been moved outside the visible area and therefore is not contained in mCachedGeometries
02192   {
02193     QgsFeature f;
02194     QgsGeometry* fGeom = 0;
02195     if ( featureAtId( selectedFeatureId, f, true, false ) )
02196     {
02197       fGeom = f.geometryAndOwnership();
02198       if ( fGeom )
02199       {
02200         int errorCode = fGeom->addIsland( ring );
02201         editGeometryChange( selectedFeatureId, *fGeom );
02202         setModified( true, true );
02203         delete fGeom;
02204         return errorCode;
02205       }
02206     }
02207   }
02208 
02209   return 6; //geometry not found
02210 }
02211 
02212 int QgsVectorLayer::translateFeature( int featureId, double dx, double dy )
02213 {
02214   if ( !hasGeometryType() )
02215     return 1;
02216 
02217   //look if geometry of selected feature already contains geometry changes
02218   QgsGeometryMap::iterator changedIt = mChangedGeometries.find( featureId );
02219   if ( changedIt != mChangedGeometries.end() )
02220   {
02221     QgsGeometry geom = *changedIt;
02222     int errorCode = geom.translate( dx, dy );
02223     editGeometryChange( featureId, geom );
02224     return errorCode;
02225   }
02226 
02227   //look if id of selected feature belongs to an added feature
02228 #if 0
02229   for ( QgsFeatureList::iterator addedIt = mAddedFeatures.begin(); addedIt != mAddedFeatures.end(); ++addedIt )
02230   {
02231     if ( addedIt->id() == featureId )
02232     {
02233       return addedIt->geometry()->translate( dx, dy );
02234     }
02235   }
02236 #endif
02237 
02238   //else look in mCachedGeometries to make access faster
02239   QgsGeometryMap::iterator cachedIt = mCachedGeometries.find( featureId );
02240   if ( cachedIt != mCachedGeometries.end() )
02241   {
02242     int errorCode = cachedIt->translate( dx, dy );
02243     if ( errorCode == 0 )
02244     {
02245       editGeometryChange( featureId, *cachedIt );
02246       setModified( true, true );
02247     }
02248     return errorCode;
02249   }
02250 
02251   //else get the geometry from provider (may be slow)
02252   QgsFeature f;
02253   if ( mDataProvider && mDataProvider->featureAtId( featureId, f, true ) )
02254   {
02255     if ( f.geometry() )
02256     {
02257       QgsGeometry translateGeom( *( f.geometry() ) );
02258       int errorCode = translateGeom.translate( dx, dy );
02259       if ( errorCode == 0 )
02260       {
02261         editGeometryChange( featureId, translateGeom );
02262         setModified( true, true );
02263       }
02264       return errorCode;
02265     }
02266   }
02267   return 1; //geometry not found
02268 }
02269 
02270 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
02271 {
02272   if ( !hasGeometryType() )
02273     return 4;
02274 
02275   QgsFeatureList newFeatures; //store all the newly created features
02276   double xMin, yMin, xMax, yMax;
02277   QgsRectangle bBox; //bounding box of the split line
02278   int returnCode = 0;
02279   int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
02280   int numberOfSplittedFeatures = 0;
02281 
02282   QgsFeatureList featureList;
02283   const QgsFeatureIds selectedIds = selectedFeaturesIds();
02284 
02285   if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
02286   {
02287     featureList = selectedFeatures();
02288   }
02289   else //else consider all the feature that intersect the bounding box of the split line
02290   {
02291     if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
02292     {
02293       bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
02294       bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
02295     }
02296     else
02297     {
02298       return 1;
02299     }
02300 
02301     if ( bBox.isEmpty() )
02302     {
02303       //if the bbox is a line, try to make a square out of it
02304       if ( bBox.width() == 0.0 && bBox.height() > 0 )
02305       {
02306         bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
02307         bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
02308       }
02309       else if ( bBox.height() == 0.0 && bBox.width() > 0 )
02310       {
02311         bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
02312         bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
02313       }
02314       else
02315       {
02316         return 2;
02317       }
02318     }
02319 
02320     select( pendingAllAttributesList(), bBox, true, true );
02321 
02322     QgsFeature f;
02323     while ( nextFeature( f ) )
02324       featureList << QgsFeature( f );
02325   }
02326 
02327   QgsFeatureList::iterator select_it = featureList.begin();
02328   for ( ; select_it != featureList.end(); ++select_it )
02329   {
02330     QList<QgsGeometry*> newGeometries;
02331     QList<QgsPoint> topologyTestPoints;
02332     QgsGeometry* newGeometry = 0;
02333     splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
02334     if ( splitFunctionReturn == 0 )
02335     {
02336       //change this geometry
02337       editGeometryChange( select_it->id(), *( select_it->geometry() ) );
02338       //update of cached geometries is necessary because we use addTopologicalPoints() later
02339       mCachedGeometries[select_it->id()] = *( select_it->geometry() );
02340 
02341       //insert new features
02342       for ( int i = 0; i < newGeometries.size(); ++i )
02343       {
02344         newGeometry = newGeometries.at( i );
02345         QgsFeature newFeature;
02346         newFeature.setGeometry( newGeometry );
02347         newFeature.setAttributeMap( select_it->attributeMap() );
02348         newFeatures.append( newFeature );
02349       }
02350 
02351       setModified( true, true );
02352       if ( topologicalEditing )
02353       {
02354         QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
02355         for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
02356         {
02357           addTopologicalPoints( *topol_it );
02358         }
02359       }
02360       ++numberOfSplittedFeatures;
02361     }
02362     else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
02363     {
02364       returnCode = splitFunctionReturn;
02365     }
02366   }
02367 
02368   if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
02369   {
02370     //There is a selection but no feature has been split.
02371     //Maybe user forgot that only the selected features are split
02372     returnCode = 4;
02373   }
02374 
02375 
02376   //now add the new features to this vectorlayer
02377   addFeatures( newFeatures, false );
02378 
02379   return returnCode;
02380 }
02381 
02382 int QgsVectorLayer::removePolygonIntersections( QgsGeometry* geom )
02383 {
02384   if ( !hasGeometryType() )
02385     return 1;
02386 
02387   int returnValue = 0;
02388 
02389   //first test if geom really has type polygon or multipolygon
02390   if ( geom->type() != QGis::Polygon )
02391   {
02392     return 1;
02393   }
02394 
02395   //get bounding box of geom
02396   QgsRectangle geomBBox = geom->boundingBox();
02397 
02398   //get list of features that intersect this bounding box
02399   select( QgsAttributeList(), geomBBox, true, true );
02400 
02401   QgsFeature f;
02402   while ( nextFeature( f ) )
02403   {
02404     //call geometry->makeDifference for each feature
02405     QgsGeometry *currentGeom = f.geometry();
02406     if ( currentGeom )
02407     {
02408       if ( geom->makeDifference( currentGeom ) != 0 )
02409       {
02410         returnValue = 2;
02411       }
02412     }
02413   }
02414   return returnValue;
02415 }
02416 
02417 int QgsVectorLayer::addTopologicalPoints( QgsGeometry* geom )
02418 {
02419   if ( !hasGeometryType() )
02420     return 1;
02421 
02422   if ( !geom )
02423   {
02424     return 1;
02425   }
02426 
02427   int returnVal = 0;
02428 
02429   QGis::WkbType wkbType = geom->wkbType();
02430 
02431   switch ( wkbType )
02432   {
02433       //line
02434     case QGis::WKBLineString25D:
02435     case QGis::WKBLineString:
02436     {
02437       QgsPolyline theLine = geom->asPolyline();
02438       QgsPolyline::const_iterator line_it = theLine.constBegin();
02439       for ( ; line_it != theLine.constEnd(); ++line_it )
02440       {
02441         if ( addTopologicalPoints( *line_it ) != 0 )
02442         {
02443           returnVal = 2;
02444         }
02445       }
02446       break;
02447     }
02448 
02449     //multiline
02450     case QGis::WKBMultiLineString25D:
02451     case QGis::WKBMultiLineString:
02452     {
02453       QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
02454       QgsPolyline currentPolyline;
02455 
02456       for ( int i = 0; i < theMultiLine.size(); ++i )
02457       {
02458         QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
02459         for ( ; line_it != currentPolyline.constEnd(); ++line_it )
02460         {
02461           if ( addTopologicalPoints( *line_it ) != 0 )
02462           {
02463             returnVal = 2;
02464           }
02465         }
02466       }
02467       break;
02468     }
02469 
02470     //polygon
02471     case QGis::WKBPolygon25D:
02472     case QGis::WKBPolygon:
02473     {
02474       QgsPolygon thePolygon = geom->asPolygon();
02475       QgsPolyline currentRing;
02476 
02477       for ( int i = 0; i < thePolygon.size(); ++i )
02478       {
02479         currentRing = thePolygon.at( i );
02480         QgsPolyline::const_iterator line_it = currentRing.constBegin();
02481         for ( ; line_it != currentRing.constEnd(); ++line_it )
02482         {
02483           if ( addTopologicalPoints( *line_it ) != 0 )
02484           {
02485             returnVal = 2;
02486           }
02487         }
02488       }
02489       break;
02490     }
02491 
02492     //multipolygon
02493     case QGis::WKBMultiPolygon25D:
02494     case QGis::WKBMultiPolygon:
02495     {
02496       QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
02497       QgsPolygon currentPolygon;
02498       QgsPolyline currentRing;
02499 
02500       for ( int i = 0; i < theMultiPolygon.size(); ++i )
02501       {
02502         currentPolygon = theMultiPolygon.at( i );
02503         for ( int j = 0; j < currentPolygon.size(); ++j )
02504         {
02505           currentRing = currentPolygon.at( j );
02506           QgsPolyline::const_iterator line_it = currentRing.constBegin();
02507           for ( ; line_it != currentRing.constEnd(); ++line_it )
02508           {
02509             if ( addTopologicalPoints( *line_it ) != 0 )
02510             {
02511               returnVal = 2;
02512             }
02513           }
02514         }
02515       }
02516       break;
02517     }
02518     default:
02519       break;
02520   }
02521   return returnVal;
02522 }
02523 
02524 int QgsVectorLayer::addTopologicalPoints( const QgsPoint& p )
02525 {
02526   if ( !hasGeometryType() )
02527     return 1;
02528 
02529   QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
02530   //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
02531   QMultiMap<double, QgsSnappingResult> vertexSnapResults;
02532 
02533   QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
02534 
02535   //work with a tolerance because coordinate projection may introduce some rounding
02536   double threshold =  0.0000001;
02537   if ( mCRS && mCRS->mapUnits() == QGis::Meters )
02538   {
02539     threshold = 0.001;
02540   }
02541   else if ( mCRS && mCRS->mapUnits() == QGis::Feet )
02542   {
02543     threshold = 0.0001;
02544   }
02545 
02546 
02547   if ( snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
02548   {
02549     return 2;
02550   }
02551 
02552   QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
02553   QMultiMap<double, QgsSnappingResult>::const_iterator vertex_snap_it;
02554   for ( ; snap_it != snapResults.constEnd(); ++snap_it )
02555   {
02556     //test if p is already a vertex of this geometry. If yes, don't insert it
02557     bool vertexAlreadyExists = false;
02558     if ( snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
02559     {
02560       continue;
02561     }
02562 
02563     vertex_snap_it = vertexSnapResults.constBegin();
02564     for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
02565     {
02566       if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
02567       {
02568         vertexAlreadyExists = true;
02569       }
02570     }
02571 
02572     if ( !vertexAlreadyExists )
02573     {
02574       filteredSnapResults.push_back( *snap_it );
02575     }
02576   }
02577   insertSegmentVerticesForSnap( filteredSnapResults );
02578   return 0;
02579 }
02580 
02581 QgsLabel *QgsVectorLayer::label()
02582 {
02583   return mLabel;
02584 }
02585 
02586 const QgsLabel *QgsVectorLayer::label() const
02587 {
02588   return mLabel;
02589 }
02590 
02591 void QgsVectorLayer::enableLabels( bool on )
02592 {
02593   mLabelOn = on;
02594 }
02595 
02596 bool QgsVectorLayer::hasLabelsEnabled( void ) const
02597 {
02598   return mLabelOn;
02599 }
02600 
02601 bool QgsVectorLayer::startEditing()
02602 {
02603   if ( !mDataProvider )
02604   {
02605     return false;
02606   }
02607 
02608   // allow editing if provider supports any of the capabilities
02609   if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
02610   {
02611     return false;
02612   }
02613 
02614   if ( mReadOnly )
02615   {
02616     return false;
02617   }
02618 
02619   if ( mEditable )
02620   {
02621     // editing already underway
02622     return false;
02623   }
02624 
02625   mEditable = true;
02626 
02627   mAddedAttributeIds.clear();
02628   mDeletedAttributeIds.clear();
02629   updateFieldMap();
02630 
02631   for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
02632     if ( it.key() > mMaxUpdatedIndex )
02633       mMaxUpdatedIndex = it.key();
02634 
02635   emit editingStarted();
02636 
02637   return true;
02638 }
02639 
02640 bool QgsVectorLayer::readXml( QDomNode & layer_node )
02641 {
02642   QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
02643 
02644   //process provider key
02645   QDomNode pkeyNode = layer_node.namedItem( "provider" );
02646 
02647   if ( pkeyNode.isNull() )
02648   {
02649     mProviderKey = "";
02650   }
02651   else
02652   {
02653     QDomElement pkeyElt = pkeyNode.toElement();
02654     mProviderKey = pkeyElt.text();
02655   }
02656 
02657   // determine type of vector layer
02658   if ( ! mProviderKey.isNull() )
02659   {
02660     // if the provider string isn't empty, then we successfully
02661     // got the stored provider
02662   }
02663   else if ( mDataSource.contains( "dbname=" ) )
02664   {
02665     mProviderKey = "postgres";
02666   }
02667   else
02668   {
02669     mProviderKey = "ogr";
02670   }
02671 
02672   if ( ! setDataProvider( mProviderKey ) )
02673   {
02674     return false;
02675   }
02676 
02677   QDomElement pkeyElem = pkeyNode.toElement();
02678   if ( !pkeyElem.isNull() )
02679   {
02680     QString encodingString = pkeyElem.attribute( "encoding" );
02681     if ( !encodingString.isEmpty() )
02682     {
02683       mDataProvider->setEncoding( encodingString );
02684     }
02685   }
02686 
02687   //load vector joins
02688   if ( !mJoinBuffer )
02689   {
02690     mJoinBuffer = new QgsVectorLayerJoinBuffer();
02691   }
02692   mJoinBuffer->readXml( layer_node );
02693 
02694   updateFieldMap();
02695 
02696   QString errorMsg;
02697   if ( !readSymbology( layer_node, errorMsg ) )
02698   {
02699     return false;
02700   }
02701 
02702   return mValid;               // should be true if read successfully
02703 
02704 } // void QgsVectorLayer::readXml
02705 
02706 
02707 
02708 bool QgsVectorLayer::setDataProvider( QString const & provider )
02709 {
02710   // XXX should I check for and possibly delete any pre-existing providers?
02711   // XXX How often will that scenario occur?
02712 
02713   mProviderKey = provider;     // XXX is this necessary?  Usually already set
02714   // XXX when execution gets here.
02715 
02716   //XXX - This was a dynamic cast but that kills the Windows
02717   //      version big-time with an abnormal termination error
02718   mDataProvider =
02719     ( QgsVectorDataProvider* )( QgsProviderRegistry::instance()->getProvider( provider, mDataSource ) );
02720 
02721   if ( mDataProvider )
02722   {
02723     QgsDebugMsg( "Instantiated the data provider plugin" );
02724 
02725     mValid = mDataProvider->isValid();
02726     if ( mValid )
02727     {
02728 
02729       // TODO: Check if the provider has the capability to send fullExtentCalculated
02730       connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
02731 
02732       // get the extent
02733       QgsRectangle mbr = mDataProvider->extent();
02734 
02735       // show the extent
02736       QString s = mbr.toString();
02737       QgsDebugMsg( "Extent of layer: " +  s );
02738       // store the extent
02739       mLayerExtent.setXMaximum( mbr.xMaximum() );
02740       mLayerExtent.setXMinimum( mbr.xMinimum() );
02741       mLayerExtent.setYMaximum( mbr.yMaximum() );
02742       mLayerExtent.setYMinimum( mbr.yMinimum() );
02743 
02744       // get and store the feature type
02745       mWkbType = mDataProvider->geometryType();
02746 
02747       // look at the fields in the layer and set the primary
02748       // display field using some real fuzzy logic
02749       setDisplayField();
02750 
02751       if ( mProviderKey == "postgres" )
02752       {
02753         QgsDebugMsg( "Beautifying layer name " + name() );
02754 
02755         // adjust the display name for postgres layers
02756         QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
02757         if ( reg.indexIn( name() ) >= 0 )
02758         {
02759           QStringList stuff = reg.capturedTexts();
02760           QString lName = stuff[1];
02761 
02762           const QMap<QString, QgsMapLayer*> &layers = QgsMapLayerRegistry::instance()->mapLayers();
02763 
02764           QMap<QString, QgsMapLayer*>::const_iterator it;
02765           for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; it++ )
02766             ;
02767 
02768           if ( it != layers.constEnd() && stuff.size() > 2 )
02769           {
02770             lName += "." + stuff[2].mid( 2, stuff[2].length() - 3 );
02771           }
02772 
02773           if ( !lName.isEmpty() )
02774             setLayerName( lName );
02775         }
02776 
02777         QgsDebugMsg( "Beautified layer name " + name() );
02778 
02779         // deal with unnecessary schema qualification to make v.in.ogr happy
02780         mDataSource = mDataProvider->dataSourceUri();
02781       }
02782       else if ( mProviderKey == "osm" )
02783       {
02784         // make sure that the "observer" has been removed from URI to avoid crashes
02785         mDataSource = mDataProvider->dataSourceUri();
02786       }
02787 
02788       // label
02789       mLabel = new QgsLabel( mDataProvider->fields() );
02790       mLabelOn = false;
02791     }
02792     else
02793     {
02794       QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
02795       return false;
02796     }
02797   }
02798   else
02799   {
02800     QgsDebugMsg( " unable to get data provider" );
02801 
02802     return false;
02803   }
02804 
02805   return true;
02806 
02807 } // QgsVectorLayer:: setDataProvider
02808 
02809 
02810 
02811 
02812 /* virtual */
02813 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
02814                                QDomDocument & document )
02815 {
02816   // first get the layer element so that we can append the type attribute
02817 
02818   QDomElement mapLayerNode = layer_node.toElement();
02819 
02820   if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
02821   {
02822     QgsDebugMsg( "can't find <maplayer>" );
02823     return false;
02824   }
02825 
02826   mapLayerNode.setAttribute( "type", "vector" );
02827 
02828   // set the geometry type
02829   mapLayerNode.setAttribute( "geometry", QGis::qgisVectorGeometryType[geometryType()] );
02830 
02831   // add provider node
02832   if ( mDataProvider )
02833   {
02834     QDomElement provider  = document.createElement( "provider" );
02835     provider.setAttribute( "encoding", mDataProvider->encoding() );
02836     QDomText providerText = document.createTextNode( providerType() );
02837     provider.appendChild( providerText );
02838     layer_node.appendChild( provider );
02839   }
02840 
02841   //save joins
02842   mJoinBuffer->writeXml( layer_node, document );
02843 
02844   // renderer specific settings
02845   QString errorMsg;
02846   return writeSymbology( layer_node, document, errorMsg );
02847 } // bool QgsVectorLayer::writeXml
02848 
02849 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
02850 {
02851   if ( hasGeometryType() )
02852   {
02853     // try renderer v2 first
02854     QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
02855     if ( !rendererElement.isNull() )
02856     {
02857       // using renderer v2
02858       setUsingRendererV2( true );
02859 
02860       QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
02861       if ( r == NULL )
02862         return false;
02863 
02864       setRendererV2( r );
02865     }
02866     else
02867     {
02868       // using renderer v1
02869       setUsingRendererV2( false );
02870 
02871       // create and bind a renderer to this layer
02872 
02873       QDomNode singlenode = node.namedItem( "singlesymbol" );
02874       QDomNode graduatednode = node.namedItem( "graduatedsymbol" );
02875       QDomNode continuousnode = node.namedItem( "continuoussymbol" );
02876       QDomNode uniquevaluenode = node.namedItem( "uniquevalue" );
02877 
02878       QgsRenderer * renderer = 0;
02879       int returnCode = 1;
02880 
02881       if ( !singlenode.isNull() )
02882       {
02883         renderer = new QgsSingleSymbolRenderer( geometryType() );
02884         returnCode = renderer->readXML( singlenode, *this );
02885       }
02886       else if ( !graduatednode.isNull() )
02887       {
02888         renderer = new QgsGraduatedSymbolRenderer( geometryType() );
02889         returnCode = renderer->readXML( graduatednode, *this );
02890       }
02891       else if ( !continuousnode.isNull() )
02892       {
02893         renderer = new QgsContinuousColorRenderer( geometryType() );
02894         returnCode = renderer->readXML( continuousnode, *this );
02895       }
02896       else if ( !uniquevaluenode.isNull() )
02897       {
02898         renderer = new QgsUniqueValueRenderer( geometryType() );
02899         returnCode = renderer->readXML( uniquevaluenode, *this );
02900       }
02901 
02902       if ( !renderer )
02903       {
02904         errorMessage = tr( "Unknown renderer" );
02905         return false;
02906       }
02907 
02908       if ( returnCode == 1 )
02909       {
02910         errorMessage = tr( "No renderer object" ); delete renderer; return false;
02911       }
02912       else if ( returnCode == 2 )
02913       {
02914         errorMessage = tr( "Classification field not found" ); delete renderer; return false;
02915       }
02916 
02917       mRenderer = renderer;
02918     }
02919 
02920     // get and set the display field if it exists.
02921     QDomNode displayFieldNode = node.namedItem( "displayfield" );
02922     if ( !displayFieldNode.isNull() )
02923     {
02924       QDomElement e = displayFieldNode.toElement();
02925       setDisplayField( e.text() );
02926     }
02927 
02928     // use scale dependent visibility flag
02929     QDomElement e = node.toElement();
02930     mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
02931     mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
02932     mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
02933 
02934     //also restore custom properties (for labeling-ng)
02935     readCustomProperties( node, "labeling" );
02936 
02937     // Test if labeling is on or off
02938     QDomNode labelnode = node.namedItem( "label" );
02939     QDomElement element = labelnode.toElement();
02940     int hasLabelsEnabled = element.text().toInt();
02941     if ( hasLabelsEnabled < 1 )
02942     {
02943       enableLabels( false );
02944     }
02945     else
02946     {
02947       enableLabels( true );
02948     }
02949 
02950     QDomNode labelattributesnode = node.namedItem( "labelattributes" );
02951 
02952     if ( !labelattributesnode.isNull() )
02953     {
02954       QgsDebugMsg( "calling readXML" );
02955       mLabel->readXML( labelattributesnode );
02956     }
02957 
02958     //diagram renderer and diagram layer settings
02959     delete mDiagramRenderer; mDiagramRenderer = 0;
02960     QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
02961     if ( !singleCatDiagramElem.isNull() )
02962     {
02963       mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
02964       mDiagramRenderer->readXML( singleCatDiagramElem );
02965     }
02966     QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
02967     if ( !linearDiagramElem.isNull() )
02968     {
02969       mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
02970       mDiagramRenderer->readXML( linearDiagramElem );
02971     }
02972 
02973     if ( mDiagramRenderer )
02974     {
02975       QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
02976       if ( !diagramSettingsElem.isNull() )
02977       {
02978         mDiagramLayerSettings = new QgsDiagramLayerSettings();
02979         mDiagramLayerSettings->readXML( diagramSettingsElem );
02980       }
02981     }
02982   }
02983 
02984   // process the attribute actions
02985   mActions->readXML( node );
02986 
02987   mEditTypes.clear();
02988   QDomNode editTypesNode = node.namedItem( "edittypes" );
02989   if ( !editTypesNode.isNull() )
02990   {
02991     QDomNodeList editTypeNodes = editTypesNode.childNodes();
02992 
02993     for ( int i = 0; i < editTypeNodes.size(); i++ )
02994     {
02995       QDomNode editTypeNode = editTypeNodes.at( i );
02996       QDomElement editTypeElement = editTypeNode.toElement();
02997 
02998       QString name = editTypeElement.attribute( "name" );
02999       if ( fieldNameIndex( name ) < -1 )
03000         continue;
03001 
03002       EditType editType = ( EditType ) editTypeElement.attribute( "type" ).toInt();
03003       mEditTypes.insert( name, editType );
03004 
03005       if ( editType == ValueMap && editTypeNode.hasChildNodes() )
03006       {
03007         mValueMaps.insert( name, QMap<QString, QVariant>() );
03008 
03009         QDomNodeList valueMapNodes = editTypeNode.childNodes();
03010         for ( int j = 0; j < valueMapNodes.size(); j++ )
03011         {
03012           QDomElement value = valueMapNodes.at( j ).toElement();
03013           mValueMaps[ name ].insert( value.attribute( "key" ), value.attribute( "value" ) );
03014         }
03015       }
03016       else if ( editType == EditRange || editType == SliderRange )
03017       {
03018         QVariant min = editTypeElement.attribute( "min" );
03019         QVariant max = editTypeElement.attribute( "max" );
03020         QVariant step = editTypeElement.attribute( "step" );
03021 
03022         mRanges[ name ] = RangeData( min, max, step );
03023       }
03024       else if ( editType == CheckBox )
03025       {
03026         mCheckedStates[ name ] = QPair<QString, QString>( editTypeElement.attribute( "checked" ), editTypeElement.attribute( "unchecked" ) );
03027       }
03028     }
03029   }
03030 
03031   QDomNode editFormNode = node.namedItem( "editform" );
03032   if ( !editFormNode.isNull() )
03033   {
03034     QDomElement e = editFormNode.toElement();
03035     mEditForm = QgsProject::instance()->readPath( e.text() );
03036   }
03037 
03038   QDomNode editFormInitNode = node.namedItem( "editforminit" );
03039   if ( !editFormInitNode.isNull() )
03040   {
03041     mEditFormInit = editFormInitNode.toElement().text();
03042   }
03043 
03044   QDomNode annotationFormNode = node.namedItem( "annotationform" );
03045   if ( !annotationFormNode.isNull() )
03046   {
03047     QDomElement e = annotationFormNode.toElement();
03048     mAnnotationForm = QgsProject::instance()->readPath( e.text() );
03049   }
03050 
03051   mAttributeAliasMap.clear();
03052   QDomNode aliasesNode = node.namedItem( "aliases" );
03053   if ( !aliasesNode.isNull() )
03054   {
03055     QDomElement aliasElem;
03056     QString name;
03057 
03058     QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
03059     for ( int i = 0; i < aliasNodeList.size(); ++i )
03060     {
03061       aliasElem = aliasNodeList.at( i ).toElement();
03062 
03063       QString field;
03064       if ( aliasElem.hasAttribute( "field" ) )
03065       {
03066         field = aliasElem.attribute( "field" );
03067       }
03068       else
03069       {
03070         int index = aliasElem.attribute( "index" ).toInt();
03071 
03072         if ( pendingFields().contains( index ) )
03073           field = pendingFields()[ index ].name();
03074       }
03075 
03076       mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
03077     }
03078   }
03079 
03080   return true;
03081 }
03082 
03083 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
03084 {
03085   QDomElement mapLayerNode = node.toElement();
03086 
03087   if ( hasGeometryType() )
03088   {
03089     if ( mUsingRendererV2 )
03090     {
03091       QDomElement rendererElement = mRendererV2->save( doc );
03092       node.appendChild( rendererElement );
03093     }
03094     else
03095     {
03096       // use scale dependent visibility flag
03097       mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
03098       mapLayerNode.setAttribute( "minLabelScale", mLabel->minScale() );
03099       mapLayerNode.setAttribute( "maxLabelScale", mLabel->maxScale() );
03100 
03101       //classification field(s)
03102       QgsAttributeList attributes = mRenderer->classificationAttributes();
03103       const QgsFieldMap providerFields = mDataProvider->fields();
03104       for ( QgsAttributeList::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
03105       {
03106         QDomElement classificationElement = doc.createElement( "classificationattribute" );
03107         QDomText classificationText = doc.createTextNode( providerFields[*it].name() );
03108         classificationElement.appendChild( classificationText );
03109         node.appendChild( classificationElement );
03110       }
03111 
03112       // renderer settings
03113       const QgsRenderer * myRenderer = renderer();
03114       if ( myRenderer )
03115       {
03116         if ( !myRenderer->writeXML( node, doc, *this ) )
03117         {
03118           errorMessage = tr( "renderer failed to save" );
03119           return false;
03120         }
03121       }
03122       else
03123       {
03124         QgsDebugMsg( "no renderer" );
03125         errorMessage = tr( "no renderer" );
03126         return false;
03127       }
03128     }
03129 
03130     //save customproperties (for labeling ng)
03131     writeCustomProperties( node, doc );
03132 
03133     // add the display field
03134     QDomElement dField  = doc.createElement( "displayfield" );
03135     QDomText dFieldText = doc.createTextNode( displayField() );
03136     dField.appendChild( dFieldText );
03137     node.appendChild( dField );
03138 
03139     // add label node
03140     QDomElement labelElem = doc.createElement( "label" );
03141     QDomText labelText = doc.createTextNode( "" );
03142 
03143     if ( hasLabelsEnabled() )
03144     {
03145       labelText.setData( "1" );
03146     }
03147     else
03148     {
03149       labelText.setData( "0" );
03150     }
03151     labelElem.appendChild( labelText );
03152 
03153     node.appendChild( labelElem );
03154 
03155     // Now we get to do all that all over again for QgsLabel
03156 
03157     QString fieldname = mLabel->labelField( QgsLabel::Text );
03158     if ( fieldname != "" )
03159     {
03160       dField  = doc.createElement( "labelfield" );
03161       dFieldText = doc.createTextNode( fieldname );
03162       dField.appendChild( dFieldText );
03163       node.appendChild( dField );
03164     }
03165 
03166     mLabel->writeXML( node, doc );
03167 
03168     if ( mDiagramRenderer )
03169     {
03170       mDiagramRenderer->writeXML( mapLayerNode, doc );
03171       if ( mDiagramLayerSettings )
03172         mDiagramLayerSettings->writeXML( mapLayerNode, doc );
03173     }
03174   }
03175 
03176   //edit types
03177   if ( mEditTypes.size() > 0 )
03178   {
03179     QDomElement editTypesElement = doc.createElement( "edittypes" );
03180 
03181     for ( QMap<QString, EditType>::const_iterator it = mEditTypes.begin(); it != mEditTypes.end(); ++it )
03182     {
03183       QDomElement editTypeElement = doc.createElement( "edittype" );
03184       editTypeElement.setAttribute( "name", it.key() );
03185       editTypeElement.setAttribute( "type", it.value() );
03186 
03187       switch (( EditType ) it.value() )
03188       {
03189         case ValueMap:
03190           if ( mValueMaps.contains( it.key() ) )
03191           {
03192             const QMap<QString, QVariant> &map = mValueMaps[ it.key()];
03193 
03194             for ( QMap<QString, QVariant>::const_iterator vmit = map.begin(); vmit != map.end(); vmit++ )
03195             {
03196               QDomElement value = doc.createElement( "valuepair" );
03197               value.setAttribute( "key", vmit.key() );
03198               value.setAttribute( "value", vmit.value().toString() );
03199               editTypeElement.appendChild( value );
03200             }
03201           }
03202           break;
03203 
03204         case EditRange:
03205         case SliderRange:
03206         case DialRange:
03207           if ( mRanges.contains( it.key() ) )
03208           {
03209             editTypeElement.setAttribute( "min", mRanges[ it.key()].mMin.toString() );
03210             editTypeElement.setAttribute( "max", mRanges[ it.key()].mMax.toString() );
03211             editTypeElement.setAttribute( "step", mRanges[ it.key()].mStep.toString() );
03212           }
03213           break;
03214 
03215         case CheckBox:
03216           if ( mCheckedStates.contains( it.key() ) )
03217           {
03218             editTypeElement.setAttribute( "checked", mCheckedStates[ it.key()].first );
03219             editTypeElement.setAttribute( "unchecked", mCheckedStates[ it.key()].second );
03220           }
03221           break;
03222 
03223         case LineEdit:
03224         case UniqueValues:
03225         case UniqueValuesEditable:
03226         case Classification:
03227         case FileName:
03228         case Hidden:
03229         case TextEdit:
03230         case Calendar:
03231         case Enumeration:
03232         case Immutable:
03233           break;
03234       }
03235 
03236       editTypesElement.appendChild( editTypeElement );
03237     }
03238 
03239     node.appendChild( editTypesElement );
03240   }
03241 
03242   QDomElement efField  = doc.createElement( "editform" );
03243   QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( mEditForm ) );
03244   efField.appendChild( efText );
03245   node.appendChild( efField );
03246 
03247   QDomElement efiField  = doc.createElement( "editforminit" );
03248   QDomText efiText = doc.createTextNode( mEditFormInit );
03249   efiField.appendChild( efiText );
03250   node.appendChild( efiField );
03251 
03252   QDomElement afField = doc.createElement( "annotationform" );
03253   QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
03254   afField.appendChild( afText );
03255   node.appendChild( afField );
03256 
03257   //attribute aliases
03258   if ( mAttributeAliasMap.size() > 0 )
03259   {
03260     QDomElement aliasElem = doc.createElement( "aliases" );
03261     QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
03262     for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
03263     {
03264       int idx = fieldNameIndex( a_it.key() );
03265       if ( idx < 0 )
03266         continue;
03267 
03268       QDomElement aliasEntryElem = doc.createElement( "alias" );
03269       aliasEntryElem.setAttribute( "field", a_it.key() );
03270       aliasEntryElem.setAttribute( "index", idx );
03271       aliasEntryElem.setAttribute( "name", a_it.value() );
03272       aliasElem.appendChild( aliasEntryElem );
03273     }
03274     node.appendChild( aliasElem );
03275   }
03276 
03277   // add attribute actions
03278   mActions->writeXML( node, doc );
03279 
03280   //save vector overlays (e.g. diagrams)
03281   QList<QgsVectorOverlay*>::const_iterator overlay_it = mOverlays.constBegin();
03282   for ( ; overlay_it != mOverlays.constEnd(); ++overlay_it )
03283   {
03284     if ( *overlay_it )
03285     {
03286       ( *overlay_it )->writeXML( mapLayerNode, doc );
03287     }
03288   }
03289 
03290   return true;
03291 }
03292 
03293 
03294 bool QgsVectorLayer::changeGeometry( int fid, QgsGeometry* geom )
03295 {
03296   if ( !mEditable || !mDataProvider || !hasGeometryType() )
03297   {
03298     return false;
03299   }
03300 
03301   editGeometryChange( fid, *geom );
03302   mCachedGeometries[fid] = *geom;
03303   setModified( true, true );
03304   return true;
03305 }
03306 
03307 
03308 bool QgsVectorLayer::changeAttributeValue( int fid, int field, QVariant value, bool emitSignal )
03309 {
03310   if ( !isEditable() )
03311     return false;
03312 
03313   editAttributeChange( fid, field, value );
03314   setModified( true, false );
03315 
03316   if ( emitSignal )
03317     emit attributeValueChanged( fid, field, value );
03318 
03319   return true;
03320 }
03321 
03322 bool QgsVectorLayer::addAttribute( const QgsField &field )
03323 {
03324   if ( !isEditable() )
03325     return false;
03326 
03327   if ( field.name().isEmpty() )
03328     return false;
03329 
03330   for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
03331   {
03332     if ( it.value().name() == field.name() )
03333       return false;
03334   }
03335 
03336   if ( !mDataProvider->supportedType( field ) )
03337     return false;
03338 
03339   mMaxUpdatedIndex++;
03340 
03341   if ( mActiveCommand != NULL )
03342   {
03343     mActiveCommand->storeAttributeAdd( mMaxUpdatedIndex, field );
03344   }
03345 
03346   mUpdatedFields.insert( mMaxUpdatedIndex, field );
03347   mAddedAttributeIds.insert( mMaxUpdatedIndex );
03348 
03349   setModified( true, false );
03350 
03351   emit attributeAdded( mMaxUpdatedIndex );
03352 
03353   return true;
03354 }
03355 
03356 bool QgsVectorLayer::addAttribute( QString name, QString type )
03357 {
03358   const QList< QgsVectorDataProvider::NativeType > &types = mDataProvider->nativeTypes();
03359 
03360   int i;
03361   for ( i = 0; i < types.size() && types[i].mTypeName != type; i++ )
03362     ;
03363 
03364   return i < types.size() && addAttribute( QgsField( name, types[i].mType, type ) );
03365 }
03366 
03367 void QgsVectorLayer::addAttributeAlias( int attIndex, QString aliasString )
03368 {
03369   if ( !pendingFields().contains( attIndex ) )
03370     return;
03371 
03372   QString name = pendingFields()[ attIndex ].name();
03373 
03374   mAttributeAliasMap.insert( name, aliasString );
03375   emit layerModified( false );
03376 }
03377 
03378 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
03379 {
03380   if ( !pendingFields().contains( attributeIndex ) )
03381     return "";
03382 
03383   QString name = pendingFields()[ attributeIndex ].name();
03384 
03385   return mAttributeAliasMap.value( name, "" );
03386 }
03387 
03388 QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
03389 {
03390   QString displayName = attributeAlias( attributeIndex );
03391   if ( displayName.isEmpty() )
03392   {
03393     const QgsFieldMap& fields = pendingFields();
03394     QgsFieldMap::const_iterator fieldIt = fields.find( attributeIndex );
03395     if ( fieldIt != fields.constEnd() )
03396     {
03397       displayName = fieldIt->name();
03398     }
03399   }
03400   return displayName;
03401 }
03402 
03403 bool QgsVectorLayer::deleteAttribute( int index )
03404 {
03405   if ( !isEditable() )
03406     return false;
03407 
03408   if ( mDeletedAttributeIds.contains( index ) )
03409     return false;
03410 
03411   if ( !mAddedAttributeIds.contains( index ) &&
03412        !mDataProvider->fields().contains( index ) )
03413     return false;
03414 
03415   if ( mActiveCommand != NULL )
03416   {
03417     mActiveCommand->storeAttributeDelete( index, mUpdatedFields[index] );
03418   }
03419 
03420   mDeletedAttributeIds.insert( index );
03421   mAddedAttributeIds.remove( index );
03422   mUpdatedFields.remove( index );
03423 
03424   setModified( true, false );
03425 
03426   emit attributeDeleted( index );
03427 
03428   return true;
03429 }
03430 
03431 bool QgsVectorLayer::deleteFeature( int fid )
03432 {
03433   if ( !isEditable() )
03434     return false;
03435 
03436   if ( mDeletedFeatureIds.contains( fid ) )
03437     return true;
03438 
03439   mSelectedFeatureIds.remove( fid ); // remove it from selection
03440   editFeatureDelete( fid );
03441 
03442   setModified( true, false );
03443 
03444   emit featureDeleted( fid );
03445 
03446   return true;
03447 }
03448 
03449 const QgsFieldMap &QgsVectorLayer::pendingFields() const
03450 {
03451   return mUpdatedFields;
03452 }
03453 
03454 QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
03455 {
03456   return mUpdatedFields.keys();
03457 }
03458 
03459 int QgsVectorLayer::pendingFeatureCount()
03460 {
03461   return mDataProvider->featureCount()
03462          + mAddedFeatures.size()
03463          - mDeletedFeatureIds.size();
03464 }
03465 
03466 bool QgsVectorLayer::commitChanges()
03467 {
03468   bool success = true;
03469 
03470   //clear the cache image so markers don't appear anymore on next draw
03471   setCacheImage( 0 );
03472 
03473   mCommitErrors.clear();
03474 
03475   if ( !mDataProvider )
03476   {
03477     mCommitErrors << tr( "ERROR: no provider" );
03478     return false;
03479   }
03480 
03481   if ( !isEditable() )
03482   {
03483     mCommitErrors << tr( "ERROR: layer not editable" );
03484     return false;
03485   }
03486 
03487   int cap = mDataProvider->capabilities();
03488 
03489   //
03490   // delete attributes
03491   //
03492   bool attributesChanged = false;
03493   if ( mDeletedAttributeIds.size() > 0 )
03494   {
03495     if (( cap & QgsVectorDataProvider::DeleteAttributes ) && mDataProvider->deleteAttributes( mDeletedAttributeIds ) )
03496     {
03497       mCommitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
03498 
03499       emit committedAttributesDeleted( id(), mDeletedAttributeIds );
03500 
03501       mDeletedAttributeIds.clear();
03502       attributesChanged = true;
03503     }
03504     else
03505     {
03506       mCommitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
03507       success = false;
03508     }
03509   }
03510 
03511   //
03512   // add attributes
03513   //
03514   if ( mAddedAttributeIds.size() > 0 )
03515   {
03516     QList<QgsField> addedAttributes;
03517     for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.constBegin(); it != mAddedAttributeIds.constEnd(); it++ )
03518     {
03519       addedAttributes << mUpdatedFields[*it];
03520     }
03521 
03522 
03523     if (( cap & QgsVectorDataProvider::AddAttributes ) && mDataProvider->addAttributes( addedAttributes ) )
03524     {
03525       mCommitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributeIds.size() );
03526 
03527       emit committedAttributesAdded( id(), addedAttributes );
03528 
03529       mAddedAttributeIds.clear();
03530       attributesChanged = true;
03531     }
03532     else
03533     {
03534       mCommitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributeIds.size() );
03535       success = false;
03536     }
03537   }
03538 
03539   //
03540   // remap changed and attributes of added features
03541   //
03542   bool attributeChangesOk = true;
03543   if ( attributesChanged )
03544   {
03545     // map updates field indexes to names
03546     QMap<int, QString> src;
03547     for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
03548     {
03549       src[ it.key()] = it.value().name();
03550     }
03551 
03552     int maxAttrIdx = -1;
03553     const QgsFieldMap &pFields = mDataProvider->fields();
03554 
03555     // map provider table names to field indexes
03556     QMap<QString, int> dst;
03557     for ( QgsFieldMap::const_iterator it = pFields.begin(); it != pFields.end(); it++ )
03558     {
03559       dst[ it.value().name()] = it.key();
03560       if ( it.key() > maxAttrIdx )
03561         maxAttrIdx = it.key();
03562     }
03563 
03564     // if adding attributes failed add fields that are now missing
03565     // (otherwise we'll loose updates when doing the remapping)
03566     if ( mAddedAttributeIds.size() > 0 )
03567     {
03568       for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.constBegin(); it != mAddedAttributeIds.constEnd(); it++ )
03569       {
03570         QString name =  mUpdatedFields[ *it ].name();
03571         if ( dst.contains( name ) )
03572         {
03573           // it's there => so we don't need to add it anymore
03574           mAddedAttributeIds.remove( *it );
03575           mCommitErrors << tr( "SUCCESS: attribute %1 was added." ).arg( name );
03576         }
03577         else
03578         {
03579           // field not there => put it behind the existing attributes
03580           dst[ name ] = ++maxAttrIdx;
03581           attributeChangesOk = false;   // don't try attribute updates - they'll fail.
03582           mCommitErrors << tr( "ERROR: attribute %1 not added" ).arg( name );
03583         }
03584       }
03585     }
03586 
03587     // map updated fields to provider fields
03588     QMap<int, int> remap;
03589     for ( QMap<int, QString>::const_iterator it = src.begin(); it != src.end(); it++ )
03590     {
03591       if ( dst.contains( it.value() ) )
03592       {
03593         remap[ it.key()] = dst[ it.value()];
03594       }
03595     }
03596 
03597     // remap changed attributes
03598     for ( QgsChangedAttributesMap::iterator fit = mChangedAttributeValues.begin(); fit != mChangedAttributeValues.end(); fit++ )
03599     {
03600       QgsAttributeMap &src = fit.value();
03601       QgsAttributeMap dst;
03602 
03603       for ( QgsAttributeMap::const_iterator it = src.begin(); it != src.end(); it++ )
03604       {
03605         if ( remap.contains( it.key() ) )
03606         {
03607           dst[ remap[it.key()] ] = it.value();
03608         }
03609       }
03610       src = dst;
03611     }
03612 
03613     // remap features of added attributes
03614     for ( QgsFeatureList::iterator fit = mAddedFeatures.begin(); fit != mAddedFeatures.end(); fit++ )
03615     {
03616       const QgsAttributeMap &src = fit->attributeMap();
03617       QgsAttributeMap dst;
03618 
03619       for ( QgsAttributeMap::const_iterator it = src.begin(); it != src.end(); it++ )
03620         if ( remap.contains( it.key() ) )
03621           dst[ remap[it.key()] ] = it.value();
03622 
03623       fit->setAttributeMap( dst );
03624     }
03625 
03626     QgsFieldMap attributes;
03627 
03628     // update private field map
03629     for ( QMap<int, int>::iterator it = remap.begin(); it != remap.end(); it++ )
03630       attributes[ it.value()] = mUpdatedFields[ it.key()];
03631 
03632     mUpdatedFields = attributes;
03633   }
03634 
03635   if ( attributeChangesOk )
03636   {
03637     //
03638     // change attributes
03639     //
03640     if ( mChangedAttributeValues.size() > 0 )
03641     {
03642       if (( cap & QgsVectorDataProvider::ChangeAttributeValues ) && mDataProvider->changeAttributeValues( mChangedAttributeValues ) )
03643       {
03644         mCommitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
03645 
03646         emit committedAttributeValuesChanges( id(), mChangedAttributeValues );
03647 
03648         mChangedAttributeValues.clear();
03649       }
03650       else
03651       {
03652         mCommitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
03653         success = false;
03654       }
03655     }
03656 
03657     //
03658     //  add features
03659     //
03660     if ( mAddedFeatures.size() > 0 )
03661     {
03662       for ( int i = 0; i < mAddedFeatures.size(); i++ )
03663       {
03664         QgsFeature &f = mAddedFeatures[i];
03665 
03666         if ( mDeletedFeatureIds.contains( f.id() ) )
03667         {
03668           mDeletedFeatureIds.remove( f.id() );
03669 
03670           if ( mChangedGeometries.contains( f.id() ) )
03671             mChangedGeometries.remove( f.id() );
03672 
03673           mAddedFeatures.removeAt( i-- );
03674           continue;
03675         }
03676 
03677         if ( mChangedGeometries.contains( f.id() ) )
03678         {
03679           f.setGeometry( mChangedGeometries.take( f.id() ) );
03680         }
03681       }
03682 
03683       if (( cap & QgsVectorDataProvider::AddFeatures ) && mDataProvider->addFeatures( mAddedFeatures ) )
03684       {
03685         mCommitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", mAddedFeatures.size() );
03686 
03687         emit committedFeaturesAdded( id(), mAddedFeatures );
03688 
03689         mAddedFeatures.clear();
03690       }
03691       else
03692       {
03693         mCommitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
03694         success = false;
03695       }
03696     }
03697   }
03698 
03699   //
03700   // update geometries
03701   //
03702   if ( mChangedGeometries.size() > 0 )
03703   {
03704     if (( cap & QgsVectorDataProvider::ChangeGeometries ) && mDataProvider->changeGeometryValues( mChangedGeometries ) )
03705     {
03706       mCommitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
03707 
03708       emit committedGeometriesChanges( id(), mChangedGeometries );
03709 
03710       mChangedGeometries.clear();
03711     }
03712     else
03713     {
03714       mCommitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
03715       success = false;
03716     }
03717   }
03718 
03719   //
03720   // delete features
03721   //
03722   if ( mDeletedFeatureIds.size() > 0 )
03723   {
03724     if (( cap & QgsVectorDataProvider::DeleteFeatures ) && mDataProvider->deleteFeatures( mDeletedFeatureIds ) )
03725     {
03726       mCommitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
03727       for ( QgsFeatureIds::const_iterator it = mDeletedFeatureIds.begin(); it != mDeletedFeatureIds.end(); it++ )
03728       {
03729         mChangedAttributeValues.remove( *it );
03730         mChangedGeometries.remove( *it );
03731       }
03732 
03733       emit committedFeaturesRemoved( id(), mDeletedFeatureIds );
03734 
03735       mDeletedFeatureIds.clear();
03736     }
03737     else
03738     {
03739       mCommitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
03740       success = false;
03741     }
03742   }
03743 
03744   deleteCachedGeometries();
03745 
03746   if ( success )
03747   {
03748     mEditable = false;
03749     setModified( false );
03750     undoStack()->clear();
03751     emit editingStopped();
03752   }
03753 
03754   updateFieldMap();
03755   mDataProvider->updateExtents();
03756   QgsDebugMsg( "result:\n  " + mCommitErrors.join( "\n  " ) );
03757 
03758   return success;
03759 }
03760 
03761 const QStringList &QgsVectorLayer::commitErrors()
03762 {
03763   return mCommitErrors;
03764 }
03765 
03766 bool QgsVectorLayer::rollBack()
03767 {
03768   if ( !isEditable() )
03769   {
03770     return false;
03771   }
03772 
03773   if ( isModified() )
03774   {
03775     while ( undoStack()->canUndo() )
03776     {
03777       undoStack()->undo();
03778     }
03779 
03780     Q_ASSERT( mAddedAttributeIds.isEmpty() );
03781     Q_ASSERT( mDeletedAttributeIds.isEmpty() );
03782     Q_ASSERT( mChangedAttributeValues.isEmpty() );
03783     Q_ASSERT( mChangedGeometries.isEmpty() );
03784     Q_ASSERT( mAddedFeatures.isEmpty() );
03785 
03786     updateFieldMap();
03787   }
03788 
03789   deleteCachedGeometries();
03790 
03791   mEditable = false;
03792   emit editingStopped();
03793 
03794   setModified( false );
03795   // invalidate the cache so the layer updates properly to show its original
03796   // after the rollback
03797   setCacheImage( 0 );
03798   return true;
03799 }
03800 
03801 void QgsVectorLayer::setSelectedFeatures( const QgsFeatureIds& ids )
03802 {
03803   // TODO: check whether features with these ID exist
03804   mSelectedFeatureIds = ids;
03805 
03806   // invalidate cache
03807   setCacheImage( 0 );
03808 
03809   emit selectionChanged();
03810 }
03811 
03812 int QgsVectorLayer::selectedFeatureCount()
03813 {
03814   return mSelectedFeatureIds.size();
03815 }
03816 
03817 const QgsFeatureIds& QgsVectorLayer::selectedFeaturesIds() const
03818 {
03819   return mSelectedFeatureIds;
03820 }
03821 
03822 
03823 QgsFeatureList QgsVectorLayer::selectedFeatures()
03824 {
03825   if ( !mDataProvider )
03826   {
03827     return QgsFeatureList();
03828   }
03829 
03830   QgsFeatureList features;
03831 
03832   QgsAttributeList allAttrs = mDataProvider->attributeIndexes();
03833   mFetchAttributes = pendingAllAttributesList();
03834 
03835   for ( QgsFeatureIds::iterator it = mSelectedFeatureIds.begin(); it != mSelectedFeatureIds.end(); ++it )
03836   {
03837     QgsFeature feat;
03838 
03839     bool selectionIsAddedFeature = false;
03840 
03841     // Check this selected item against the uncommitted added features
03842     for ( QgsFeatureList::iterator iter = mAddedFeatures.begin(); iter != mAddedFeatures.end(); ++iter )
03843     {
03844       if ( *it == iter->id() )
03845       {
03846         feat = QgsFeature( *iter );
03847         selectionIsAddedFeature = true;
03848         break;
03849       }
03850     }
03851 
03852     // if the geometry is not newly added, get it from provider
03853     if ( !selectionIsAddedFeature )
03854     {
03855       mDataProvider->featureAtId( *it, feat, true, allAttrs );
03856     }
03857 
03858     updateFeatureAttributes( feat );
03859     updateFeatureGeometry( feat );
03860 
03861     features << feat;
03862   } // for each selected
03863 
03864   return features;
03865 }
03866 
03867 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
03868 {
03869   if ( !mDataProvider )
03870   {
03871     return false;
03872   }
03873 
03874   if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) )
03875   {
03876     return false;
03877   }
03878 
03879   if ( !isEditable() )
03880   {
03881     return false;
03882   }
03883 
03884   if ( makeSelected )
03885   {
03886     mSelectedFeatureIds.clear();
03887   }
03888 
03889   for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
03890   {
03891     addFeature( *iter );
03892 
03893     if ( makeSelected )
03894     {
03895       mSelectedFeatureIds.insert( iter->id() );
03896     }
03897   }
03898 
03899   updateExtents();
03900 
03901   if ( makeSelected )
03902   {
03903     // invalidate cache
03904     setCacheImage( 0 );
03905 
03906     emit selectionChanged();
03907   }
03908 
03909   return true;
03910 }
03911 
03912 
03913 bool QgsVectorLayer::copySymbologySettings( const QgsMapLayer& other )
03914 {
03915   if ( !hasGeometryType() )
03916     return false;
03917 
03918   const QgsVectorLayer* vl = qobject_cast<const QgsVectorLayer *>( &other );
03919 
03920   // exit if both vectorlayer are the same
03921   if ( this == vl )
03922   {
03923     return false;
03924   }
03925 
03926   if ( !vl )
03927   {
03928     return false;
03929   }
03930   delete mRenderer;
03931 
03932   QgsRenderer* r = vl->mRenderer;
03933   if ( r )
03934   {
03935     mRenderer = r->clone();
03936     return true;
03937   }
03938   else
03939   {
03940     return false;
03941   }
03942 }
03943 
03944 bool QgsVectorLayer::hasCompatibleSymbology( const QgsMapLayer& other ) const
03945 {
03946   // vector layers are symbology compatible if they have the same type, the same sequence of numerical/ non numerical fields and the same field names
03947 
03948   const QgsVectorLayer* otherVectorLayer = qobject_cast<const QgsVectorLayer *>( &other );
03949   if ( otherVectorLayer )
03950   {
03951     if ( otherVectorLayer->type() != type() )
03952     {
03953       return false;
03954     }
03955 
03956     const QgsFieldMap& fieldsThis = mDataProvider->fields();
03957     const QgsFieldMap& fieldsOther = otherVectorLayer ->mDataProvider->fields();
03958 
03959     if ( fieldsThis.size() != fieldsOther.size() )
03960     {
03961       return false;
03962     }
03963 
03964     // TODO: fill two sets with the numerical types for both layers
03965 
03966     uint fieldsThisSize = fieldsThis.size();
03967 
03968     for ( uint i = 0; i < fieldsThisSize; ++i )
03969     {
03970       if ( fieldsThis[i].name() != fieldsOther[i].name() ) // field names need to be the same
03971       {
03972         return false;
03973       }
03974       // TODO: compare types of the fields
03975     }
03976     return true; // layers are symbology compatible if the code reaches this point
03977   }
03978   return false;
03979 }
03980 
03981 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
03982 {
03983   if ( !hasGeometryType() )
03984     return false;
03985 
03986   QMultiMap<double, QgsSnappingResult> snapResults;
03987   int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
03988 
03989   if ( result != 0 )
03990   {
03991     return false;
03992   }
03993 
03994   if ( snapResults.size() < 1 )
03995   {
03996     return false;
03997   }
03998 
03999   QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
04000   point.setX( snap_it.value().snappedVertex.x() );
04001   point.setY( snap_it.value().snappedVertex.y() );
04002   return true;
04003 }
04004 
04005 
04006 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
04007                                      QMultiMap<double, QgsSnappingResult>& snappingResults,
04008                                      QgsSnapper::SnappingType snap_to )
04009 {
04010   if ( !hasGeometryType() )
04011     return 1;
04012 
04013   if ( snappingTolerance <= 0 || !mDataProvider )
04014   {
04015     return 1;
04016   }
04017 
04018   QList<QgsFeature> featureList;
04019   QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
04020                            startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
04021   double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
04022 
04023   int n = 0;
04024   QgsFeature f;
04025 
04026   if ( mCachedGeometriesRect.contains( searchRect ) )
04027   {
04028     QgsGeometryMap::iterator it = mCachedGeometries.begin();
04029     for ( ; it != mCachedGeometries.end() ; ++it )
04030     {
04031       QgsGeometry* g = &( it.value() );
04032       if ( g->boundingBox().intersects( searchRect ) )
04033       {
04034         snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
04035         ++n;
04036       }
04037     }
04038   }
04039   else
04040   {
04041     // snapping outside cached area
04042 
04043     select( QgsAttributeList(), searchRect, true, true );
04044 
04045     while ( nextFeature( f ) )
04046     {
04047       snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
04048       ++n;
04049     }
04050   }
04051 
04052   return n == 0 ? 2 : 0;
04053 }
04054 
04055 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint, int featureId, QgsGeometry* geom, double sqrSnappingTolerance,
04056                                      QMultiMap<double, QgsSnappingResult>& snappingResults, QgsSnapper::SnappingType snap_to ) const
04057 {
04058   if ( !geom )
04059   {
04060     return;
04061   }
04062 
04063   int atVertex, beforeVertex, afterVertex;
04064   double sqrDistVertexSnap, sqrDistSegmentSnap;
04065   QgsPoint snappedPoint;
04066   QgsSnappingResult snappingResultVertex;
04067   QgsSnappingResult snappingResultSegment;
04068 
04069   if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
04070   {
04071     snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
04072     if ( sqrDistVertexSnap < sqrSnappingTolerance )
04073     {
04074       snappingResultVertex.snappedVertex = snappedPoint;
04075       snappingResultVertex.snappedVertexNr = atVertex;
04076       snappingResultVertex.beforeVertexNr = beforeVertex;
04077       if ( beforeVertex != -1 ) // make sure the vertex is valid
04078       {
04079         snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
04080       }
04081       snappingResultVertex.afterVertexNr = afterVertex;
04082       if ( afterVertex != -1 ) // make sure the vertex is valid
04083       {
04084         snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
04085       }
04086       snappingResultVertex.snappedAtGeometry = featureId;
04087       snappingResultVertex.layer = this;
04088       snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
04089       return;
04090     }
04091   }
04092   if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
04093   {
04094     if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
04095     {
04096       sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex );
04097 
04098       if ( sqrDistSegmentSnap < sqrSnappingTolerance )
04099       {
04100         snappingResultSegment.snappedVertex = snappedPoint;
04101         snappingResultSegment.snappedVertexNr = -1;
04102         snappingResultSegment.beforeVertexNr = afterVertex - 1;
04103         snappingResultSegment.afterVertexNr = afterVertex;
04104         snappingResultSegment.snappedAtGeometry = featureId;
04105         snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
04106         snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
04107         snappingResultSegment.layer = this;
04108         snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
04109       }
04110     }
04111   }
04112 
04113 }
04114 
04115 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
04116 {
04117   if ( !hasGeometryType() )
04118     return 1;
04119 
04120   int returnval = 0;
04121   QgsPoint layerPoint;
04122 
04123   QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
04124   for ( ; it != snapResults.constEnd(); ++it )
04125   {
04126     if ( it->snappedVertexNr == -1 ) // segment snap
04127     {
04128       layerPoint = it->snappedVertex;
04129       if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
04130       {
04131         returnval = 3;
04132       }
04133     }
04134   }
04135   return returnval;
04136 }
04137 
04138 int QgsVectorLayer::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
04139 {
04140   if ( list.size() < 1 )
04141   {
04142     return 1;
04143   }
04144 
04145   xmin = std::numeric_limits<double>::max();
04146   xmax = -std::numeric_limits<double>::max();
04147   ymin = std::numeric_limits<double>::max();
04148   ymax = -std::numeric_limits<double>::max();
04149 
04150   for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
04151   {
04152     if ( it->x() < xmin )
04153     {
04154       xmin = it->x();
04155     }
04156     if ( it->x() > xmax )
04157     {
04158       xmax = it->x();
04159     }
04160     if ( it->y() < ymin )
04161     {
04162       ymin = it->y();
04163     }
04164     if ( it->y() > ymax )
04165     {
04166       ymax = it->y();
04167     }
04168   }
04169 
04170   return 0;
04171 }
04172 
04173 QgsVectorLayer::VertexMarkerType QgsVectorLayer::currentVertexMarkerType()
04174 {
04175   QSettings settings;
04176   QString markerTypeString = settings.value( "/qgis/digitizing/marker_style", "Cross" ).toString();
04177   if ( markerTypeString == "Cross" )
04178   {
04179     return QgsVectorLayer::Cross;
04180   }
04181   else if ( markerTypeString == "SemiTransparentCircle" )
04182   {
04183     return QgsVectorLayer::SemiTransparentCircle;
04184   }
04185   else
04186   {
04187     return QgsVectorLayer::NoMarker;
04188   }
04189 }
04190 
04191 int QgsVectorLayer::currentVertexMarkerSize()
04192 {
04193   QSettings settings;
04194   return settings.value( "/qgis/digitizing/marker_size", 3 ).toInt();
04195 }
04196 
04197 void QgsVectorLayer::drawFeature( QgsRenderContext &renderContext,
04198                                   QgsFeature& fet,
04199                                   QImage * marker )
04200 {
04201   QPainter *p = renderContext.painter();
04202   // Only have variables, etc outside the switch() statement that are
04203   // used in all cases of the statement (otherwise they may get
04204   // executed, but never used, in a bit of code where performance is
04205   // critical).
04206   if ( ! fet.isValid() )
04207   {
04208     return;
04209   }
04210 
04211   QgsGeometry* geom = fet.geometry();
04212   if ( !geom )
04213   {
04214     return;
04215   }
04216   unsigned char* feature = geom->asWkb();
04217 
04218   QGis::WkbType wkbType = geom->wkbType();
04219 
04220   switch ( wkbType )
04221   {
04222     case QGis::WKBPoint:
04223     case QGis::WKBPoint25D:
04224     {
04225       double x = *(( double * )( feature + 5 ) );
04226       double y = *(( double * )( feature + 5 + sizeof( double ) ) );
04227 
04228       transformPoint( x, y, &renderContext.mapToPixel(), renderContext.coordinateTransform() );
04229       if ( qAbs( x ) > QgsClipper::MAX_X ||
04230            qAbs( y ) > QgsClipper::MAX_Y )
04231       {
04232         break;
04233       }
04234 
04235       //QPointF pt(x - (marker->width()/2),  y - (marker->height()/2));
04236       QPointF pt( x * renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
04237                   y * renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
04238 
04239       p->save();
04240       //p->scale(markerScaleFactor,markerScaleFactor);
04241       p->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
04242       p->drawImage( pt, *marker );
04243       p->restore();
04244 
04245       break;
04246     }
04247     case QGis::WKBMultiPoint:
04248     case QGis::WKBMultiPoint25D:
04249     {
04250       unsigned char *ptr = feature + 5;
04251       unsigned int nPoints = *(( int* )ptr );
04252       ptr += 4;
04253 
04254       p->save();
04255       //p->scale(markerScaleFactor, markerScaleFactor);
04256       p->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
04257 
04258       for ( register unsigned int i = 0; i < nPoints; ++i )
04259       {
04260         ptr += 5;
04261         double x = *(( double * ) ptr );
04262         ptr += sizeof( double );
04263         double y = *(( double * ) ptr );
04264         ptr += sizeof( double );
04265 
04266         if ( wkbType == QGis::WKBMultiPoint25D ) // ignore Z value
04267           ptr += sizeof( double );
04268 
04269         transformPoint( x, y, &renderContext.mapToPixel(), renderContext.coordinateTransform() );
04270         //QPointF pt(x - (marker->width()/2),  y - (marker->height()/2));
04271         //QPointF pt(x/markerScaleFactor - (marker->width()/2),  y/markerScaleFactor - (marker->height()/2));
04272         QPointF pt( x * renderContext.rasterScaleFactor() - ( marker->width() / 2 ),
04273                     y * renderContext.rasterScaleFactor() - ( marker->height() / 2 ) );
04274         //QPointF pt( x, y );
04275 
04276         // Work around a +/- 32768 limitation on coordinates
04277         if ( qAbs( x ) <= QgsClipper::MAX_X &&
04278              qAbs( y ) <= QgsClipper::MAX_Y )
04279           p->drawImage( pt, *marker );
04280       }
04281       p->restore();
04282 
04283       break;
04284     }
04285     case QGis::WKBLineString:
04286     case QGis::WKBLineString25D:
04287     {
04288       drawLineString( feature, renderContext );
04289       break;
04290     }
04291     case QGis::WKBMultiLineString:
04292     case QGis::WKBMultiLineString25D:
04293     {
04294       unsigned char* ptr = feature + 5;
04295       unsigned int numLineStrings = *(( int* )ptr );
04296       ptr = feature + 9;
04297 
04298       for ( register unsigned int jdx = 0; jdx < numLineStrings; jdx++ )
04299       {
04300         ptr = drawLineString( ptr, renderContext );
04301       }
04302       break;
04303     }
04304     case QGis::WKBPolygon:
04305     case QGis::WKBPolygon25D:
04306     {
04307       drawPolygon( feature, renderContext );
04308       break;
04309     }
04310     case QGis::WKBMultiPolygon:
04311     case QGis::WKBMultiPolygon25D:
04312     {
04313       unsigned char *ptr = feature + 5;
04314       unsigned int numPolygons = *(( int* )ptr );
04315       ptr = feature + 9;
04316       for ( register unsigned int kdx = 0; kdx < numPolygons; kdx++ )
04317         ptr = drawPolygon( ptr, renderContext );
04318       break;
04319     }
04320     default:
04321       QgsDebugMsg( "Unknown WkbType ENCOUNTERED" );
04322       break;
04323   }
04324 }
04325 
04326 
04327 
04328 void QgsVectorLayer::setCoordinateSystem()
04329 {
04330   QgsDebugMsg( "----- Computing Coordinate System" );
04331 
04332   //
04333   // Get the layers project info and set up the QgsCoordinateTransform
04334   // for this layer
04335   //
04336 
04337   // get CRS directly from provider
04338   *mCRS = mDataProvider->crs();
04339 
04340   //QgsCoordinateReferenceSystem provides a mechanism for FORCE a srs to be valid
04341   //which is inolves falling back to system, project or user selected
04342   //defaults if the srs is not properly intialised.
04343   //we only nee to do that if the srs is not alreay valid
04344   if ( !mCRS->isValid() )
04345   {
04346     if ( hasGeometryType() )
04347     {
04348       mCRS->setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
04349       mCRS->validate();
04350     }
04351     else
04352     {
04353       mCRS->createFromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
04354     }
04355   }
04356 }
04357 
04358 // Convenience function to transform the given point
04359 inline void QgsVectorLayer::transformPoint(
04360   double& x, double& y,
04361   const QgsMapToPixel* mtp,
04362   const QgsCoordinateTransform* ct )
04363 {
04364   // transform the point
04365   if ( ct )
04366   {
04367     double z = 0;
04368     ct->transformInPlace( x, y, z );
04369   }
04370 
04371   // transform from projected coordinate system to pixel
04372   // position on map canvas
04373   mtp->transformInPlace( x, y );
04374 }
04375 
04376 inline void QgsVectorLayer::transformPoints(
04377   std::vector<double>& x, std::vector<double>& y, std::vector<double>& z,
04378   QgsRenderContext &renderContext )
04379 {
04380   // transform the point
04381   if ( renderContext.coordinateTransform() )
04382     renderContext.coordinateTransform()->transformInPlace( x, y, z );
04383 
04384   // transform from projected coordinate system to pixel
04385   // position on map canvas
04386   renderContext.mapToPixel().transformInPlace( x, y );
04387 }
04388 
04389 
04390 const QString QgsVectorLayer::displayField() const
04391 {
04392   return mDisplayField;
04393 }
04394 
04395 bool QgsVectorLayer::isEditable() const
04396 {
04397   return ( mEditable && mDataProvider );
04398 }
04399 
04400 bool QgsVectorLayer::isReadOnly() const
04401 {
04402   return mReadOnly;
04403 }
04404 
04405 bool QgsVectorLayer::setReadOnly( bool readonly )
04406 {
04407   // exit if the layer is in editing mode
04408   if ( readonly && mEditable )
04409     return false;
04410 
04411   mReadOnly = readonly;
04412   return true;
04413 }
04414 
04415 bool QgsVectorLayer::isModified() const
04416 {
04417   return mModified;
04418 }
04419 
04420 void QgsVectorLayer::setModified( bool modified, bool onlyGeometry )
04421 {
04422   mModified = modified;
04423   emit layerModified( onlyGeometry );
04424 }
04425 
04426 QgsVectorLayer::EditType QgsVectorLayer::editType( int idx )
04427 {
04428   const QgsFieldMap &fields = pendingFields();
04429   if ( fields.contains( idx ) && mEditTypes.contains( fields[idx].name() ) )
04430     return mEditTypes[ fields[idx].name()];
04431   else
04432     return LineEdit;
04433 }
04434 
04435 void QgsVectorLayer::setEditType( int idx, EditType type )
04436 {
04437   const QgsFieldMap &fields = pendingFields();
04438   if ( fields.contains( idx ) )
04439     mEditTypes[ fields[idx].name()] = type;
04440 }
04441 
04442 QString QgsVectorLayer::editForm()
04443 {
04444   return mEditForm;
04445 }
04446 
04447 void QgsVectorLayer::setEditForm( QString ui )
04448 {
04449   mEditForm = ui;
04450 }
04451 
04452 void QgsVectorLayer::setAnnotationForm( const QString& ui )
04453 {
04454   mAnnotationForm = ui;
04455 }
04456 
04457 QString QgsVectorLayer::editFormInit()
04458 {
04459   return mEditFormInit;
04460 }
04461 
04462 void QgsVectorLayer::setEditFormInit( QString function )
04463 {
04464   mEditFormInit = function;
04465 }
04466 
04467 QMap< QString, QVariant > &QgsVectorLayer::valueMap( int idx )
04468 {
04469   const QgsFieldMap &fields = pendingFields();
04470 
04471   // FIXME: throw an exception!?
04472   if ( !fields.contains( idx ) )
04473   {
04474     QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
04475   }
04476 
04477   if ( !mValueMaps.contains( fields[idx].name() ) )
04478     mValueMaps[ fields[idx].name()] = QMap<QString, QVariant>();
04479 
04480   return mValueMaps[ fields[idx].name()];
04481 }
04482 
04483 QgsVectorLayer::RangeData &QgsVectorLayer::range( int idx )
04484 {
04485   const QgsFieldMap &fields = pendingFields();
04486 
04487   // FIXME: throw an exception!?
04488   if ( fields.contains( idx ) )
04489   {
04490     QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
04491   }
04492 
04493   if ( !mRanges.contains( fields[idx].name() ) )
04494     mRanges[ fields[idx].name()] = RangeData();
04495 
04496   return mRanges[ fields[idx].name()];
04497 }
04498 
04499 void QgsVectorLayer::addOverlay( QgsVectorOverlay* overlay )
04500 {
04501   mOverlays.push_back( overlay );
04502 }
04503 
04504 void QgsVectorLayer::removeOverlay( const QString& typeName )
04505 {
04506   for ( int i = mOverlays.size() - 1; i >= 0; --i )
04507   {
04508     if ( mOverlays.at( i )->typeName() == typeName )
04509     {
04510       mOverlays.removeAt( i );
04511     }
04512   }
04513 }
04514 
04515 void QgsVectorLayer::vectorOverlays( QList<QgsVectorOverlay*>& overlayList )
04516 {
04517   overlayList = mOverlays;
04518 }
04519 
04520 QgsVectorOverlay* QgsVectorLayer::findOverlayByType( const QString& typeName )
04521 {
04522   QList<QgsVectorOverlay*>::iterator it = mOverlays.begin();
04523   for ( ; it != mOverlays.end(); ++it )
04524   {
04525     if (( *it )->typeName() == typeName )
04526     {
04527       return *it;
04528     }
04529   }
04530   return 0; //not found
04531 }
04532 
04533 
04534 QgsFeatureRendererV2* QgsVectorLayer::rendererV2()
04535 {
04536   return mRendererV2;
04537 }
04538 void QgsVectorLayer::setRendererV2( QgsFeatureRendererV2* r )
04539 {
04540   if ( !hasGeometryType() )
04541     return;
04542 
04543   delete mRendererV2;
04544   mRendererV2 = r;
04545 }
04546 bool QgsVectorLayer::isUsingRendererV2()
04547 {
04548   return mUsingRendererV2;
04549 }
04550 void QgsVectorLayer::setUsingRendererV2( bool usingRendererV2 )
04551 {
04552   if ( !hasGeometryType() )
04553     return;
04554 
04555   mUsingRendererV2 = usingRendererV2;
04556 }
04557 
04558 
04559 void QgsVectorLayer::editGeometryChange( int featureId, QgsGeometry& geometry )
04560 {
04561   if ( mActiveCommand != NULL )
04562   {
04563     mActiveCommand->storeGeometryChange( featureId, mChangedGeometries[ featureId ], geometry );
04564   }
04565   mChangedGeometries[ featureId ] = geometry;
04566 }
04567 
04568 
04569 void QgsVectorLayer::editFeatureAdd( QgsFeature& feature )
04570 {
04571   if ( mActiveCommand != NULL )
04572   {
04573     mActiveCommand->storeFeatureAdd( feature );
04574   }
04575   mAddedFeatures.append( feature );
04576 }
04577 
04578 void QgsVectorLayer::editFeatureDelete( int featureId )
04579 {
04580   if ( mActiveCommand != NULL )
04581   {
04582     mActiveCommand->storeFeatureDelete( featureId );
04583   }
04584   mDeletedFeatureIds.insert( featureId );
04585 }
04586 
04587 void QgsVectorLayer::editAttributeChange( int featureId, int field, QVariant value )
04588 {
04589   if ( mActiveCommand != NULL )
04590   {
04591     QVariant original;
04592     bool isFirstChange = true;
04593     if ( featureId < 0 )
04594     {
04595       // work with added feature
04596       for ( int i = 0; i < mAddedFeatures.size(); i++ )
04597       {
04598         if ( mAddedFeatures[i].id() == featureId && mAddedFeatures[i].attributeMap().contains( field ) )
04599         {
04600           original = mAddedFeatures[i].attributeMap()[field];
04601           isFirstChange = false;
04602           break;
04603         }
04604       }
04605     }
04606     else
04607     {
04608       if ( mChangedAttributeValues.contains( featureId ) && mChangedAttributeValues[featureId].contains( field ) )
04609       {
04610         original = mChangedAttributeValues[featureId][field];
04611         isFirstChange = false;
04612       }
04613     }
04614     mActiveCommand->storeAttributeChange( featureId, field, original, value, isFirstChange );
04615   }
04616 
04617   if ( featureId >= 0 )
04618   {
04619     // changed attribute of existing feature
04620     if ( !mChangedAttributeValues.contains( featureId ) )
04621     {
04622       mChangedAttributeValues.insert( featureId, QgsAttributeMap() );
04623     }
04624 
04625     mChangedAttributeValues[featureId].insert( field, value );
04626   }
04627   else
04628   {
04629     // updated added feature
04630     for ( int i = 0; i < mAddedFeatures.size(); i++ )
04631     {
04632       if ( mAddedFeatures[i].id() == featureId )
04633       {
04634         mAddedFeatures[i].changeAttribute( field, value );
04635         break;
04636       }
04637     }
04638   }
04639 }
04640 
04641 void QgsVectorLayer::beginEditCommand( QString text )
04642 {
04643   if ( mActiveCommand == NULL )
04644   {
04645     mActiveCommand = new QgsUndoCommand( this, text );
04646   }
04647 }
04648 
04649 void QgsVectorLayer::endEditCommand()
04650 {
04651   if ( mActiveCommand != NULL )
04652   {
04653     undoStack()->push( mActiveCommand );
04654     mActiveCommand = NULL;
04655   }
04656 
04657 }
04658 
04659 void QgsVectorLayer::destroyEditCommand()
04660 {
04661   if ( mActiveCommand != NULL )
04662   {
04663     undoEditCommand( mActiveCommand );
04664     delete mActiveCommand;
04665     mActiveCommand = NULL;
04666   }
04667 
04668 }
04669 
04670 void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
04671 {
04672   QMap<int, QgsUndoCommand::GeometryChangeEntry>& geometryChange = cmd->mGeometryChange;
04673   QgsFeatureIds& deletedFeatureIdChange = cmd->mDeletedFeatureIdChange;
04674   QgsFeatureList& addedFeatures = cmd->mAddedFeatures;
04675   QMap<int, QgsUndoCommand::AttributeChanges>& attributeChange = cmd->mAttributeChange;
04676   QgsFieldMap& addedAttributes = cmd->mAddedAttributes;
04677   QgsFieldMap& deletedAttributes = cmd->mDeletedAttributes;
04678 
04679 
04680   // geometry changes
04681   QMap<int, QgsUndoCommand::GeometryChangeEntry>::iterator it = geometryChange.begin();
04682   for ( ; it != geometryChange.end(); ++it )
04683   {
04684     if ( it.value().target == NULL )
04685     {
04686       mChangedGeometries.remove( it.key() );
04687     }
04688     else
04689     {
04690       mChangedGeometries[it.key()] = *( it.value().target );
04691     }
04692   }
04693 
04694   // deleted features
04695   QgsFeatureIds::iterator delIt = deletedFeatureIdChange.begin();
04696   for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
04697   {
04698     mDeletedFeatureIds.insert( *delIt );
04699     emit featureDeleted( *delIt );
04700   }
04701 
04702   // added features
04703   QgsFeatureList::iterator addIt = addedFeatures.begin();
04704   for ( ; addIt != addedFeatures.end(); ++addIt )
04705   {
04706     mAddedFeatures.append( *addIt );
04707     emit featureAdded( addIt->id() );
04708   }
04709 
04710   // changed attributes
04711   QMap<int, QgsUndoCommand::AttributeChanges>::iterator attrFeatIt = attributeChange.begin();
04712   for ( ; attrFeatIt != attributeChange.end(); ++attrFeatIt )
04713   {
04714     int fid = attrFeatIt.key();
04715     // for every changed attribute in feature
04716     QMap<int, QgsUndoCommand::AttributeChangeEntry>::iterator  attrChIt = attrFeatIt.value().begin();
04717     for ( ; attrChIt != attrFeatIt.value().end(); ++attrChIt )
04718     {
04719       if ( fid >= 0 )
04720       {
04721         // existing feature
04722         if ( attrChIt.value().target.isNull() )
04723         {
04724           mChangedAttributeValues[fid].remove( attrChIt.key() );
04725           if ( mChangedAttributeValues[fid].isEmpty() )
04726             mChangedAttributeValues.remove( fid );
04727         }
04728         else
04729         {
04730           mChangedAttributeValues[fid][attrChIt.key()] = attrChIt.value().target;
04731         }
04732       }
04733       else
04734       {
04735         // added feature
04736         for ( int i = 0; i < mAddedFeatures.size(); i++ )
04737         {
04738           if ( mAddedFeatures[i].id() == fid )
04739           {
04740             mAddedFeatures[i].changeAttribute( attrChIt.key(), attrChIt.value().target );
04741             break;
04742           }
04743         }
04744       }
04745       emit attributeValueChanged( fid, attrChIt.key(), attrChIt.value().target );
04746     }
04747   }
04748 
04749   // added attributes
04750   QgsFieldMap::iterator attrIt = addedAttributes.begin();
04751   for ( ; attrIt != addedAttributes.end(); ++attrIt )
04752   {
04753     int attrIndex = attrIt.key();
04754     mAddedAttributeIds.insert( attrIndex );
04755     mUpdatedFields.insert( attrIndex, attrIt.value() );
04756     emit attributeAdded( attrIndex );
04757   }
04758 
04759   // deleted attributes
04760   QgsFieldMap::iterator dAttrIt = deletedAttributes.begin();
04761   for ( ; dAttrIt != deletedAttributes.end(); ++dAttrIt )
04762   {
04763     int attrIndex = dAttrIt.key();
04764     mDeletedAttributeIds.insert( attrIndex );
04765     mUpdatedFields.remove( attrIndex );
04766     emit attributeDeleted( attrIndex );
04767   }
04768   setModified( true );
04769 
04770   // it's not ideal to trigger refresh from here
04771   triggerRepaint();
04772 }
04773 
04774 void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
04775 {
04776   QMap<int, QgsUndoCommand::GeometryChangeEntry>& geometryChange = cmd->mGeometryChange;
04777   QgsFeatureIds& deletedFeatureIdChange = cmd->mDeletedFeatureIdChange;
04778   QgsFeatureList& addedFeatures = cmd->mAddedFeatures;
04779   QMap<int, QgsUndoCommand::AttributeChanges>& attributeChange = cmd->mAttributeChange;
04780   QgsFieldMap& addedAttributes = cmd->mAddedAttributes;
04781   QgsFieldMap& deletedAttributes = cmd->mDeletedAttributes;
04782 
04783   // deleted attributes
04784   QgsFieldMap::iterator dAttrIt = deletedAttributes.begin();
04785   for ( ; dAttrIt != deletedAttributes.end(); ++dAttrIt )
04786   {
04787     int attrIndex = dAttrIt.key();
04788     mDeletedAttributeIds.remove( attrIndex );
04789     mUpdatedFields.insert( attrIndex, dAttrIt.value() );
04790     emit attributeAdded( attrIndex );
04791   }
04792 
04793   // added attributes
04794   QgsFieldMap::iterator attrIt = addedAttributes.begin();
04795   for ( ; attrIt != addedAttributes.end(); ++attrIt )
04796   {
04797     int attrIndex = attrIt.key();
04798     mAddedAttributeIds.remove( attrIndex );
04799     mUpdatedFields.remove( attrIndex );
04800     emit attributeDeleted( attrIndex );
04801   }
04802 
04803   // geometry changes
04804   QMap<int, QgsUndoCommand::GeometryChangeEntry>::iterator it = geometryChange.begin();
04805   for ( ; it != geometryChange.end(); ++it )
04806   {
04807     if ( it.value().original == NULL )
04808     {
04809       mChangedGeometries.remove( it.key() );
04810     }
04811     else
04812     {
04813       mChangedGeometries[it.key()] = *( it.value().original );
04814     }
04815   }
04816 
04817   // deleted features
04818   QgsFeatureIds::iterator delIt = deletedFeatureIdChange.begin();
04819   for ( ; delIt != deletedFeatureIdChange.end(); ++delIt )
04820   {
04821     mDeletedFeatureIds.remove( *delIt );
04822     emit featureAdded( *delIt );
04823   }
04824 
04825   // added features
04826   QgsFeatureList::iterator addIt = addedFeatures.begin();
04827   for ( ; addIt != addedFeatures.end(); ++addIt )
04828   {
04829     QgsFeatureList::iterator addedIt = mAddedFeatures.begin();
04830     for ( ; addedIt != mAddedFeatures.end(); ++addedIt )
04831     {
04832       if ( addedIt->id() == addIt->id() )
04833       {
04834         mAddedFeatures.erase( addedIt );
04835         emit featureDeleted( addIt->id() );
04836         break; // feature was found so move to next one
04837       }
04838     }
04839   }
04840 
04841   // updated attributes
04842   QMap<int, QgsUndoCommand::AttributeChanges>::iterator attrFeatIt = attributeChange.begin();
04843   for ( ; attrFeatIt != attributeChange.end(); ++attrFeatIt )
04844   {
04845     int fid = attrFeatIt.key();
04846     QMap<int, QgsUndoCommand::AttributeChangeEntry>::iterator  attrChIt = attrFeatIt.value().begin();
04847     for ( ; attrChIt != attrFeatIt.value().end(); ++attrChIt )
04848     {
04849       if ( fid >= 0 )
04850       {
04851         if ( attrChIt.value().isFirstChange )
04852         {
04853           mChangedAttributeValues[fid].remove( attrChIt.key() );
04854           if ( mChangedAttributeValues[fid].isEmpty() )
04855             mChangedAttributeValues.remove( fid );
04856         }
04857         else
04858         {
04859           mChangedAttributeValues[fid][attrChIt.key()] = attrChIt.value().original;
04860         }
04861       }
04862       else
04863       {
04864         // added feature TODO:
04865         for ( int i = 0; i < mAddedFeatures.size(); i++ )
04866         {
04867           if ( mAddedFeatures[i].id() == fid )
04868           {
04869             mAddedFeatures[i].changeAttribute( attrChIt.key(), attrChIt.value().original );
04870             break;
04871           }
04872         }
04873       }
04874       QVariant original = attrChIt.value().original;
04875       if ( attrChIt.value().isFirstChange )
04876       {
04877         QgsFeature tmp;
04878         mDataProvider->featureAtId( fid, tmp, false, QgsAttributeList() << attrChIt.key() );
04879         original = tmp.attributeMap()[ attrChIt.key()];
04880       }
04881       emit attributeValueChanged( fid, attrChIt.key(), original );
04882     }
04883   }
04884   setModified( true );
04885 
04886   // it's not ideal to trigger refresh from here
04887   triggerRepaint();
04888 }
04889 
04890 void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
04891 {
04892   const QgsFieldMap &fields = pendingFields();
04893   if ( fields.contains( idx ) )
04894     mCheckedStates[ fields[idx].name()] = QPair<QString, QString>( checked, unchecked );
04895 }
04896 
04897 QPair<QString, QString> QgsVectorLayer::checkedState( int idx )
04898 {
04899   const QgsFieldMap &fields = pendingFields();
04900   if ( fields.contains( idx ) && mCheckedStates.contains( fields[idx].name() ) )
04901     return mCheckedStates[ fields[idx].name()];
04902   else
04903     return QPair<QString, QString>( "1", "0" );
04904 }
04905 
04906 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
04907 {
04908   const QgsFieldMap &theFields = pendingFields();
04909 
04910   for ( QgsFieldMap::const_iterator it = theFields.constBegin(); it != theFields.constEnd(); ++it )
04911   {
04912     if ( QString::compare( it->name(), fieldName, Qt::CaseInsensitive ) == 0 )
04913     {
04914       return it.key();
04915     }
04916   }
04917   return -1;
04918 }
04919 
04920 void QgsVectorLayer::addJoin( QgsVectorJoinInfo joinInfo )
04921 {
04922   mJoinBuffer->addJoin( joinInfo );
04923   updateFieldMap();
04924 }
04925 
04926 void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
04927 {
04928   removeJoin( theLayerId );
04929 }
04930 
04931 void QgsVectorLayer::removeJoin( const QString& joinLayerId )
04932 {
04933   mJoinBuffer->removeJoin( joinLayerId );
04934   updateFieldMap();
04935 }
04936 
04937 const QList< QgsVectorJoinInfo >& QgsVectorLayer::vectorJoins() const
04938 {
04939   return mJoinBuffer->vectorJoins();
04940 }
04941 
04942 void QgsVectorLayer::updateFieldMap()
04943 {
04944   //first backup mAddedAttributes
04945   QgsFieldMap bkAddedAttributes;
04946   QgsAttributeIds::const_iterator attIdIt = mAddedAttributeIds.constBegin();
04947   for ( ; attIdIt != mAddedAttributeIds.constEnd(); ++attIdIt )
04948   {
04949     bkAddedAttributes.insert( *attIdIt, mUpdatedFields.value( *attIdIt ) );
04950   }
04951 
04952   mUpdatedFields = QgsFieldMap();
04953   if ( mDataProvider )
04954   {
04955     mUpdatedFields = mDataProvider->fields();
04956   }
04957 
04958   int currentMaxIndex = 0; //maximum index of current layer
04959   if ( !QgsVectorLayerJoinBuffer::maximumIndex( mUpdatedFields, currentMaxIndex ) )
04960   {
04961     return;
04962   }
04963 
04964   mMaxUpdatedIndex = currentMaxIndex;
04965 
04966   //joined fields
04967   if ( mJoinBuffer->containsJoins() )
04968   {
04969     mJoinBuffer->updateFieldMap( mUpdatedFields, mMaxUpdatedIndex );
04970   }
04971 
04972   //insert added attributes after provider fields and joined fields
04973   mAddedAttributeIds.clear();
04974   QgsFieldMap::const_iterator fieldIt = bkAddedAttributes.constBegin();
04975   for ( ; fieldIt != bkAddedAttributes.constEnd(); ++fieldIt )
04976   {
04977     ++mMaxUpdatedIndex;
04978     mUpdatedFields.insert( mMaxUpdatedIndex, fieldIt.value() );
04979     mAddedAttributeIds.insert( mMaxUpdatedIndex );
04980 
04981     //go through the changed attributes map and adapt indices of added attributes
04982     for ( int i = 0; i < mChangedAttributeValues.size(); ++i )
04983     {
04984       updateAttributeMapIndex( mChangedAttributeValues[i], fieldIt.key(), mMaxUpdatedIndex );
04985     }
04986 
04987     //go through added features and adapt attribute maps
04988     QgsFeatureList::iterator featureIt = mAddedFeatures.begin();
04989     for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
04990     {
04991       QgsAttributeMap attMap = featureIt->attributeMap();
04992       updateAttributeMapIndex( attMap, fieldIt.key(), mMaxUpdatedIndex );
04993       featureIt->setAttributeMap( attMap );
04994     }
04995   }
04996 
04997   //remove deleted attributes
04998   QgsAttributeIds::const_iterator deletedIt = mDeletedAttributeIds.constBegin();
04999   for ( ; deletedIt != mDeletedAttributeIds.constEnd(); ++deletedIt )
05000   {
05001     mUpdatedFields.remove( *deletedIt );
05002   }
05003 }
05004 
05005 void QgsVectorLayer::createJoinCaches()
05006 {
05007   if ( mJoinBuffer->containsJoins() )
05008   {
05009     mJoinBuffer->createJoinCaches();
05010   }
05011 }
05012 
05013 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
05014 {
05015   uniqueValues.clear();
05016   if ( !mDataProvider )
05017   {
05018     return;
05019   }
05020 
05021   int maxProviderIndex;
05022   QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), maxProviderIndex );
05023 
05024   if ( index <= maxProviderIndex && !mEditable ) //a provider field
05025   {
05026     return mDataProvider->uniqueValues( index, uniqueValues, limit );
05027   }
05028   else // a joined field?
05029   {
05030     if ( mJoinBuffer )
05031     {
05032       int indexOffset; //offset between layer index and joined provider index
05033       const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
05034       if ( join )
05035       {
05036         QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
05037         if ( vl && vl->dataProvider() )
05038         {
05039           return vl->dataProvider()->uniqueValues( index - indexOffset, uniqueValues, limit );
05040         }
05041       }
05042     }
05043   }
05044 
05045 
05046   //the layer is editable, but in certain cases it can still be avoided going through all features
05047   if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
05048   {
05049     return mDataProvider->uniqueValues( index, uniqueValues, limit );
05050   }
05051 
05052   //we need to go through each feature
05053   QgsAttributeList attList;
05054   attList << index;
05055 
05056   select( attList, QgsRectangle(), false, false );
05057 
05058   QgsFeature f;
05059   QVariant currentValue;
05060   QHash<QString, QVariant> val;
05061   while ( nextFeature( f ) )
05062   {
05063     currentValue = f.attributeMap()[index];
05064     val.insert( currentValue.toString(), currentValue );
05065     if ( limit >= 0 && val.size() >= limit )
05066     {
05067       break;
05068     }
05069   }
05070 
05071   uniqueValues = val.values();
05072 }
05073 
05074 QVariant QgsVectorLayer::minimumValue( int index )
05075 {
05076   if ( !mDataProvider )
05077   {
05078     return QVariant();
05079   }
05080 
05081   int maxProviderIndex;
05082   QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), maxProviderIndex );
05083 
05084   if ( index <= maxProviderIndex && !mEditable ) //a provider field
05085   {
05086     return mDataProvider->minimumValue( index );
05087   }
05088   else // a joined field?
05089   {
05090     int indexOffset; //offset between layer index and joined provider index
05091     const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
05092     if ( join )
05093     {
05094       QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
05095       if ( vl )
05096       {
05097         return vl->minimumValue( index );
05098       }
05099     }
05100   }
05101 
05102   //the layer is editable, but in certain cases it can still be avoided going through all features
05103   if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
05104   {
05105     return mDataProvider->minimumValue( index );
05106   }
05107 
05108   //we need to go through each feature
05109   QgsAttributeList attList;
05110   attList << index;
05111 
05112   select( attList, QgsRectangle(), false, false );
05113 
05114   QgsFeature f;
05115   double minimumValue = std::numeric_limits<double>::max();
05116   double currentValue = 0;
05117   while ( nextFeature( f ) )
05118   {
05119     currentValue = f.attributeMap()[index].toDouble();
05120     if ( currentValue < minimumValue )
05121     {
05122       minimumValue = currentValue;
05123     }
05124   }
05125   return QVariant( minimumValue );
05126 }
05127 
05128 QVariant QgsVectorLayer::maximumValue( int index )
05129 {
05130   if ( !mDataProvider )
05131   {
05132     return QVariant();
05133   }
05134 
05135   int maxProviderIndex;
05136   QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), maxProviderIndex );
05137 
05138   if ( index <= maxProviderIndex && !mEditable ) //a provider field
05139   {
05140     return mDataProvider->maximumValue( index );
05141   }
05142   else // a joined field?
05143   {
05144     int indexOffset; //offset between layer index and joined provider index
05145     const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
05146     if ( join )
05147     {
05148       QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
05149       if ( vl )
05150       {
05151         return vl->maximumValue( index );
05152       }
05153     }
05154   }
05155 
05156   //the layer is editable, but in certain cases it can still be avoided going through all features
05157   if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
05158   {
05159     return mDataProvider->maximumValue( index );
05160   }
05161 
05162   //we need to go through each feature
05163   QgsAttributeList attList;
05164   attList << index;
05165 
05166   select( attList, QgsRectangle(), false, false );
05167 
05168   QgsFeature f;
05169   double maximumValue = -std::numeric_limits<double>::max();
05170   double currentValue = 0;
05171   while ( nextFeature( f ) )
05172   {
05173     currentValue = f.attributeMap()[index].toDouble();
05174     if ( currentValue > maximumValue )
05175     {
05176       maximumValue = currentValue;
05177     }
05178   }
05179   return QVariant( maximumValue );
05180 }
05181 
05182 void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
05183 {
05184   mRendererV2->stopRender( rendererContext );
05185   if ( selRenderer )
05186   {
05187     selRenderer->stopRender( rendererContext );
05188     delete selRenderer;
05189   }
05190 }
05191 
05192 void QgsVectorLayer::updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const
05193 {
05194   QgsAttributeMap::const_iterator it = map.find( oldIndex );
05195   if ( it == map.constEnd() )
05196   {
05197     return;
05198   }
05199 
05200   map.insert( newIndex, it.value() );
05201   map.remove( oldIndex );
05202 }
05203 
05204 void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling )
05205 {
05206   if ( !rendererContext.labelingEngine() )
05207     return;
05208 
05209   QSet<int> attrIndex;
05210   if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
05211   {
05212     QSet<int>::const_iterator attIt = attrIndex.constBegin();
05213     for ( ; attIt != attrIndex.constEnd(); ++attIt )
05214     {
05215       if ( !attributes.contains( *attIt ) )
05216       {
05217         attributes << *attIt;
05218       }
05219     }
05220     labeling = true;
05221   }
05222 
05223   //register diagram layers
05224   if ( mDiagramRenderer && mDiagramLayerSettings )
05225   {
05226     mDiagramLayerSettings->renderer = mDiagramRenderer;
05227     rendererContext.labelingEngine()->addDiagramLayer( this, mDiagramLayerSettings );
05228     //add attributes needed by the diagram renderer
05229     QList<int> att = mDiagramRenderer->diagramAttributes();
05230     QList<int>::const_iterator attIt = att.constBegin();
05231     for ( ; attIt != att.constEnd(); ++attIt )
05232     {
05233       if ( !attributes.contains( *attIt ) )
05234       {
05235         attributes << *attIt;
05236       }
05237     }
05238     //and the ones needed for data defined diagram positions
05239     if ( mDiagramLayerSettings->xPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->xPosColumn ) )
05240     {
05241       attributes << mDiagramLayerSettings->xPosColumn;
05242     }
05243     if ( mDiagramLayerSettings->yPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->yPosColumn ) )
05244     {
05245       attributes << mDiagramLayerSettings->yPosColumn;
05246     }
05247   }
05248 }
05249 
05250 void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings& s )
05251 {
05252   if ( !mDiagramLayerSettings )
05253     mDiagramLayerSettings = new QgsDiagramLayerSettings();
05254   *mDiagramLayerSettings = s;
05255 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines