Quantum GIS API Documentation  master-693a1fe
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 
00024 #include <limits>
00025 
00026 #include <QImage>
00027 #include <QPainter>
00028 #include <QPainterPath>
00029 #include <QPolygonF>
00030 #include <QProgressDialog>
00031 #include <QSettings>
00032 #include <QString>
00033 #include <QDomNode>
00034 #include <QVector>
00035 
00036 #include "qgsvectorlayer.h"
00037 
00038 #include "qgsattributeaction.h"
00039 
00040 #include "qgis.h" //for globals
00041 #include "qgsapplication.h"
00042 #include "qgscoordinatetransform.h"
00043 #include "qgsdatasourceuri.h"
00044 #include "qgsfeature.h"
00045 #include "qgsfeaturerequest.h"
00046 #include "qgsfield.h"
00047 #include "qgsgeometry.h"
00048 #include "qgslabel.h"
00049 #include "qgslogger.h"
00050 #include "qgsmessagelog.h"
00051 #include "qgsmaptopixel.h"
00052 #include "qgspoint.h"
00053 #include "qgsproviderregistry.h"
00054 #include "qgsrectangle.h"
00055 #include "qgsrendercontext.h"
00056 #include "qgscoordinatereferencesystem.h"
00057 #include "qgsvectordataprovider.h"
00058 #include "qgsgeometrycache.h"
00059 #include "qgsvectorlayereditbuffer.h"
00060 #include "qgsvectorlayereditutils.h"
00061 #include "qgsvectorlayerfeatureiterator.h"
00062 #include "qgsvectorlayerjoinbuffer.h"
00063 #include "qgsvectorlayerundocommand.h"
00064 #include "qgsvectoroverlay.h"
00065 #include "qgsmaplayerregistry.h"
00066 #include "qgsclipper.h"
00067 #include "qgsproject.h"
00068 
00069 #include "qgsrendererv2.h"
00070 #include "qgssymbolv2.h"
00071 #include "qgssymbollayerv2.h"
00072 #include "qgssinglesymbolrendererv2.h"
00073 #include "qgsdiagramrendererv2.h"
00074 #include "qgsstylev2.h"
00075 #include "qgssymbologyv2conversion.h"
00076 #include "qgspallabeling.h"
00077 
00078 #ifdef TESTPROVIDERLIB
00079 #include <dlfcn.h>
00080 #endif
00081 
00082 typedef bool saveStyle_t(
00083   const QString& uri,
00084   const QString& qmlStyle,
00085   const QString& sldStyle,
00086   const QString& styleName,
00087   const QString& styleDescription,
00088   const QString& uiFileContent,
00089   bool useAsDefault,
00090   QString& errCause
00091 );
00092 
00093 typedef QString loadStyle_t(
00094   const QString& uri,
00095   QString& errCause
00096 );
00097 
00098 typedef int listStyles_t(
00099   const QString& uri,
00100   QStringList &ids,
00101   QStringList &names,
00102   QStringList &descriptions,
00103   QString& errCause
00104 );
00105 
00106 typedef QString getStyleById_t(
00107   const QString& uri,
00108   QString styleID,
00109   QString& errCause
00110 );
00111 
00112 
00113 QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
00114                                 QString baseName,
00115                                 QString providerKey,
00116                                 bool loadDefaultStyleFlag )
00117     : QgsMapLayer( VectorLayer, baseName, vectorLayerPath )
00118     , mUpdateThreshold( 0 )     // XXX better default value?
00119     , mDataProvider( NULL )
00120     , mProviderKey( providerKey )
00121     , mReadOnly( false )
00122     , mRendererV2( NULL )
00123     , mLabel( 0 )
00124     , mLabelOn( false )
00125     , mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
00126     , mLayerTransparency( 0 )
00127     , mVertexMarkerOnlyForSelection( false )
00128     , mCache( new QgsGeometryCache( this ) )
00129     , mEditBuffer( 0 )
00130     , mJoinBuffer( 0 )
00131     , mDiagramRenderer( 0 )
00132     , mDiagramLayerSettings( 0 )
00133     , mValidExtent( false )
00134     , mSymbolFeatureCounted( false )
00135     , mCurrentRendererContext( 0 )
00136 
00137 {
00138   mActions = new QgsAttributeAction( this );
00139 
00140   // if we're given a provider type, try to create and bind one to this layer
00141   if ( ! mProviderKey.isEmpty() )
00142   {
00143     setDataProvider( mProviderKey );
00144   }
00145   if ( mValid )
00146   {
00147     // Always set crs
00148     setCoordinateSystem();
00149 
00150     mJoinBuffer = new QgsVectorLayerJoinBuffer();
00151 
00152     updateFields();
00153 
00154     // check if there is a default style / propertysheet defined
00155     // for this layer and if so apply it
00156     bool defaultLoadedFlag = false;
00157     if ( loadDefaultStyleFlag )
00158     {
00159       loadDefaultStyle( defaultLoadedFlag );
00160     }
00161 
00162     // if the default style failed to load or was disabled use some very basic defaults
00163     if ( !defaultLoadedFlag && hasGeometryType() )
00164     {
00165       // add single symbol renderer
00166       setRendererV2( QgsFeatureRendererV2::defaultRenderer( geometryType() ) );
00167     }
00168 
00169     connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
00170 
00171     // Get the update threshold from user settings. We
00172     // do this only on construction to avoid the penality of
00173     // fetching this each time the layer is drawn. If the user
00174     // changes the threshold from the preferences dialog, it will
00175     // have no effect on existing layers
00176     // TODO: load this setting somewhere else [MD]
00177     //QSettings settings;
00178     //mUpdateThreshold = settings.readNumEntry("Map/updateThreshold", 1000);
00179   }
00180 
00181   connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( selectionChanged() ) );
00182 } // QgsVectorLayer ctor
00183 
00184 
00185 
00186 QgsVectorLayer::~QgsVectorLayer()
00187 {
00188   QgsDebugMsg( "entered." );
00189 
00190   emit layerDeleted();
00191 
00192   mValid = false;
00193 
00194   delete mDataProvider;
00195   delete mEditBuffer;
00196   delete mJoinBuffer;
00197   delete mCache;
00198   delete mLabel;
00199   delete mDiagramLayerSettings;
00200 
00201   delete mActions;
00202 
00203   //delete remaining overlays
00204 
00205   QList<QgsVectorOverlay*>::iterator overlayIt = mOverlays.begin();
00206   for ( ; overlayIt != mOverlays.end(); ++overlayIt )
00207   {
00208     delete *overlayIt;
00209   }
00210 }
00211 
00212 QString QgsVectorLayer::storageType() const
00213 {
00214   if ( mDataProvider )
00215   {
00216     return mDataProvider->storageType();
00217   }
00218   return 0;
00219 }
00220 
00221 
00222 QString QgsVectorLayer::capabilitiesString() const
00223 {
00224   if ( mDataProvider )
00225   {
00226     return mDataProvider->capabilitiesString();
00227   }
00228   return 0;
00229 }
00230 
00231 QString QgsVectorLayer::dataComment() const
00232 {
00233   if ( mDataProvider )
00234   {
00235     return mDataProvider->dataComment();
00236   }
00237   return QString();
00238 }
00239 
00240 
00241 QString QgsVectorLayer::providerType() const
00242 {
00243   return mProviderKey;
00244 }
00245 
00249 void QgsVectorLayer::setDisplayField( QString fldName )
00250 {
00251   if ( !hasGeometryType() )
00252     return;
00253 
00254   // If fldName is provided, use it as the display field, otherwise
00255   // determine the field index for the feature column of the identify
00256   // dialog. We look for fields containing "name" first and second for
00257   // fields containing "id". If neither are found, the first field
00258   // is used as the node.
00259   QString idxName = "";
00260   QString idxId = "";
00261 
00262   if ( !fldName.isEmpty() )
00263   {
00264     mDisplayField = fldName;
00265   }
00266   else
00267   {
00268     const QgsFields &fields = pendingFields();
00269     int fieldsSize = fields.size();
00270 
00271     for ( int idx = 0; idx < fields.count(); ++idx )
00272     {
00273       QString fldName = fields[idx].name();
00274       QgsDebugMsg( "Checking field " + fldName + " of " + QString::number( fieldsSize ) + " total" );
00275 
00276       // Check the fields and keep the first one that matches.
00277       // We assume that the user has organized the data with the
00278       // more "interesting" field names first. As such, name should
00279       // be selected before oldname, othername, etc.
00280       if ( fldName.indexOf( "name", false ) > -1 )
00281       {
00282         if ( idxName.isEmpty() )
00283         {
00284           idxName = fldName;
00285         }
00286       }
00287       if ( fldName.indexOf( "descrip", false ) > -1 )
00288       {
00289         if ( idxName.isEmpty() )
00290         {
00291           idxName = fldName;
00292         }
00293       }
00294       if ( fldName.indexOf( "id", false ) > -1 )
00295       {
00296         if ( idxId.isEmpty() )
00297         {
00298           idxId = fldName;
00299         }
00300       }
00301     }
00302 
00303     //if there were no fields in the dbf just return - otherwise qgis segfaults!
00304     if ( fieldsSize == 0 )
00305       return;
00306 
00307     if ( idxName.length() > 0 )
00308     {
00309       mDisplayField = idxName;
00310     }
00311     else
00312     {
00313       if ( idxId.length() > 0 )
00314       {
00315         mDisplayField = idxId;
00316       }
00317       else
00318       {
00319         mDisplayField = fields[0].name();
00320       }
00321     }
00322 
00323   }
00324 }
00325 
00326 // NOTE this is a temporary method added by Tim to prevent label clipping
00327 // which was occurring when labeller was called in the main draw loop
00328 // This method will probably be removed again in the near future!
00329 void QgsVectorLayer::drawLabels( QgsRenderContext& rendererContext )
00330 {
00331   if ( !hasGeometryType() )
00332     return;
00333 
00334   QgsDebugMsg( "Starting draw of labels: " + id() );
00335 
00336   if ( mRendererV2 && mLabelOn &&
00337        ( !mLabel->scaleBasedVisibility() ||
00338          ( mLabel->minScale() <= rendererContext.rendererScale() &&
00339            rendererContext.rendererScale() <= mLabel->maxScale() ) ) )
00340   {
00341     QgsAttributeList attributes;
00342     foreach ( QString attrName, mRendererV2->usedAttributes() )
00343     {
00344       int attrNum = fieldNameIndex( attrName );
00345       attributes.append( attrNum );
00346     }
00347     // make sure the renderer is ready for classification ("symbolForFeature")
00348     mRendererV2->startRender( rendererContext, this );
00349 
00350     // Add fields required for labels
00351     mLabel->addRequiredFields( attributes );
00352 
00353     QgsDebugMsg( "Selecting features based on view extent" );
00354 
00355     int featureCount = 0;
00356 
00357     try
00358     {
00359       // select the records in the extent. The provider sets a spatial filter
00360       // and sets up the selection set for retrieval
00361       QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
00362                                             .setFilterRect( rendererContext.extent() )
00363                                             .setSubsetOfAttributes( attributes ) );
00364 
00365       QgsFeature fet;
00366       while ( fit.nextFeature( fet ) )
00367       {
00368         if ( mRendererV2->willRenderFeature( fet ) )
00369         {
00370           bool sel = mSelectedFeatureIds.contains( fet.id() );
00371           mLabel->renderLabel( rendererContext, fet, sel, 0 );
00372         }
00373         featureCount++;
00374       }
00375     }
00376     catch ( QgsCsException &e )
00377     {
00378       Q_UNUSED( e );
00379       QgsDebugMsg( "Error projecting label locations" );
00380     }
00381 
00382     if ( mRendererV2 )
00383     {
00384       mRendererV2->stopRender( rendererContext );
00385     }
00386 
00387     QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
00388 
00389     // XXX Something in our draw event is triggering an additional draw event when resizing [TE 01/26/06]
00390     // XXX Calling this will begin processing the next draw event causing image havoc and recursion crashes.
00391     //qApp->processEvents();
00392 
00393   }
00394 }
00395 
00396 
00397 
00398 void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling )
00399 {
00400   if ( !hasGeometryType() )
00401     return;
00402 
00403   mCurrentRendererContext = &rendererContext;
00404 
00405   QSettings settings;
00406   bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
00407 
00408 #ifndef Q_WS_MAC
00409   int featureCount = 0;
00410 #endif //Q_WS_MAC
00411 
00412   QgsFeature fet;
00413   while ( fit.nextFeature( fet ) )
00414   {
00415     try
00416     {
00417       if ( !fet.geometry() )
00418         continue; // skip features without geometry
00419 
00420 #ifndef Q_WS_MAC //MH: disable this on Mac for now to avoid problems with resizing
00421 #ifdef Q_WS_X11
00422       if ( !mEnableBackbuffer ) // do not handle events, as we're already inside a paint event
00423       {
00424 #endif // Q_WS_X11
00425         if ( mUpdateThreshold > 0 && 0 == featureCount % mUpdateThreshold )
00426         {
00427           emit screenUpdateRequested();
00428           // emit drawingProgress( featureCount, totalFeatures );
00429           qApp->processEvents();
00430         }
00431         else if ( featureCount % 1000 == 0 )
00432         {
00433           // emit drawingProgress( featureCount, totalFeatures );
00434           qApp->processEvents();
00435         }
00436 #ifdef Q_WS_X11
00437       }
00438 #endif // Q_WS_X11
00439 #endif // Q_WS_MAC
00440 
00441       if ( rendererContext.renderingStopped() )
00442       {
00443         break;
00444       }
00445 
00446       bool sel = mSelectedFeatureIds.contains( fet.id() );
00447       bool drawMarker = ( mEditBuffer && ( !vertexMarkerOnlyForSelection || sel ) );
00448 
00449       // render feature
00450       bool rendered = mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker );
00451 
00452       if ( mEditBuffer )
00453       {
00454         // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
00455         mCache->cacheGeometry( fet.id(), *fet.geometry() );
00456       }
00457 
00458       // labeling - register feature
00459       if ( rendered && rendererContext.labelingEngine() )
00460       {
00461         if ( labeling )
00462         {
00463           rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
00464         }
00465         if ( mDiagramRenderer )
00466         {
00467           rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
00468         }
00469       }
00470     }
00471     catch ( const QgsCsException &cse )
00472     {
00473       Q_UNUSED( cse );
00474       QgsDebugMsg( QString( "Failed to transform a point while drawing a feature with ID '%1'. Ignoring this feature. %2" )
00475                    .arg( fet.id() ).arg( cse.what() ) );
00476     }
00477 #ifndef Q_WS_MAC
00478     ++featureCount;
00479 #endif //Q_WS_MAC
00480   }
00481 
00482   stopRendererV2( rendererContext, NULL );
00483 
00484   mCurrentRendererContext = NULL;
00485 
00486 #ifndef Q_WS_MAC
00487   QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
00488 #endif
00489 }
00490 
00491 void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling )
00492 {
00493   if ( !hasGeometryType() )
00494     return;
00495 
00496   QHash< QgsSymbolV2*, QList<QgsFeature> > features; // key = symbol, value = array of features
00497 
00498   QSettings settings;
00499   bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();
00500 
00501   QgsSingleSymbolRendererV2* selRenderer = NULL;
00502   if ( !mSelectedFeatureIds.isEmpty() )
00503   {
00504     selRenderer = new QgsSingleSymbolRendererV2( QgsSymbolV2::defaultSymbol( geometryType() ) );
00505     selRenderer->symbol()->setColor( rendererContext.selectionColor() );
00506     selRenderer->setVertexMarkerAppearance( currentVertexMarkerType(), currentVertexMarkerSize() );
00507     selRenderer->startRender( rendererContext, this );
00508   }
00509 
00510   // 1. fetch features
00511   QgsFeature fet;
00512 #ifndef Q_WS_MAC
00513   int featureCount = 0;
00514 #endif //Q_WS_MAC
00515   while ( fit.nextFeature( fet ) )
00516   {
00517     if ( !fet.geometry() )
00518       continue; // skip features without geometry
00519 
00520     if ( rendererContext.renderingStopped() )
00521     {
00522       stopRendererV2( rendererContext, selRenderer );
00523       return;
00524     }
00525 #ifndef Q_WS_MAC
00526     if ( featureCount % 1000 == 0 )
00527     {
00528       qApp->processEvents();
00529     }
00530 #endif //Q_WS_MAC
00531     QgsSymbolV2* sym = mRendererV2->symbolForFeature( fet );
00532     if ( !sym )
00533     {
00534       continue;
00535     }
00536 
00537     if ( !features.contains( sym ) )
00538     {
00539       features.insert( sym, QList<QgsFeature>() );
00540     }
00541     features[sym].append( fet );
00542 
00543     if ( mEditBuffer )
00544     {
00545       // Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
00546       mCache->cacheGeometry( fet.id(), *fet.geometry() );
00547     }
00548 
00549     if ( sym && rendererContext.labelingEngine() )
00550     {
00551       if ( labeling )
00552       {
00553         rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
00554       }
00555       if ( mDiagramRenderer )
00556       {
00557         rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
00558       }
00559     }
00560 
00561 #ifndef Q_WS_MAC
00562     ++featureCount;
00563 #endif //Q_WS_MAC
00564   }
00565 
00566   // find out the order
00567   QgsSymbolV2LevelOrder levels;
00568   QgsSymbolV2List symbols = mRendererV2->symbols();
00569   for ( int i = 0; i < symbols.count(); i++ )
00570   {
00571     QgsSymbolV2* sym = symbols[i];
00572     for ( int j = 0; j < sym->symbolLayerCount(); j++ )
00573     {
00574       int level = sym->symbolLayer( j )->renderingPass();
00575       if ( level < 0 || level >= 1000 ) // ignore invalid levels
00576         continue;
00577       QgsSymbolV2LevelItem item( sym, j );
00578       while ( level >= levels.count() ) // append new empty levels
00579         levels.append( QgsSymbolV2Level() );
00580       levels[level].append( item );
00581     }
00582   }
00583 
00584   // 2. draw features in correct order
00585   for ( int l = 0; l < levels.count(); l++ )
00586   {
00587     QgsSymbolV2Level& level = levels[l];
00588     for ( int i = 0; i < level.count(); i++ )
00589     {
00590       QgsSymbolV2LevelItem& item = level[i];
00591       if ( !features.contains( item.symbol() ) )
00592       {
00593         QgsDebugMsg( "level item's symbol not found!" );
00594         continue;
00595       }
00596       int layer = item.layer();
00597       QList<QgsFeature>& lst = features[item.symbol()];
00598       QList<QgsFeature>::iterator fit;
00599 #ifndef Q_WS_MAC
00600       featureCount = 0;
00601 #endif //Q_WS_MAC
00602       for ( fit = lst.begin(); fit != lst.end(); ++fit )
00603       {
00604         if ( rendererContext.renderingStopped() )
00605         {
00606           stopRendererV2( rendererContext, selRenderer );
00607           return;
00608         }
00609 #ifndef Q_WS_MAC
00610         if ( featureCount % 1000 == 0 )
00611         {
00612           qApp->processEvents();
00613         }
00614 #endif //Q_WS_MAC
00615         bool sel = mSelectedFeatureIds.contains( fit->id() );
00616         // maybe vertex markers should be drawn only during the last pass...
00617         bool drawMarker = ( mEditBuffer && ( !vertexMarkerOnlyForSelection || sel ) );
00618 
00619         try
00620         {
00621           mRendererV2->renderFeature( *fit, rendererContext, layer, sel, drawMarker );
00622         }
00623         catch ( const QgsCsException &cse )
00624         {
00625           Q_UNUSED( cse );
00626           QgsDebugMsg( QString( "Failed to transform a point while drawing a feature with ID '%1'. Ignoring this feature. %2" )
00627                        .arg( fet.id() ).arg( cse.what() ) );
00628         }
00629 #ifndef Q_WS_MAC
00630         ++featureCount;
00631 #endif //Q_WS_MAC
00632       }
00633     }
00634   }
00635 
00636   stopRendererV2( rendererContext, selRenderer );
00637 }
00638 
00639 void QgsVectorLayer::reload()
00640 {
00641   if ( mDataProvider )
00642   {
00643     mDataProvider->reloadData();
00644   }
00645 }
00646 
00647 bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
00648 {
00649   if ( !hasGeometryType() )
00650     return true;
00651 
00652   //set update threshold before each draw to make sure the current setting is picked up
00653   QSettings settings;
00654   mUpdateThreshold = settings.value( "Map/updateThreshold", 0 ).toInt();
00655 #ifdef Q_WS_X11
00656   mEnableBackbuffer = settings.value( "/Map/enableBackbuffer", 1 ).toBool();
00657 #endif
00658 
00659   if ( !mRendererV2 )
00660     return false;
00661 
00662   QgsDebugMsg( "rendering v2:\n" + mRendererV2->dump() );
00663 
00664   if ( mEditBuffer )
00665   {
00666     // Destroy all cached geometries and clear the references to them
00667     mCache->deleteCachedGeometries();
00668     mCache->setCachedGeometriesRect( rendererContext.extent() );
00669 
00670     // set editing vertex markers style
00671     mRendererV2->setVertexMarkerAppearance( currentVertexMarkerType(), currentVertexMarkerSize() );
00672   }
00673 
00674   QgsAttributeList attributes;
00675   foreach ( QString attrName, mRendererV2->usedAttributes() )
00676   {
00677     int attrNum = fieldNameIndex( attrName );
00678     attributes.append( attrNum );
00679     QgsDebugMsg( "attrs: " + attrName + " - " + QString::number( attrNum ) );
00680   }
00681 
00682   bool labeling = false;
00683   //register label and diagram layer to the labeling engine
00684   prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
00685 
00686   //do startRender before getFeatures to give renderers the possibility of querying features in the startRender method
00687   mRendererV2->startRender( rendererContext, this );
00688 
00689   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
00690                                         .setFilterRect( rendererContext.extent() )
00691                                         .setSubsetOfAttributes( attributes ) );
00692 
00693   if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels )
00694       && mRendererV2->usingSymbolLevels() )
00695     drawRendererV2Levels( fit, rendererContext, labeling );
00696   else
00697     drawRendererV2( fit, rendererContext, labeling );
00698 
00699   return true;
00700 }
00701 
00702 void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int m )
00703 {
00704   if ( type == QgsVectorLayer::SemiTransparentCircle )
00705   {
00706     p.setPen( QColor( 50, 100, 120, 200 ) );
00707     p.setBrush( QColor( 200, 200, 210, 120 ) );
00708     p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
00709   }
00710   else if ( type == QgsVectorLayer::Cross )
00711   {
00712     p.setPen( QColor( 255, 0, 0 ) );
00713     p.drawLine( x - m, y + m, x + m, y - m );
00714     p.drawLine( x - m, y - m, x + m, y + m );
00715   }
00716 }
00717 
00718 void QgsVectorLayer::select( const QgsFeatureId& fid )
00719 {
00720   mSelectedFeatureIds.insert( fid );
00721 
00722   setCacheImage( 0 );
00723   emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
00724 }
00725 
00726 void QgsVectorLayer::select( const QgsFeatureIds& featureIds )
00727 {
00728   mSelectedFeatureIds.unite( featureIds );
00729 
00730   setCacheImage( 0 );
00731   emit selectionChanged( featureIds, QgsFeatureIds(), false );
00732 }
00733 
00734 void QgsVectorLayer::deselect( const QgsFeatureId fid )
00735 {
00736   mSelectedFeatureIds.remove( fid );
00737 
00738   setCacheImage( 0 );
00739   emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
00740 }
00741 
00742 void QgsVectorLayer::deselect( const QgsFeatureIds& featureIds )
00743 {
00744   mSelectedFeatureIds.subtract( featureIds );
00745 
00746   setCacheImage( 0 );
00747   emit selectionChanged( QgsFeatureIds(), featureIds, false );
00748 }
00749 
00750 void QgsVectorLayer::select( QgsRectangle & rect, bool addToSelection )
00751 {
00752   // normalize the rectangle
00753   rect.normalize();
00754 
00755   //select all the elements
00756   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
00757                                         .setFilterRect( rect )
00758                                         .setFlags( QgsFeatureRequest::ExactIntersect | QgsFeatureRequest::NoGeometry )
00759                                         .setSubsetOfAttributes( QgsAttributeList() ) );
00760 
00761   QgsFeatureIds ids;
00762 
00763   QgsFeature f;
00764   while ( fit.nextFeature( f ) )
00765   {
00766     ids << f.id();
00767   }
00768 
00769   if ( !addToSelection )
00770   {
00771     setSelectedFeatures( mSelectedFeatureIds + ids );
00772   }
00773   else
00774   {
00775     select( ids );
00776   }
00777 }
00778 
00779 void QgsVectorLayer::modifySelection( QgsFeatureIds selectIds, QgsFeatureIds deselectIds )
00780 {
00781   QgsFeatureIds intersectingIds = selectIds & deselectIds;
00782   if ( intersectingIds.count() > 0 )
00783   {
00784     QgsDebugMsg( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." );
00785   }
00786 
00787   mSelectedFeatureIds -= deselectIds;
00788   mSelectedFeatureIds += selectIds;
00789 
00790   emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
00791 }
00792 
00793 void QgsVectorLayer::invertSelection()
00794 {
00795   // copy the ids of selected features to tmp
00796   QgsFeatureIds tmp = mSelectedFeatureIds;
00797 
00798   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
00799                                         .setFlags( QgsFeatureRequest::NoGeometry )
00800                                         .setSubsetOfAttributes( QgsAttributeList() ) );
00801 
00802   QgsFeatureIds ids;
00803 
00804   QgsFeature fet;
00805   while ( fit.nextFeature( fet ) )
00806   {
00807     ids << fet.id();
00808   }
00809 
00810   ids.subtract( mSelectedFeatureIds );
00811 
00812   setSelectedFeatures( ids );
00813 }
00814 
00815 void QgsVectorLayer::invertSelectionInRectangle( QgsRectangle & rect )
00816 {
00817   // normalize the rectangle
00818   rect.normalize();
00819 
00820   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
00821                                         .setFilterRect( rect )
00822                                         .setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect )
00823                                         .setSubsetOfAttributes( QgsAttributeList() ) );
00824 
00825   QgsFeatureIds selectIds;
00826   QgsFeatureIds deselectIds;
00827 
00828   QgsFeature fet;
00829   while ( fit.nextFeature( fet ) )
00830   {
00831     if ( mSelectedFeatureIds.contains( fet.id() ) )
00832     {
00833       deselectIds << fet.id();
00834     }
00835     else
00836     {
00837       selectIds << fet.id();
00838     }
00839   }
00840 
00841   modifySelection( selectIds, deselectIds );
00842 }
00843 
00844 void QgsVectorLayer::removeSelection()
00845 {
00846   if ( mSelectedFeatureIds.size() == 0 )
00847     return;
00848 
00849   setSelectedFeatures( QgsFeatureIds() );
00850 }
00851 
00852 void QgsVectorLayer::triggerRepaint()
00853 {
00854   emit repaintRequested();
00855 }
00856 
00857 QgsVectorDataProvider* QgsVectorLayer::dataProvider()
00858 {
00859   return mDataProvider;
00860 }
00861 
00862 const QgsVectorDataProvider* QgsVectorLayer::dataProvider() const
00863 {
00864   return mDataProvider;
00865 }
00866 
00867 void QgsVectorLayer::setProviderEncoding( const QString& encoding )
00868 {
00869   if ( mDataProvider )
00870   {
00871     mDataProvider->setEncoding( encoding );
00872     updateFields();
00873   }
00874 }
00875 
00876 void QgsVectorLayer::setDiagramRenderer( QgsDiagramRendererV2* r )
00877 {
00878   delete mDiagramRenderer;
00879   mDiagramRenderer = r;
00880 }
00881 
00882 QGis::GeometryType QgsVectorLayer::geometryType() const
00883 {
00884   if ( mDataProvider )
00885   {
00886     int type = mDataProvider->geometryType();
00887     switch ( type )
00888     {
00889       case QGis::WKBPoint:
00890       case QGis::WKBPoint25D:
00891         return QGis::Point;
00892 
00893       case QGis::WKBLineString:
00894       case QGis::WKBLineString25D:
00895         return QGis::Line;
00896 
00897       case QGis::WKBPolygon:
00898       case QGis::WKBPolygon25D:
00899         return QGis::Polygon;
00900 
00901       case QGis::WKBMultiPoint:
00902       case QGis::WKBMultiPoint25D:
00903         return QGis::Point;
00904 
00905       case QGis::WKBMultiLineString:
00906       case QGis::WKBMultiLineString25D:
00907         return QGis::Line;
00908 
00909       case QGis::WKBMultiPolygon:
00910       case QGis::WKBMultiPolygon25D:
00911         return QGis::Polygon;
00912 
00913       case QGis::WKBNoGeometry:
00914         return QGis::NoGeometry;
00915     }
00916     QgsDebugMsg( QString( "Data Provider Geometry type is not recognised, is %1" ).arg( type ) );
00917   }
00918   else
00919   {
00920     QgsDebugMsg( "pointer to mDataProvider is null" );
00921   }
00922 
00923   // We shouldn't get here, and if we have, other things are likely to
00924   // go wrong. Code that uses the type() return value should be
00925   // rewritten to cope with a value of QGis::Unknown. To make this
00926   // need known, the following message is printed every time we get
00927   // here.
00928   QgsDebugMsg( "WARNING: This code should never be reached. Problems may occur..." );
00929 
00930   return QGis::UnknownGeometry;
00931 }
00932 
00933 bool QgsVectorLayer::hasGeometryType() const
00934 {
00935   QGis::GeometryType t = geometryType();
00936   return ( t != QGis::NoGeometry && t != QGis::UnknownGeometry );
00937 }
00938 
00939 QGis::WkbType QgsVectorLayer::wkbType() const
00940 {
00941   return ( QGis::WkbType )( mWkbType );
00942 }
00943 
00944 QgsRectangle QgsVectorLayer::boundingBoxOfSelected()
00945 {
00946   if ( mSelectedFeatureIds.size() == 0 ) //no selected features
00947   {
00948     return QgsRectangle( 0, 0, 0, 0 );
00949   }
00950 
00951   QgsRectangle r, retval;
00952   retval.setMinimal();
00953 
00954   QgsFeature fet;
00955   if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
00956   {
00957     foreach ( QgsFeatureId fid, mSelectedFeatureIds )
00958     {
00959       if ( getFeatures( QgsFeatureRequest()
00960                         .setFilterFid( fid )
00961                         .setSubsetOfAttributes( QgsAttributeList() ) )
00962            .nextFeature( fet ) &&
00963            fet.geometry() )
00964       {
00965         r = fet.geometry()->boundingBox();
00966         retval.combineExtentWith( &r );
00967       }
00968     }
00969   }
00970   else
00971   {
00972     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
00973                                           .setSubsetOfAttributes( QgsAttributeList() ) );
00974 
00975     while ( fit.nextFeature( fet ) )
00976     {
00977       if ( mSelectedFeatureIds.contains( fet.id() ) )
00978       {
00979         if ( fet.geometry() )
00980         {
00981           r = fet.geometry()->boundingBox();
00982           retval.combineExtentWith( &r );
00983         }
00984       }
00985     }
00986   }
00987 
00988   if ( retval.width() == 0.0 || retval.height() == 0.0 )
00989   {
00990     // If all of the features are at the one point, buffer the
00991     // rectangle a bit. If they are all at zero, do something a bit
00992     // more crude.
00993 
00994     if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
00995          retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
00996     {
00997       retval.set( -1.0, -1.0, 1.0, 1.0 );
00998     }
00999   }
01000 
01001   return retval;
01002 }
01003 
01004 long QgsVectorLayer::featureCount() const
01005 {
01006   if ( !mDataProvider )
01007   {
01008     QgsDebugMsg( "invoked with null mDataProvider" );
01009     return 0;
01010   }
01011 
01012   return mDataProvider->featureCount();
01013 }
01014 
01015 long QgsVectorLayer::featureCount( QgsSymbolV2* symbol )
01016 {
01017   if ( !mSymbolFeatureCounted ) return -1;
01018   return mSymbolFeatureCountMap.value( symbol );
01019 }
01020 
01021 bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
01022 {
01023   if ( mSymbolFeatureCounted ) return true;
01024   mSymbolFeatureCountMap.clear();
01025 
01026   if ( !mDataProvider )
01027   {
01028     QgsDebugMsg( "invoked with null mDataProvider" );
01029     return false;
01030   }
01031   if ( !mRendererV2 )
01032   {
01033     QgsDebugMsg( "invoked with null mRendererV2" );
01034     return false;
01035   }
01036 
01037   QgsLegendSymbolList symbolList = mRendererV2->legendSymbolItems();
01038   QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
01039 
01040   for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
01041   {
01042     mSymbolFeatureCountMap.insert( symbolIt->second, 0 );
01043   }
01044 
01045   long nFeatures = pendingFeatureCount();
01046   QProgressDialog progressDialog( tr( "Updating feature count for layer %1" ).arg( name() ), tr( "Abort" ), 0, nFeatures );
01047   progressDialog.setWindowModality( Qt::WindowModal );
01048   int featuresCounted = 0;
01049 
01050   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) );
01051 
01052   // Renderer (rule based) may depend on context scale, with scale is ignored if 0
01053   QgsRenderContext renderContext;
01054   renderContext.setRendererScale( 0 );
01055   mRendererV2->startRender( renderContext, this );
01056 
01057   QgsFeature f;
01058   while ( fit.nextFeature( f ) )
01059   {
01060     QgsSymbolV2List featureSymbolList = mRendererV2->symbolsForFeature( f );
01061     for ( QgsSymbolV2List::iterator symbolIt = featureSymbolList.begin(); symbolIt != featureSymbolList.end(); ++symbolIt )
01062     {
01063       mSymbolFeatureCountMap[*symbolIt] += 1;
01064     }
01065     ++featuresCounted;
01066 
01067     if ( showProgress )
01068     {
01069       if ( featuresCounted % 50 == 0 )
01070       {
01071         if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
01072         {
01073           progressDialog.setMaximum( 0 );
01074         }
01075         progressDialog.setValue( featuresCounted );
01076         if ( progressDialog.wasCanceled() )
01077         {
01078           mSymbolFeatureCountMap.clear();
01079           mRendererV2->stopRender( renderContext );
01080           return false;
01081         }
01082       }
01083     }
01084   }
01085   mRendererV2->stopRender( renderContext );
01086   progressDialog.setValue( nFeatures );
01087   mSymbolFeatureCounted = true;
01088   return true;
01089 }
01090 
01091 void QgsVectorLayer::updateExtents()
01092 {
01093   mValidExtent = false;
01094 }
01095 
01096 void QgsVectorLayer::setExtent( const QgsRectangle &r )
01097 {
01098   QgsMapLayer::setExtent( r );
01099   mValidExtent = true;
01100 }
01101 
01102 QgsRectangle QgsVectorLayer::extent()
01103 {
01104   if ( mValidExtent )
01105     return QgsMapLayer::extent();
01106 
01107   QgsRectangle rect;
01108   rect.setMinimal();
01109 
01110   if ( !hasGeometryType() )
01111     return rect;
01112 
01113   if ( !mDataProvider )
01114   {
01115     QgsDebugMsg( "invoked with null mDataProvider" );
01116   }
01117 
01118   if ( mEditBuffer && mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mChangedGeometries.isEmpty() )
01119   {
01120     mDataProvider->updateExtents();
01121 
01122     // get the extent of the layer from the provider
01123     // but only when there are some features already
01124     if ( mDataProvider->featureCount() != 0 )
01125     {
01126       QgsRectangle r = mDataProvider->extent();
01127       rect.combineExtentWith( &r );
01128     }
01129 
01130     for ( QgsFeatureMap::iterator it = mEditBuffer->mAddedFeatures.begin(); it != mEditBuffer->mAddedFeatures.end(); it++ )
01131     {
01132       QgsRectangle r = it->geometry()->boundingBox();
01133       rect.combineExtentWith( &r );
01134     }
01135   }
01136   else
01137   {
01138     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
01139                                           .setSubsetOfAttributes( QgsAttributeList() ) );
01140 
01141     QgsFeature fet;
01142     while ( fit.nextFeature( fet ) )
01143     {
01144       if ( fet.geometry() )
01145       {
01146         QgsRectangle bb = fet.geometry()->boundingBox();
01147         rect.combineExtentWith( &bb );
01148       }
01149     }
01150   }
01151 
01152   if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
01153   {
01154     // special case when there are no features in provider nor any added
01155     rect = QgsRectangle(); // use rectangle with zero coordinates
01156   }
01157 
01158   setExtent( rect );
01159 
01160   // Send this (hopefully) up the chain to the map canvas
01161   emit recalculateExtents();
01162 
01163   return rect;
01164 }
01165 
01166 QString QgsVectorLayer::subsetString()
01167 {
01168   if ( ! mDataProvider )
01169   {
01170     QgsDebugMsg( "invoked with null mDataProvider" );
01171     return 0;
01172   }
01173   return mDataProvider->subsetString();
01174 }
01175 
01176 bool QgsVectorLayer::setSubsetString( QString subset )
01177 {
01178   if ( ! mDataProvider )
01179   {
01180     QgsDebugMsg( "invoked with null mDataProvider" );
01181     return false;
01182   }
01183 
01184   bool res = mDataProvider->setSubsetString( subset );
01185 
01186   // get the updated data source string from the provider
01187   mDataSource = mDataProvider->dataSourceUri();
01188   updateExtents();
01189 
01190   if ( res )
01191     setCacheImage( 0 );
01192 
01193   return res;
01194 }
01195 
01196 
01197 QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request )
01198 {
01199   if ( !mDataProvider )
01200     return QgsFeatureIterator();
01201 
01202   return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, request ) );
01203 }
01204 
01205 
01206 bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent )
01207 {
01208   Q_UNUSED( alsoUpdateExtent ); // TODO[MD]
01209   if ( !mEditBuffer || !mDataProvider )
01210     return false;
01211 
01212   return mEditBuffer->addFeature( f );
01213 }
01214 
01215 bool QgsVectorLayer::updateFeature( QgsFeature &f )
01216 {
01217   QgsFeatureRequest req;
01218   req.setFilterFid( f.id() );
01219   if ( !f.geometry() )
01220     req.setFlags( QgsFeatureRequest::NoGeometry );
01221   if ( f.attributes().isEmpty() )
01222     req.setSubsetOfAttributes( QgsAttributeList() );
01223 
01224   QgsFeature current;
01225   if ( !getFeatures( req ).nextFeature( current ) )
01226   {
01227     QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( f.id() ) );
01228     return false;
01229   }
01230 
01231   if ( f.geometry() && current.geometry() && f.geometry() != current.geometry() && !f.geometry()->isGeosEqual( *current.geometry() ) )
01232   {
01233     if ( !changeGeometry( f.id(), f.geometry() ) )
01234     {
01235       QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( f.id() ) );
01236       return false;
01237     }
01238   }
01239 
01240   const QgsAttributes &fa = f.attributes();
01241   const QgsAttributes &ca = current.attributes();
01242 
01243   for ( int attr = 0; attr < fa.count(); ++attr )
01244   {
01245     if ( fa[attr] != ca[attr] )
01246     {
01247       if ( !changeAttributeValue( f.id(), attr, fa[attr] ) )
01248       {
01249         QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( f.id() ) );
01250         return false;
01251       }
01252     }
01253   }
01254 
01255   return true;
01256 }
01257 
01258 
01259 bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
01260 {
01261   if ( !mEditBuffer || !mDataProvider )
01262     return false;
01263 
01264   QgsVectorLayerEditUtils utils( this );
01265   return utils.insertVertex( x, y, atFeatureId, beforeVertex );
01266 }
01267 
01268 
01269 bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
01270 {
01271   if ( !mEditBuffer || !mDataProvider )
01272     return false;
01273 
01274   QgsVectorLayerEditUtils utils( this );
01275   return utils.moveVertex( x, y, atFeatureId, atVertex );
01276 }
01277 
01278 
01279 bool QgsVectorLayer::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
01280 {
01281   if ( !mEditBuffer || !mDataProvider )
01282     return false;
01283 
01284   QgsVectorLayerEditUtils utils( this );
01285   return utils.deleteVertex( atFeatureId, atVertex );
01286 }
01287 
01288 
01289 bool QgsVectorLayer::deleteSelectedFeatures()
01290 {
01291   if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
01292   {
01293     return false;
01294   }
01295 
01296   if ( !isEditable() )
01297   {
01298     return false;
01299   }
01300 
01301   if ( mSelectedFeatureIds.size() == 0 )
01302     return true;
01303 
01304   while ( mSelectedFeatureIds.size() > 0 )
01305   {
01306     QgsFeatureId fid = *mSelectedFeatureIds.begin();
01307     deleteFeature( fid );  // removes from selection
01308   }
01309 
01310   // invalidate cache
01311   setCacheImage( 0 );
01312   triggerRepaint();
01313   updateExtents();
01314 
01315   return true;
01316 }
01317 
01318 int QgsVectorLayer::addRing( const QList<QgsPoint>& ring )
01319 {
01320   if ( !mEditBuffer || !mDataProvider )
01321     return 6;
01322 
01323   QgsVectorLayerEditUtils utils( this );
01324   return utils.addRing( ring );
01325 }
01326 
01327 int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
01328 {
01329   if ( !mEditBuffer || !mDataProvider )
01330     return 7;
01331 
01332   //number of selected features must be 1
01333 
01334   if ( mSelectedFeatureIds.size() < 1 )
01335   {
01336     QgsDebugMsg( "Number of selected features <1" );
01337     return 4;
01338   }
01339   else if ( mSelectedFeatureIds.size() > 1 )
01340   {
01341     QgsDebugMsg( "Number of selected features >1" );
01342     return 5;
01343   }
01344 
01345   QgsVectorLayerEditUtils utils( this );
01346   return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
01347 }
01348 
01349 
01350 int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
01351 {
01352   if ( !mEditBuffer || !mDataProvider )
01353     return -1;
01354 
01355   QgsVectorLayerEditUtils utils( this );
01356   return utils.translateFeature( featureId, dx, dy );
01357 }
01358 
01359 int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
01360 {
01361   if ( !mEditBuffer || !mDataProvider )
01362     return -1;
01363 
01364   QgsVectorLayerEditUtils utils( this );
01365   return utils.splitFeatures( splitLine, topologicalEditing );
01366 }
01367 
01368 int QgsVectorLayer::removePolygonIntersections( QgsGeometry* geom, QgsFeatureIds ignoreFeatures )
01369 {
01370   if ( !hasGeometryType() )
01371     return 1;
01372 
01373   int returnValue = 0;
01374 
01375   //first test if geom really has type polygon or multipolygon
01376   if ( geom->type() != QGis::Polygon )
01377   {
01378     return 1;
01379   }
01380 
01381   //get bounding box of geom
01382   QgsRectangle geomBBox = geom->boundingBox();
01383 
01384   //get list of features that intersect this bounding box
01385   QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
01386                                         .setFilterRect( geomBBox )
01387                                         .setFlags( QgsFeatureRequest::ExactIntersect )
01388                                         .setSubsetOfAttributes( QgsAttributeList() ) );
01389 
01390   QgsFeature f;
01391   while ( fit.nextFeature( f ) )
01392   {
01393     if ( ignoreFeatures.contains( f.id() ) )
01394     {
01395       continue;
01396     }
01397 
01398     //call geometry->makeDifference for each feature
01399     QgsGeometry *currentGeom = f.geometry();
01400     if ( currentGeom )
01401     {
01402       if ( geom->makeDifference( currentGeom ) != 0 )
01403       {
01404         returnValue = 2;
01405       }
01406     }
01407   }
01408 
01409   return returnValue;
01410 }
01411 
01412 int QgsVectorLayer::addTopologicalPoints( QgsGeometry* geom )
01413 {
01414   if ( !mEditBuffer || !mDataProvider )
01415     return -1;
01416 
01417   QgsVectorLayerEditUtils utils( this );
01418   return utils.addTopologicalPoints( geom );
01419 }
01420 
01421 int QgsVectorLayer::addTopologicalPoints( const QgsPoint& p )
01422 {
01423   if ( !mEditBuffer || !mDataProvider )
01424     return -1;
01425 
01426   QgsVectorLayerEditUtils utils( this );
01427   return utils.addTopologicalPoints( p );
01428 }
01429 
01430 QgsLabel *QgsVectorLayer::label()
01431 {
01432   return mLabel;
01433 }
01434 
01435 const QgsLabel *QgsVectorLayer::label() const
01436 {
01437   return mLabel;
01438 }
01439 
01440 void QgsVectorLayer::enableLabels( bool on )
01441 {
01442   mLabelOn = on;
01443 }
01444 
01445 bool QgsVectorLayer::hasLabelsEnabled( void ) const
01446 {
01447   return mLabelOn;
01448 }
01449 
01450 bool QgsVectorLayer::startEditing()
01451 {
01452   if ( !mDataProvider )
01453   {
01454     return false;
01455   }
01456 
01457   // allow editing if provider supports any of the capabilities
01458   if ( !( mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities ) )
01459   {
01460     return false;
01461   }
01462 
01463   if ( mReadOnly )
01464   {
01465     return false;
01466   }
01467 
01468   if ( mEditBuffer )
01469   {
01470     // editing already underway
01471     return false;
01472   }
01473 
01474   mEditBuffer = new QgsVectorLayerEditBuffer( this );
01475   // forward signals
01476   connect( mEditBuffer, SIGNAL( layerModified() ), this, SIGNAL( layerModified() ) ); // TODO[MD]: necessary?
01477   //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
01478   connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( featureAdded( QgsFeatureId ) ) );
01479   connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SIGNAL( featureDeleted( QgsFeatureId ) ) );
01480   connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
01481   connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
01482   connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), this, SIGNAL( attributeAdded( int ) ) );
01483   connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), this, SIGNAL( attributeDeleted( int ) ) );
01484   connect( mEditBuffer, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ), this, SIGNAL( committedFeaturesAdded( QString, QgsFeatureList ) ) );
01485   connect( mEditBuffer, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ), this, SIGNAL( committedFeaturesRemoved( QString, QgsFeatureIds ) ) );
01486 
01487   updateFields();
01488 
01489   emit editingStarted();
01490 
01491   return true;
01492 }
01493 
01494 bool QgsVectorLayer::readXml( const QDomNode& layer_node )
01495 {
01496   QgsDebugMsg( QString( "Datasource in QgsVectorLayer::readXml: " ) + mDataSource.toLocal8Bit().data() );
01497 
01498   //process provider key
01499   QDomNode pkeyNode = layer_node.namedItem( "provider" );
01500 
01501   if ( pkeyNode.isNull() )
01502   {
01503     mProviderKey = "";
01504   }
01505   else
01506   {
01507     QDomElement pkeyElt = pkeyNode.toElement();
01508     mProviderKey = pkeyElt.text();
01509   }
01510 
01511   // determine type of vector layer
01512   if ( ! mProviderKey.isNull() )
01513   {
01514     // if the provider string isn't empty, then we successfully
01515     // got the stored provider
01516   }
01517   else if ( mDataSource.contains( "dbname=" ) )
01518   {
01519     mProviderKey = "postgres";
01520   }
01521   else
01522   {
01523     mProviderKey = "ogr";
01524   }
01525 
01526   if ( ! setDataProvider( mProviderKey ) )
01527   {
01528     return false;
01529   }
01530 
01531   QDomElement pkeyElem = pkeyNode.toElement();
01532   if ( !pkeyElem.isNull() )
01533   {
01534     QString encodingString = pkeyElem.attribute( "encoding" );
01535     if ( !encodingString.isEmpty() )
01536     {
01537       mDataProvider->setEncoding( encodingString );
01538     }
01539   }
01540 
01541   //load vector joins
01542   if ( !mJoinBuffer )
01543   {
01544     mJoinBuffer = new QgsVectorLayerJoinBuffer();
01545   }
01546   mJoinBuffer->readXml( layer_node );
01547 
01548   updateFields();
01549   connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );
01550 
01551   QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );
01552 
01553   if ( prevExpNode.isNull() )
01554   {
01555     mDisplayExpression = "";
01556   }
01557   else
01558   {
01559     QDomElement prevExpElem = prevExpNode.toElement();
01560     mDisplayExpression = prevExpElem.text();
01561   }
01562 
01563   QString errorMsg;
01564   if ( !readSymbology( layer_node, errorMsg ) )
01565   {
01566     return false;
01567   }
01568 
01569   return mValid;               // should be true if read successfully
01570 
01571 } // void QgsVectorLayer::readXml
01572 
01573 
01574 bool QgsVectorLayer::setDataProvider( QString const & provider )
01575 {
01576   // XXX should I check for and possibly delete any pre-existing providers?
01577   // XXX How often will that scenario occur?
01578 
01579   mProviderKey = provider;     // XXX is this necessary?  Usually already set
01580   // XXX when execution gets here.
01581 
01582   //XXX - This was a dynamic cast but that kills the Windows
01583   //      version big-time with an abnormal termination error
01584   mDataProvider =
01585     ( QgsVectorDataProvider* )( QgsProviderRegistry::instance()->provider( provider, mDataSource ) );
01586 
01587   if ( mDataProvider )
01588   {
01589     QgsDebugMsg( "Instantiated the data provider plugin" );
01590 
01591     mValid = mDataProvider->isValid();
01592     if ( mValid )
01593     {
01594 
01595       // TODO: Check if the provider has the capability to send fullExtentCalculated
01596       connect( mDataProvider, SIGNAL( fullExtentCalculated() ), this, SLOT( updateExtents() ) );
01597 
01598       // get the extent
01599       QgsRectangle mbr = mDataProvider->extent();
01600 
01601       // show the extent
01602       QString s = mbr.toString();
01603       QgsDebugMsg( "Extent of layer: " +  s );
01604       // store the extent
01605       setExtent( mbr );
01606 
01607       // get and store the feature type
01608       mWkbType = mDataProvider->geometryType();
01609 
01610       // look at the fields in the layer and set the primary
01611       // display field using some real fuzzy logic
01612       setDisplayField();
01613 
01614       if ( mProviderKey == "postgres" )
01615       {
01616         QgsDebugMsg( "Beautifying layer name " + name() );
01617 
01618         // adjust the display name for postgres layers
01619         QRegExp reg( "\"[^\"]+\"\\.\"([^\"]+)\"( \\([^)]+\\))?" );
01620         if ( reg.indexIn( name() ) >= 0 )
01621         {
01622           QStringList stuff = reg.capturedTexts();
01623           QString lName = stuff[1];
01624 
01625           const QMap<QString, QgsMapLayer*> &layers = QgsMapLayerRegistry::instance()->mapLayers();
01626 
01627           QMap<QString, QgsMapLayer*>::const_iterator it;
01628           for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; it++ )
01629             ;
01630 
01631           if ( it != layers.constEnd() && stuff.size() > 2 )
01632           {
01633             lName += "." + stuff[2].mid( 2, stuff[2].length() - 3 );
01634           }
01635 
01636           if ( !lName.isEmpty() )
01637             setLayerName( lName );
01638         }
01639 
01640         QgsDebugMsg( "Beautified layer name " + name() );
01641 
01642         // deal with unnecessary schema qualification to make v.in.ogr happy
01643         mDataSource = mDataProvider->dataSourceUri();
01644       }
01645       else if ( mProviderKey == "osm" )
01646       {
01647         // make sure that the "observer" has been removed from URI to avoid crashes
01648         mDataSource = mDataProvider->dataSourceUri();
01649       }
01650       else if ( provider == "ogr" )
01651       {
01652         // make sure that the /vsigzip or /vsizip is added to uri, if applicable
01653         mDataSource = mDataProvider->dataSourceUri();
01654         if ( mDataSource.right( 10 ) == "|layerid=0" )
01655           mDataSource.chop( 10 );
01656       }
01657 
01658       // label
01659       mLabel = new QgsLabel( mDataProvider->fields() );
01660       mLabelOn = false;
01661     }
01662     else
01663     {
01664       QgsDebugMsg( "Invalid provider plugin " + QString( mDataSource.toUtf8() ) );
01665       return false;
01666     }
01667   }
01668   else
01669   {
01670     QgsDebugMsg( " unable to get data provider" );
01671     return false;
01672   }
01673 
01674   return true;
01675 
01676 } // QgsVectorLayer:: setDataProvider
01677 
01678 
01679 
01680 
01681 /* virtual */
01682 bool QgsVectorLayer::writeXml( QDomNode & layer_node,
01683                                QDomDocument & document )
01684 {
01685   // first get the layer element so that we can append the type attribute
01686 
01687   QDomElement mapLayerNode = layer_node.toElement();
01688 
01689   if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
01690   {
01691     QgsDebugMsg( "can't find <maplayer>" );
01692     return false;
01693   }
01694 
01695   mapLayerNode.setAttribute( "type", "vector" );
01696 
01697   // set the geometry type
01698   mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );
01699 
01700   // add provider node
01701   if ( mDataProvider )
01702   {
01703     QDomElement provider  = document.createElement( "provider" );
01704     provider.setAttribute( "encoding", mDataProvider->encoding() );
01705     QDomText providerText = document.createTextNode( providerType() );
01706     provider.appendChild( providerText );
01707     layer_node.appendChild( provider );
01708   }
01709 
01710   // save preview expression
01711   QDomElement prevExpElem = document.createElement( "previewExpression" );
01712   QDomText prevExpText = document.createTextNode( mDisplayExpression );
01713   prevExpElem.appendChild( prevExpText );
01714   layer_node.appendChild( prevExpElem );
01715 
01716   //save joins
01717   mJoinBuffer->writeXml( layer_node, document );
01718 
01719   // renderer specific settings
01720   QString errorMsg;
01721   return writeSymbology( layer_node, document, errorMsg );
01722 } // bool QgsVectorLayer::writeXml
01723 
01724 bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage )
01725 {
01726   Q_UNUSED( errorMessage );
01727   if ( hasGeometryType() )
01728   {
01729     // try renderer v2 first
01730     QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
01731     if ( !rendererElement.isNull() )
01732     {
01733       QgsFeatureRendererV2* r = QgsFeatureRendererV2::load( rendererElement );
01734       if ( !r )
01735         return false;
01736 
01737       setRendererV2( r );
01738     }
01739     else
01740     {
01741       QgsFeatureRendererV2* r = QgsSymbologyV2Conversion::readOldRenderer( node, geometryType() );
01742       if ( !r )
01743         r = QgsFeatureRendererV2::defaultRenderer( geometryType() );
01744 
01745       setRendererV2( r );
01746     }
01747 
01748     // get and set the display field if it exists.
01749     QDomNode displayFieldNode = node.namedItem( "displayfield" );
01750     if ( !displayFieldNode.isNull() )
01751     {
01752       QDomElement e = displayFieldNode.toElement();
01753       setDisplayField( e.text() );
01754     }
01755 
01756     // get and set the blend mode if it exists
01757     QDomNode blendModeNode = node.namedItem( "blendMode" );
01758     if ( !blendModeNode.isNull() )
01759     {
01760       QDomElement e = blendModeNode.toElement();
01761       setBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) e.text().toInt() ) );
01762     }
01763 
01764     // get and set the feature blend mode if it exists
01765     QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
01766     if ( !featureBlendModeNode.isNull() )
01767     {
01768       QDomElement e = featureBlendModeNode.toElement();
01769       setFeatureBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) e.text().toInt() ) );
01770     }
01771 
01772     // get and set the layer transparency if it exists
01773     QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
01774     if ( !layerTransparencyNode.isNull() )
01775     {
01776       QDomElement e = layerTransparencyNode.toElement();
01777       setLayerTransparency( e.text().toInt() );
01778     }
01779 
01780     // use scale dependent visibility flag
01781     QDomElement e = node.toElement();
01782     mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
01783     mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() );
01784     mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );
01785 
01786     //also restore custom properties (for labeling-ng)
01787     readCustomProperties( node, "labeling" );
01788 
01789     // Test if labeling is on or off
01790     QDomNode labelnode = node.namedItem( "label" );
01791     QDomElement element = labelnode.toElement();
01792     int hasLabelsEnabled = element.text().toInt();
01793     if ( hasLabelsEnabled < 1 )
01794     {
01795       enableLabels( false );
01796     }
01797     else
01798     {
01799       enableLabels( true );
01800     }
01801 
01802     QDomNode labelattributesnode = node.namedItem( "labelattributes" );
01803 
01804     if ( !labelattributesnode.isNull() )
01805     {
01806       QgsDebugMsg( "calling readXML" );
01807       mLabel->readXML( labelattributesnode );
01808     }
01809 
01810     //diagram renderer and diagram layer settings
01811     delete mDiagramRenderer; mDiagramRenderer = 0;
01812     QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
01813     if ( !singleCatDiagramElem.isNull() )
01814     {
01815       mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
01816       mDiagramRenderer->readXML( singleCatDiagramElem );
01817     }
01818     QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
01819     if ( !linearDiagramElem.isNull() )
01820     {
01821       mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
01822       mDiagramRenderer->readXML( linearDiagramElem );
01823     }
01824 
01825     if ( mDiagramRenderer )
01826     {
01827       QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
01828       if ( !diagramSettingsElem.isNull() )
01829       {
01830         mDiagramLayerSettings = new QgsDiagramLayerSettings();
01831         mDiagramLayerSettings->readXML( diagramSettingsElem );
01832       }
01833     }
01834   }
01835 
01836   // process the attribute actions
01837   mActions->readXML( node );
01838 
01839   mEditTypes.clear();
01840   QDomNode editTypesNode = node.namedItem( "edittypes" );
01841   if ( !editTypesNode.isNull() )
01842   {
01843     QDomNodeList editTypeNodes = editTypesNode.childNodes();
01844 
01845     for ( int i = 0; i < editTypeNodes.size(); i++ )
01846     {
01847       QDomNode editTypeNode = editTypeNodes.at( i );
01848       QDomElement editTypeElement = editTypeNode.toElement();
01849 
01850       QString name = editTypeElement.attribute( "name" );
01851       if ( fieldNameIndex( name ) < -1 )
01852         continue;
01853 
01854       EditType editType = ( EditType ) editTypeElement.attribute( "type" ).toInt();
01855       mEditTypes.insert( name, editType );
01856 
01857       int editable = editTypeElement.attribute( "editable" , "1" ).toInt();
01858       mFieldEditables.insert( name, editable == 1 );
01859 
01860       switch ( editType )
01861       {
01862         case ValueMap:
01863           if ( editTypeNode.hasChildNodes() )
01864           {
01865             mValueMaps.insert( name, QMap<QString, QVariant>() );
01866 
01867             QDomNodeList valueMapNodes = editTypeNode.childNodes();
01868             for ( int j = 0; j < valueMapNodes.size(); j++ )
01869             {
01870               QDomElement value = valueMapNodes.at( j ).toElement();
01871               mValueMaps[ name ].insert( value.attribute( "key" ), value.attribute( "value" ) );
01872             }
01873           }
01874           break;
01875 
01876         case EditRange:
01877         case SliderRange:
01878         case DialRange:
01879         {
01880           QVariant min = editTypeElement.attribute( "min" );
01881           QVariant max = editTypeElement.attribute( "max" );
01882           QVariant step = editTypeElement.attribute( "step" );
01883 
01884           mRanges[ name ] = RangeData( min, max, step );
01885         }
01886         break;
01887 
01888         case CheckBox:
01889           mCheckedStates[ name ] = QPair<QString, QString>( editTypeElement.attribute( "checked" ), editTypeElement.attribute( "unchecked" ) );
01890           break;
01891 
01892         case ValueRelation:
01893         {
01894           QString id = editTypeElement.attribute( "layer" );
01895           QString key = editTypeElement.attribute( "key" );
01896           QString value = editTypeElement.attribute( "value" );
01897           bool allowNull = editTypeElement.attribute( "allowNull" ) == "true";
01898           bool orderByValue = editTypeElement.attribute( "orderByValue" ) == "true";
01899           bool allowMulti = editTypeElement.attribute( "allowMulti", "false" ) == "true";
01900 
01901           QString filterExpression;
01902           if ( editTypeElement.hasAttribute( "filterAttributeColumn" ) &&
01903                editTypeElement.hasAttribute( "filterAttributeValue" ) )
01904           {
01905             filterExpression = QString( "\"%1\"='%2'" )
01906                                .arg( editTypeElement.attribute( "filterAttributeColumn" ) )
01907                                .arg( editTypeElement.attribute( "filterAttributeValue" ) );
01908           }
01909           else
01910           {
01911             filterExpression  = editTypeElement.attribute( "filterExpression", QString::null );
01912           }
01913 
01914           mValueRelations[ name ] = ValueRelationData( id, key, value, allowNull, orderByValue, allowMulti, filterExpression );
01915         }
01916         break;
01917 
01918         case Calendar:
01919           mDateFormats[ name ] = editTypeElement.attribute( "dateFormat" );
01920           break;
01921 
01922         case Photo:
01923           mWidgetSize[ name ] = QSize( editTypeElement.attribute( "widgetWidth" ).toInt(), editTypeElement.attribute( "widgetHeight" ).toInt() );
01924           break;
01925 
01926         case Classification:
01927         case FileName:
01928         case Immutable:
01929         case Hidden:
01930         case LineEdit:
01931         case TextEdit:
01932         case Enumeration:
01933         case UniqueValues:
01934         case UniqueValuesEditable:
01935         case UuidGenerator:
01936         case WebView:
01937         case Color:
01938           break;
01939       }
01940     }
01941   }
01942 
01943   QDomNode editFormNode = node.namedItem( "editform" );
01944   if ( !editFormNode.isNull() )
01945   {
01946     QDomElement e = editFormNode.toElement();
01947     mEditForm = QgsProject::instance()->readPath( e.text() );
01948   }
01949 
01950   QDomNode editFormInitNode = node.namedItem( "editforminit" );
01951   if ( !editFormInitNode.isNull() )
01952   {
01953     mEditFormInit = editFormInitNode.toElement().text();
01954   }
01955 
01956   QDomNode annotationFormNode = node.namedItem( "annotationform" );
01957   if ( !annotationFormNode.isNull() )
01958   {
01959     QDomElement e = annotationFormNode.toElement();
01960     mAnnotationForm = QgsProject::instance()->readPath( e.text() );
01961   }
01962 
01963   mAttributeAliasMap.clear();
01964   QDomNode aliasesNode = node.namedItem( "aliases" );
01965   if ( !aliasesNode.isNull() )
01966   {
01967     QDomElement aliasElem;
01968     QString name;
01969 
01970     QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( "alias" );
01971     for ( int i = 0; i < aliasNodeList.size(); ++i )
01972     {
01973       aliasElem = aliasNodeList.at( i ).toElement();
01974 
01975       QString field;
01976       if ( aliasElem.hasAttribute( "field" ) )
01977       {
01978         field = aliasElem.attribute( "field" );
01979       }
01980       else
01981       {
01982         int index = aliasElem.attribute( "index" ).toInt();
01983 
01984         if ( index >= 0 && index < pendingFields().count() )
01985           field = pendingFields()[ index ].name();
01986       }
01987 
01988       mAttributeAliasMap.insert( field, aliasElem.attribute( "name" ) );
01989     }
01990   }
01991 
01992   // tab display
01993   QDomNode editorLayoutNode = node.namedItem( "editorlayout" );
01994   if ( editorLayoutNode.isNull() )
01995   {
01996     mEditorLayout = GeneratedLayout;
01997   }
01998   else
01999   {
02000     if ( editorLayoutNode.toElement().text() == "uifilelayout" )
02001     {
02002       mEditorLayout = UiFileLayout;
02003     }
02004     else if ( editorLayoutNode.toElement().text() == "tablayout" )
02005     {
02006       mEditorLayout = TabLayout;
02007     }
02008     else
02009     {
02010       mEditorLayout = GeneratedLayout;
02011     }
02012   }
02013 
02014   //Attributes excluded from WMS and WFS
02015   mExcludeAttributesWMS.clear();
02016   QDomNode excludeWMSNode = node.namedItem( "excludeAttributesWMS" );
02017   if ( !excludeWMSNode.isNull() )
02018   {
02019     QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( "attribute" );
02020     for ( int i = 0; i < attributeNodeList.size(); ++i )
02021     {
02022       mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
02023     }
02024   }
02025 
02026   mExcludeAttributesWFS.clear();
02027   QDomNode excludeWFSNode = node.namedItem( "excludeAttributesWFS" );
02028   if ( !excludeWFSNode.isNull() )
02029   {
02030     QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( "attribute" );
02031     for ( int i = 0; i < attributeNodeList.size(); ++i )
02032     {
02033       mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
02034     }
02035   }
02036 
02037   // tabs and groups display info
02038   mAttributeEditorElements.clear();
02039   QDomNode attributeEditorFormNode = node.namedItem( "attributeEditorForm" );
02040   QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
02041 
02042   for ( int i = 0; i < attributeEditorFormNodeList.size(); i++ )
02043   {
02044     QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
02045 
02046     QgsAttributeEditorElement *attributeEditorWidget = attributeEditorElementFromDomElement( elem, this );
02047     mAttributeEditorElements.append( attributeEditorWidget );
02048   }
02049   return true;
02050 }
02051 
02052 QgsAttributeEditorElement* QgsVectorLayer::attributeEditorElementFromDomElement( QDomElement &elem, QObject* parent )
02053 {
02054   QgsAttributeEditorElement* newElement = NULL;
02055 
02056   if ( elem.tagName() == "attributeEditorContainer" )
02057   {
02058     QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( elem.attribute( "name" ), parent );
02059 
02060     QDomNodeList childNodeList = elem.childNodes();
02061 
02062     for ( int i = 0; i < childNodeList.size(); i++ )
02063     {
02064       QDomElement childElem = childNodeList.at( i ).toElement();
02065       QgsAttributeEditorElement* myElem = attributeEditorElementFromDomElement( childElem, container );
02066       container->addChildElement( myElem );
02067     }
02068 
02069     newElement = container;
02070   }
02071   else if ( elem.tagName() == "attributeEditorField" )
02072   {
02073     QString name = elem.attribute( "name" );
02074     int idx = *( dataProvider()->fieldNameMap() ).find( name );
02075     newElement = new QgsAttributeEditorField( name, idx, parent );
02076   }
02077 
02078   return newElement;
02079 }
02080 
02081 bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
02082 {
02083   Q_UNUSED( errorMessage );
02084   QDomElement mapLayerNode = node.toElement();
02085 
02086   if ( hasGeometryType() )
02087   {
02088     QDomElement rendererElement = mRendererV2->save( doc );
02089     node.appendChild( rendererElement );
02090 
02091     // use scale dependent visibility flag
02092     mapLayerNode.setAttribute( "scaleBasedLabelVisibilityFlag", mLabel->scaleBasedVisibility() ? 1 : 0 );
02093     mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) );
02094     mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );
02095 
02096     //save customproperties (for labeling ng)
02097     writeCustomProperties( node, doc );
02098 
02099     // add the blend mode field
02100     QDomElement blendModeElem  = doc.createElement( "blendMode" );
02101     QDomText blendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( blendMode() ) ) );
02102     blendModeElem.appendChild( blendModeText );
02103     node.appendChild( blendModeElem );
02104 
02105     // add the feature blend mode field
02106     QDomElement featureBlendModeElem  = doc.createElement( "featureBlendMode" );
02107     QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( featureBlendMode() ) ) );
02108     featureBlendModeElem.appendChild( featureBlendModeText );
02109     node.appendChild( featureBlendModeElem );
02110 
02111     // add the layer transparency
02112     QDomElement layerTransparencyElem  = doc.createElement( "layerTransparency" );
02113     QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
02114     layerTransparencyElem.appendChild( layerTransparencyText );
02115     node.appendChild( layerTransparencyElem );
02116 
02117     // add the display field
02118     QDomElement dField  = doc.createElement( "displayfield" );
02119     QDomText dFieldText = doc.createTextNode( displayField() );
02120     dField.appendChild( dFieldText );
02121     node.appendChild( dField );
02122 
02123     // add label node
02124     QDomElement labelElem = doc.createElement( "label" );
02125     QDomText labelText = doc.createTextNode( "" );
02126 
02127     if ( hasLabelsEnabled() )
02128     {
02129       labelText.setData( "1" );
02130     }
02131     else
02132     {
02133       labelText.setData( "0" );
02134     }
02135     labelElem.appendChild( labelText );
02136 
02137     node.appendChild( labelElem );
02138 
02139     // Now we get to do all that all over again for QgsLabel
02140 
02141     QString fieldname = mLabel->labelField( QgsLabel::Text );
02142     if ( fieldname != "" )
02143     {
02144       dField  = doc.createElement( "labelfield" );
02145       dFieldText = doc.createTextNode( fieldname );
02146       dField.appendChild( dFieldText );
02147       node.appendChild( dField );
02148     }
02149 
02150     mLabel->writeXML( node, doc );
02151 
02152     if ( mDiagramRenderer )
02153     {
02154       mDiagramRenderer->writeXML( mapLayerNode, doc );
02155       if ( mDiagramLayerSettings )
02156         mDiagramLayerSettings->writeXML( mapLayerNode, doc );
02157     }
02158   }
02159 
02160   //edit types
02161   if ( mEditTypes.size() > 0 )
02162   {
02163     QDomElement editTypesElement = doc.createElement( "edittypes" );
02164 
02165     for ( QMap<QString, EditType>::const_iterator it = mEditTypes.begin(); it != mEditTypes.end(); ++it )
02166     {
02167       QDomElement editTypeElement = doc.createElement( "edittype" );
02168       editTypeElement.setAttribute( "name", it.key() );
02169       editTypeElement.setAttribute( "type", it.value() );
02170       editTypeElement.setAttribute( "editable", mFieldEditables[ it.key()] ? 1 : 0 );
02171 
02172       switch (( EditType ) it.value() )
02173       {
02174         case ValueMap:
02175           if ( mValueMaps.contains( it.key() ) )
02176           {
02177             const QMap<QString, QVariant> &map = mValueMaps[ it.key()];
02178 
02179             for ( QMap<QString, QVariant>::const_iterator vmit = map.begin(); vmit != map.end(); vmit++ )
02180             {
02181               QDomElement value = doc.createElement( "valuepair" );
02182               value.setAttribute( "key", vmit.key() );
02183               value.setAttribute( "value", vmit.value().toString() );
02184               editTypeElement.appendChild( value );
02185             }
02186           }
02187           break;
02188 
02189         case EditRange:
02190         case SliderRange:
02191         case DialRange:
02192           if ( mRanges.contains( it.key() ) )
02193           {
02194             editTypeElement.setAttribute( "min", mRanges[ it.key()].mMin.toString() );
02195             editTypeElement.setAttribute( "max", mRanges[ it.key()].mMax.toString() );
02196             editTypeElement.setAttribute( "step", mRanges[ it.key()].mStep.toString() );
02197           }
02198           break;
02199 
02200         case CheckBox:
02201           if ( mCheckedStates.contains( it.key() ) )
02202           {
02203             editTypeElement.setAttribute( "checked", mCheckedStates[ it.key()].first );
02204             editTypeElement.setAttribute( "unchecked", mCheckedStates[ it.key()].second );
02205           }
02206           break;
02207 
02208         case ValueRelation:
02209           if ( mValueRelations.contains( it.key() ) )
02210           {
02211             const ValueRelationData &data = mValueRelations[ it.key()];
02212             editTypeElement.setAttribute( "layer", data.mLayer );
02213             editTypeElement.setAttribute( "key", data.mKey );
02214             editTypeElement.setAttribute( "value", data.mValue );
02215             editTypeElement.setAttribute( "allowNull", data.mAllowNull ? "true" : "false" );
02216             editTypeElement.setAttribute( "orderByValue", data.mOrderByValue ? "true" : "false" );
02217             editTypeElement.setAttribute( "allowMulti", data.mAllowMulti ? "true" : "false" );
02218             if ( !data.mFilterExpression.isNull() )
02219               editTypeElement.setAttribute( "filterExpression", data.mFilterExpression );
02220           }
02221           break;
02222 
02223         case Calendar:
02224           editTypeElement.setAttribute( "dateFormat", mDateFormats[ it.key()] );
02225           break;
02226 
02227         case Photo:
02228           editTypeElement.setAttribute( "widgetWidth", mWidgetSize[ it.key()].width() );
02229           editTypeElement.setAttribute( "widgetHeight", mWidgetSize[ it.key()].height() );
02230           break;
02231 
02232         case LineEdit:
02233         case UniqueValues:
02234         case UniqueValuesEditable:
02235         case Classification:
02236         case FileName:
02237         case Hidden:
02238         case TextEdit:
02239         case Enumeration:
02240         case Immutable:
02241         case UuidGenerator:
02242         case WebView:
02243         case Color:
02244           break;
02245       }
02246 
02247       editTypesElement.appendChild( editTypeElement );
02248     }
02249 
02250     node.appendChild( editTypesElement );
02251   }
02252 
02253   QDomElement efField  = doc.createElement( "editform" );
02254   QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( mEditForm ) );
02255   efField.appendChild( efText );
02256   node.appendChild( efField );
02257 
02258   QDomElement efiField  = doc.createElement( "editforminit" );
02259   QDomText efiText = doc.createTextNode( mEditFormInit );
02260   efiField.appendChild( efiText );
02261   node.appendChild( efiField );
02262 
02263   QDomElement afField = doc.createElement( "annotationform" );
02264   QDomText afText = doc.createTextNode( QgsProject::instance()->writePath( mAnnotationForm ) );
02265   afField.appendChild( afText );
02266   node.appendChild( afField );
02267 
02268   // tab display
02269   QDomElement editorLayoutElem  = doc.createElement( "editorlayout" );
02270   switch ( mEditorLayout )
02271   {
02272     case UiFileLayout:
02273       editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
02274       break;
02275 
02276     case TabLayout:
02277       editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
02278       break;
02279 
02280     case GeneratedLayout:
02281     default:
02282       editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
02283       break;
02284   }
02285 
02286   node.appendChild( editorLayoutElem );
02287 
02288   //attribute aliases
02289   if ( mAttributeAliasMap.size() > 0 )
02290   {
02291     QDomElement aliasElem = doc.createElement( "aliases" );
02292     QMap<QString, QString>::const_iterator a_it = mAttributeAliasMap.constBegin();
02293     for ( ; a_it != mAttributeAliasMap.constEnd(); ++a_it )
02294     {
02295       int idx = fieldNameIndex( a_it.key() );
02296       if ( idx < 0 )
02297         continue;
02298 
02299       QDomElement aliasEntryElem = doc.createElement( "alias" );
02300       aliasEntryElem.setAttribute( "field", a_it.key() );
02301       aliasEntryElem.setAttribute( "index", idx );
02302       aliasEntryElem.setAttribute( "name", a_it.value() );
02303       aliasElem.appendChild( aliasEntryElem );
02304     }
02305     node.appendChild( aliasElem );
02306   }
02307 
02308   //exclude attributes WMS
02309   QDomElement excludeWMSElem = doc.createElement( "excludeAttributesWMS" );
02310   QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
02311   for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
02312   {
02313     QDomElement attrElem = doc.createElement( "attribute" );
02314     QDomText attrText = doc.createTextNode( *attWMSIt );
02315     attrElem.appendChild( attrText );
02316     excludeWMSElem.appendChild( attrElem );
02317   }
02318   node.appendChild( excludeWMSElem );
02319 
02320   //exclude attributes WFS
02321   QDomElement excludeWFSElem = doc.createElement( "excludeAttributesWFS" );
02322   QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
02323   for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
02324   {
02325     QDomElement attrElem = doc.createElement( "attribute" );
02326     QDomText attrText = doc.createTextNode( *attWFSIt );
02327     attrElem.appendChild( attrText );
02328     excludeWFSElem.appendChild( attrElem );
02329   }
02330   node.appendChild( excludeWFSElem );
02331 
02332   // tabs and groups of edit form
02333   if ( mAttributeEditorElements.size() > 0 )
02334   {
02335     QDomElement tabsElem = doc.createElement( "attributeEditorForm" );
02336 
02337     for ( QList< QgsAttributeEditorElement* >::const_iterator it = mAttributeEditorElements.begin(); it != mAttributeEditorElements.end(); it++ )
02338     {
02339       QDomElement attributeEditorWidgetElem = ( *it )->toDomElement( doc );
02340       tabsElem.appendChild( attributeEditorWidgetElem );
02341     }
02342 
02343     node.appendChild( tabsElem );
02344   }
02345 
02346   // add attribute actions
02347   mActions->writeXML( node, doc );
02348 
02349   //save vector overlays (e.g. diagrams)
02350   QList<QgsVectorOverlay*>::const_iterator overlay_it = mOverlays.constBegin();
02351   for ( ; overlay_it != mOverlays.constEnd(); ++overlay_it )
02352   {
02353     if ( *overlay_it )
02354     {
02355       ( *overlay_it )->writeXML( mapLayerNode, doc );
02356     }
02357   }
02358 
02359   return true;
02360 }
02361 
02362 bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
02363 {
02364   // get the Name element
02365   QDomElement nameElem = node.firstChildElement( "Name" );
02366   if ( nameElem.isNull() )
02367   {
02368     errorMessage = "Warning: Name element not found within NamedLayer while it's required.";
02369   }
02370 
02371   if ( hasGeometryType() )
02372   {
02373     QgsFeatureRendererV2* r = QgsFeatureRendererV2::loadSld( node, geometryType(), errorMessage );
02374     if ( !r )
02375       return false;
02376 
02377     setRendererV2( r );
02378   }
02379   return true;
02380 }
02381 
02382 
02383 bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
02384 {
02385   Q_UNUSED( errorMessage );
02386 
02387   // store the Name element
02388   QDomElement nameNode = doc.createElement( "se:Name" );
02389   nameNode.appendChild( doc.createTextNode( name() ) );
02390   node.appendChild( nameNode );
02391 
02392   if ( hasGeometryType() )
02393   {
02394     node.appendChild( mRendererV2->writeSld( doc, *this ) );
02395   }
02396   return true;
02397 }
02398 
02399 
02400 bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry* geom )
02401 {
02402   if ( !mEditBuffer || !mDataProvider )
02403   {
02404     return false;
02405   }
02406 
02407   return mEditBuffer->changeGeometry( fid, geom );
02408 }
02409 
02410 
02411 bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, QVariant value, bool emitSignal )
02412 {
02413   Q_UNUSED( emitSignal ); // TODO[MD] - see also QgsFieldCalculator and #7071
02414   if ( !mEditBuffer || !mDataProvider )
02415     return false;
02416 
02417   return mEditBuffer->changeAttributeValue( fid, field, value );
02418 }
02419 
02420 bool QgsVectorLayer::addAttribute( const QgsField &field )
02421 {
02422   if ( !mEditBuffer || !mDataProvider )
02423     return false;
02424 
02425   return mEditBuffer->addAttribute( field );
02426 }
02427 
02428 void QgsVectorLayer::addAttributeAlias( int attIndex, QString aliasString )
02429 {
02430   if ( attIndex < 0 || attIndex >= pendingFields().count() )
02431     return;
02432 
02433   QString name = pendingFields()[ attIndex ].name();
02434 
02435   mAttributeAliasMap.insert( name, aliasString );
02436   emit layerModified(); // TODO[MD]: should have a different signal?
02437 }
02438 
02439 void QgsVectorLayer::addAttributeEditorWidget( QgsAttributeEditorElement* data )
02440 {
02441   mAttributeEditorElements.append( data );
02442 }
02443 
02444 QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
02445 {
02446   if ( attributeIndex < 0 || attributeIndex >= pendingFields().count() )
02447     return "";
02448 
02449   QString name = pendingFields()[ attributeIndex ].name();
02450 
02451   return mAttributeAliasMap.value( name, "" );
02452 }
02453 
02454 QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
02455 {
02456   QString displayName = attributeAlias( attributeIndex );
02457   if ( displayName.isEmpty() )
02458   {
02459     const QgsFields& fields = pendingFields();
02460     if ( attributeIndex >= 0 && attributeIndex < fields.count() )
02461     {
02462       displayName = fields[attributeIndex].name();
02463     }
02464   }
02465   return displayName;
02466 }
02467 
02468 bool QgsVectorLayer::deleteAttribute( int index )
02469 {
02470   if ( !mEditBuffer || !mDataProvider )
02471     return false;
02472 
02473   return mEditBuffer->deleteAttribute( index );
02474 }
02475 
02476 bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
02477 {
02478   bool deleted = false;
02479 
02480   // Remove multiple occurences of same attribute
02481   attrs = attrs.toSet().toList();
02482 
02483   qSort( attrs.begin(), attrs.end(), qGreater<int>() );
02484 
02485   foreach ( int attr, attrs )
02486   {
02487     if ( deleteAttribute( attr ) )
02488     {
02489       deleted = true;
02490     }
02491   }
02492 
02493   return deleted;
02494 }
02495 
02496 bool QgsVectorLayer::deleteFeature( QgsFeatureId fid )
02497 {
02498   if ( !mEditBuffer )
02499     return false;
02500 
02501   bool res = mEditBuffer->deleteFeature( fid );
02502   if ( res )
02503     mSelectedFeatureIds.remove( fid ); // remove it from selection
02504 
02505   return res;
02506 }
02507 
02508 const QgsFields &QgsVectorLayer::pendingFields() const
02509 {
02510   return mUpdatedFields;
02511 }
02512 
02513 QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
02514 {
02515   QgsAttributeList lst;
02516   for ( int i = 0; i < mUpdatedFields.count(); ++i )
02517     lst.append( i );
02518   return lst;
02519 }
02520 
02521 QgsAttributeList QgsVectorLayer::pendingPkAttributesList()
02522 {
02523   QgsAttributeList pkAttributesList;
02524 
02525   QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
02526   for ( int i = 0; i < mUpdatedFields.count(); ++i )
02527   {
02528     if ( mUpdatedFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
02529          providerIndexes.contains( mUpdatedFields.fieldOriginIndex( i ) ) )
02530       pkAttributesList << i;
02531   }
02532 
02533   return pkAttributesList;
02534 }
02535 
02536 int QgsVectorLayer::pendingFeatureCount()
02537 {
02538   return mDataProvider->featureCount() +
02539          ( mEditBuffer ? mEditBuffer->mAddedFeatures.size() - mEditBuffer->mDeletedFeatureIds.size() : 0 );
02540 }
02541 
02542 bool QgsVectorLayer::commitChanges()
02543 {
02544   mCommitErrors.clear();
02545 
02546   if ( !mDataProvider )
02547   {
02548     mCommitErrors << tr( "ERROR: no provider" );
02549     return false;
02550   }
02551 
02552   if ( !mEditBuffer )
02553   {
02554     mCommitErrors << tr( "ERROR: layer not editable" );
02555     return false;
02556   }
02557 
02558   emit beforeCommitChanges();
02559 
02560   bool success = mEditBuffer->commitChanges( mCommitErrors );
02561 
02562   if ( success )
02563   {
02564     delete mEditBuffer;
02565     mEditBuffer = 0;
02566     undoStack()->clear();
02567     emit editingStopped();
02568   }
02569   else
02570   {
02571     QgsMessageLog::logMessage( tr( "Commit errors:\n  %1" ).arg( mCommitErrors.join( "\n  " ) ) );
02572   }
02573 
02574   updateFields();
02575   mDataProvider->updateExtents();
02576 
02577   //clear the cache image so markers don't appear anymore on next draw
02578   setCacheImage( 0 );
02579 
02580   return success;
02581 }
02582 
02583 const QStringList &QgsVectorLayer::commitErrors()
02584 {
02585   return mCommitErrors;
02586 }
02587 
02588 bool QgsVectorLayer::rollBack( bool deleteBuffer )
02589 {
02590   if ( !mEditBuffer )
02591   {
02592     return false;
02593   }
02594 
02595   mEditBuffer->rollBack();
02596 
02597   if ( isModified() )
02598   {
02599     // new undo stack roll back method
02600     // old method of calling every undo could cause many canvas refreshes
02601     undoStack()->setIndex( 0 );
02602   }
02603 
02604   updateFields();
02605 
02606   if ( deleteBuffer )
02607   {
02608     delete mEditBuffer;
02609     mEditBuffer = 0;
02610     undoStack()->clear();
02611   }
02612   emit editingStopped();
02613 
02614   // invalidate the cache so the layer updates properly to show its original
02615   // after the rollback
02616   setCacheImage( 0 );
02617   return true;
02618 }
02619 
02620 void QgsVectorLayer::setSelectedFeatures( const QgsFeatureIds& ids )
02621 {
02622   QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - ids;
02623   // TODO: check whether features with these ID exist
02624   mSelectedFeatureIds = ids;
02625 
02626   // invalidate cache
02627   setCacheImage( 0 );
02628 
02629   emit selectionChanged( ids, deselectedFeatures, true );
02630 }
02631 
02632 int QgsVectorLayer::selectedFeatureCount()
02633 {
02634   return mSelectedFeatureIds.size();
02635 }
02636 
02637 const QgsFeatureIds& QgsVectorLayer::selectedFeaturesIds() const
02638 {
02639   return mSelectedFeatureIds;
02640 }
02641 
02642 
02643 QgsFeatureList QgsVectorLayer::selectedFeatures()
02644 {
02645   QgsFeatureList features;
02646 
02647   QgsFeatureRequest req;
02648   if ( geometryType() == QGis::NoGeometry )
02649     req.setFlags( QgsFeatureRequest::NoGeometry );
02650 
02651   foreach ( QgsFeatureId fid, mSelectedFeatureIds )
02652   {
02653     features.push_back( QgsFeature() );
02654     getFeatures( req.setFilterFid( fid ) ).nextFeature( features.back() );
02655   }
02656 
02657   return features;
02658 }
02659 
02660 bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
02661 {
02662   if ( !mEditBuffer || !mDataProvider )
02663     return false;
02664 
02665   bool res = mEditBuffer->addFeatures( features );
02666 
02667   if ( makeSelected )
02668   {
02669     QgsFeatureIds ids;
02670 
02671     for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
02672       ids << iter->id();
02673 
02674     setSelectedFeatures( ids );
02675   }
02676 
02677   return res;
02678 }
02679 
02680 
02681 bool QgsVectorLayer::snapPoint( QgsPoint& point, double tolerance )
02682 {
02683   if ( !hasGeometryType() )
02684     return false;
02685 
02686   QMultiMap<double, QgsSnappingResult> snapResults;
02687   int result = snapWithContext( point, tolerance, snapResults, QgsSnapper::SnapToVertex );
02688 
02689   if ( result != 0 )
02690   {
02691     return false;
02692   }
02693 
02694   if ( snapResults.size() < 1 )
02695   {
02696     return false;
02697   }
02698 
02699   QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
02700   point.setX( snap_it.value().snappedVertex.x() );
02701   point.setY( snap_it.value().snappedVertex.y() );
02702   return true;
02703 }
02704 
02705 
02706 int QgsVectorLayer::snapWithContext( const QgsPoint& startPoint, double snappingTolerance,
02707                                      QMultiMap<double, QgsSnappingResult>& snappingResults,
02708                                      QgsSnapper::SnappingType snap_to )
02709 {
02710   if ( !hasGeometryType() )
02711     return 1;
02712 
02713   if ( snappingTolerance <= 0 || !mDataProvider )
02714   {
02715     return 1;
02716   }
02717 
02718   QList<QgsFeature> featureList;
02719   QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
02720                            startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
02721   double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
02722 
02723   int n = 0;
02724   QgsFeature f;
02725 
02726   if ( mCache->cachedGeometriesRect().contains( searchRect ) )
02727   {
02728     QgsGeometryMap& cachedGeometries = mCache->cachedGeometries();
02729     for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
02730     {
02731       QgsGeometry* g = &( it.value() );
02732       if ( g->boundingBox().intersects( searchRect ) )
02733       {
02734         snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
02735         ++n;
02736       }
02737     }
02738   }
02739   else
02740   {
02741     // snapping outside cached area
02742 
02743     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
02744                                           .setFilterRect( searchRect )
02745                                           .setFlags( QgsFeatureRequest::ExactIntersect )
02746                                           .setSubsetOfAttributes( QgsAttributeList() ) );
02747 
02748     while ( fit.nextFeature( f ) )
02749     {
02750       snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
02751       ++n;
02752     }
02753   }
02754 
02755   return n == 0 ? 2 : 0;
02756 }
02757 
02758 void QgsVectorLayer::snapToGeometry( const QgsPoint& startPoint,
02759                                      QgsFeatureId featureId,
02760                                      QgsGeometry* geom,
02761                                      double sqrSnappingTolerance,
02762                                      QMultiMap<double, QgsSnappingResult>& snappingResults,
02763                                      QgsSnapper::SnappingType snap_to ) const
02764 {
02765   if ( !geom )
02766   {
02767     return;
02768   }
02769 
02770   int atVertex, beforeVertex, afterVertex;
02771   double sqrDistVertexSnap, sqrDistSegmentSnap;
02772   QgsPoint snappedPoint;
02773   QgsSnappingResult snappingResultVertex;
02774   QgsSnappingResult snappingResultSegment;
02775 
02776   if ( snap_to == QgsSnapper::SnapToVertex || snap_to == QgsSnapper::SnapToVertexAndSegment )
02777   {
02778     snappedPoint = geom->closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
02779     if ( sqrDistVertexSnap < sqrSnappingTolerance )
02780     {
02781       snappingResultVertex.snappedVertex = snappedPoint;
02782       snappingResultVertex.snappedVertexNr = atVertex;
02783       snappingResultVertex.beforeVertexNr = beforeVertex;
02784       if ( beforeVertex != -1 ) // make sure the vertex is valid
02785       {
02786         snappingResultVertex.beforeVertex = geom->vertexAt( beforeVertex );
02787       }
02788       snappingResultVertex.afterVertexNr = afterVertex;
02789       if ( afterVertex != -1 ) // make sure the vertex is valid
02790       {
02791         snappingResultVertex.afterVertex = geom->vertexAt( afterVertex );
02792       }
02793       snappingResultVertex.snappedAtGeometry = featureId;
02794       snappingResultVertex.layer = this;
02795       snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
02796       return;
02797     }
02798   }
02799   if ( snap_to == QgsSnapper::SnapToSegment || snap_to == QgsSnapper::SnapToVertexAndSegment ) // snap to segment
02800   {
02801     if ( geometryType() != QGis::Point ) // cannot snap to segment for points/multipoints
02802     {
02803       sqrDistSegmentSnap = geom->closestSegmentWithContext( startPoint, snappedPoint, afterVertex, NULL, crs().geographicFlag() ? 1e-12 : 1e-8 );
02804 
02805       if ( sqrDistSegmentSnap < sqrSnappingTolerance )
02806       {
02807         snappingResultSegment.snappedVertex = snappedPoint;
02808         snappingResultSegment.snappedVertexNr = -1;
02809         snappingResultSegment.beforeVertexNr = afterVertex - 1;
02810         snappingResultSegment.afterVertexNr = afterVertex;
02811         snappingResultSegment.snappedAtGeometry = featureId;
02812         snappingResultSegment.beforeVertex = geom->vertexAt( afterVertex - 1 );
02813         snappingResultSegment.afterVertex = geom->vertexAt( afterVertex );
02814         snappingResultSegment.layer = this;
02815         snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
02816       }
02817     }
02818   }
02819 }
02820 
02821 int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
02822 {
02823   QgsVectorLayerEditUtils utils( this );
02824   return utils.insertSegmentVerticesForSnap( snapResults );
02825 }
02826 
02827 
02828 QgsVectorLayer::VertexMarkerType QgsVectorLayer::currentVertexMarkerType()
02829 {
02830   QSettings settings;
02831   QString markerTypeString = settings.value( "/qgis/digitizing/marker_style", "Cross" ).toString();
02832   if ( markerTypeString == "Cross" )
02833   {
02834     return QgsVectorLayer::Cross;
02835   }
02836   else if ( markerTypeString == "SemiTransparentCircle" )
02837   {
02838     return QgsVectorLayer::SemiTransparentCircle;
02839   }
02840   else
02841   {
02842     return QgsVectorLayer::NoMarker;
02843   }
02844 }
02845 
02846 int QgsVectorLayer::currentVertexMarkerSize()
02847 {
02848   QSettings settings;
02849   return settings.value( "/qgis/digitizing/marker_size", 3 ).toInt();
02850 }
02851 
02852 
02853 
02854 void QgsVectorLayer::setCoordinateSystem()
02855 {
02856   QgsDebugMsg( "----- Computing Coordinate System" );
02857 
02858   //
02859   // Get the layers project info and set up the QgsCoordinateTransform
02860   // for this layer
02861   //
02862 
02863   if ( hasGeometryType() )
02864   {
02865     // get CRS directly from provider
02866     setCrs( mDataProvider->crs() );
02867   }
02868   else
02869   {
02870     setCrs( QgsCoordinateReferenceSystem( GEO_EPSG_CRS_AUTHID ) );
02871   }
02872 }
02873 
02874 
02875 const QString QgsVectorLayer::displayField() const
02876 {
02877   return mDisplayField;
02878 }
02879 
02880 void QgsVectorLayer::setDisplayExpression( const QString displayExpression )
02881 {
02882   mDisplayExpression = displayExpression;
02883 }
02884 
02885 const QString QgsVectorLayer::displayExpression()
02886 {
02887   return mDisplayExpression;
02888 }
02889 
02890 bool QgsVectorLayer::isEditable() const
02891 {
02892   return ( mEditBuffer && mDataProvider );
02893 }
02894 
02895 bool QgsVectorLayer::isReadOnly() const
02896 {
02897   return mReadOnly;
02898 }
02899 
02900 bool QgsVectorLayer::setReadOnly( bool readonly )
02901 {
02902   // exit if the layer is in editing mode
02903   if ( readonly && mEditBuffer )
02904     return false;
02905 
02906   mReadOnly = readonly;
02907   return true;
02908 }
02909 
02910 bool QgsVectorLayer::isModified() const
02911 {
02912   return mEditBuffer && mEditBuffer->isModified();
02913 }
02914 
02915 QgsVectorLayer::EditType QgsVectorLayer::editType( int idx )
02916 {
02917   const QgsFields &fields = pendingFields();
02918   if ( idx >= 0 && idx < fields.count() && mEditTypes.contains( fields[idx].name() ) )
02919     return mEditTypes[ fields[idx].name()];
02920   else
02921     return LineEdit;
02922 }
02923 
02924 void QgsVectorLayer::setEditType( int idx, EditType type )
02925 {
02926   const QgsFields &fields = pendingFields();
02927   if ( idx >= 0 && idx < fields.count() )
02928     mEditTypes[ fields[idx].name()] = type;
02929 }
02930 
02931 QgsVectorLayer::EditorLayout QgsVectorLayer::editorLayout()
02932 {
02933   return mEditorLayout;
02934 }
02935 
02936 void QgsVectorLayer::setEditorLayout( EditorLayout editorLayout )
02937 {
02938   mEditorLayout = editorLayout;
02939 }
02940 
02941 QString QgsVectorLayer::editForm()
02942 {
02943   return mEditForm;
02944 }
02945 
02946 void QgsVectorLayer::setEditForm( QString ui )
02947 {
02948   mEditForm = ui;
02949 }
02950 
02951 void QgsVectorLayer::setAnnotationForm( const QString& ui )
02952 {
02953   mAnnotationForm = ui;
02954 }
02955 
02956 QString QgsVectorLayer::editFormInit()
02957 {
02958   return mEditFormInit;
02959 }
02960 
02961 void QgsVectorLayer::setEditFormInit( QString function )
02962 {
02963   mEditFormInit = function;
02964 }
02965 
02966 QMap< QString, QVariant > &QgsVectorLayer::valueMap( int idx )
02967 {
02968   const QgsFields &fields = pendingFields();
02969 
02970   // FIXME: throw an exception!?
02971   static QMap< QString, QVariant > invalidMap;
02972   if ( idx < 0 || idx >= fields.count() )
02973   {
02974     QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
02975     return invalidMap;
02976   }
02977   QString fieldName = fields[idx].name();
02978 
02979   if ( !mValueMaps.contains( fieldName ) )
02980     mValueMaps[fieldName] = QMap<QString, QVariant>();
02981 
02982   return mValueMaps[fieldName];
02983 }
02984 
02985 QgsVectorLayer::RangeData &QgsVectorLayer::range( int idx )
02986 {
02987   const QgsFields &fields = pendingFields();
02988 
02989   // FIXME: throw an exception!?
02990   static QgsVectorLayer::RangeData invalidRange;
02991   if ( idx < 0 || idx >= fields.count() )
02992   {
02993     QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
02994     return invalidRange;
02995   }
02996   QString fieldName = fields[idx].name();
02997 
02998   if ( !mRanges.contains( fieldName ) )
02999     mRanges[fieldName] = RangeData();
03000 
03001   return mRanges[fieldName];
03002 }
03003 
03004 QString &QgsVectorLayer::dateFormat( int idx )
03005 {
03006   const QgsFields &fields = pendingFields();
03007 
03008   QString fieldName = fields[idx].name();
03009 
03010   if ( !mDateFormats.contains( fieldName ) )
03011     mDateFormats[fieldName] = "yyyy-MM-dd";
03012 
03013   return mDateFormats[fieldName];
03014 }
03015 
03016 QSize &QgsVectorLayer::widgetSize( int idx )
03017 {
03018   const QgsFields &fields = pendingFields();
03019 
03020   QString fieldName = fields[idx].name();
03021 
03022   if ( !mWidgetSize.contains( fieldName ) )
03023     mWidgetSize[fieldName] = QSize( 0, 0 );
03024 
03025   return mWidgetSize[fieldName];
03026 }
03027 
03028 bool QgsVectorLayer::fieldEditable( int idx )
03029 {
03030   const QgsFields &fields = pendingFields();
03031   if ( idx >= 0 && idx < fields.count() )
03032     return mFieldEditables.value( fields[idx].name(), true );
03033   else
03034     return true;
03035 }
03036 
03037 void QgsVectorLayer::setFieldEditable( int idx, bool editable )
03038 {
03039   const QgsFields &fields = pendingFields();
03040   if ( idx >= 0 && idx < fields.count() )
03041     mFieldEditables[ fields[idx].name()] = editable;
03042 }
03043 
03044 void QgsVectorLayer::addOverlay( QgsVectorOverlay* overlay )
03045 {
03046   mOverlays.push_back( overlay );
03047 }
03048 
03049 void QgsVectorLayer::removeOverlay( const QString& typeName )
03050 {
03051   for ( int i = mOverlays.size() - 1; i >= 0; --i )
03052   {
03053     if ( mOverlays.at( i )->typeName() == typeName )
03054     {
03055       mOverlays.removeAt( i );
03056     }
03057   }
03058 }
03059 
03060 void QgsVectorLayer::vectorOverlays( QList<QgsVectorOverlay*>& overlayList )
03061 {
03062   overlayList = mOverlays;
03063 }
03064 
03065 QgsVectorOverlay* QgsVectorLayer::findOverlayByType( const QString& typeName )
03066 {
03067   QList<QgsVectorOverlay*>::iterator it = mOverlays.begin();
03068   for ( ; it != mOverlays.end(); ++it )
03069   {
03070     if (( *it )->typeName() == typeName )
03071     {
03072       return *it;
03073     }
03074   }
03075   return 0; //not found
03076 }
03077 
03078 
03079 QgsFeatureRendererV2* QgsVectorLayer::rendererV2()
03080 {
03081   return mRendererV2;
03082 }
03083 
03084 void QgsVectorLayer::setRendererV2( QgsFeatureRendererV2 *r )
03085 {
03086   if ( !hasGeometryType() )
03087     return;
03088 
03089   if ( r != mRendererV2 )
03090   {
03091     delete mRendererV2;
03092     mRendererV2 = r;
03093     mSymbolFeatureCounted = false;
03094     mSymbolFeatureCountMap.clear();
03095   }
03096 }
03097 
03098 
03099 
03100 void QgsVectorLayer::beginEditCommand( QString text )
03101 {
03102   undoStack()->beginMacro( text );
03103 }
03104 
03105 void QgsVectorLayer::endEditCommand()
03106 {
03107   undoStack()->endMacro();
03108 }
03109 
03110 void QgsVectorLayer::destroyEditCommand()
03111 {
03112   undoStack()->endMacro();
03113   undoStack()->undo();
03114 }
03115 
03116 
03117 void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
03118 {
03119   const QgsFields &fields = pendingFields();
03120   if ( idx >= 0 && idx < fields.count() )
03121     mCheckedStates[ fields[idx].name()] = QPair<QString, QString>( checked, unchecked );
03122 }
03123 
03124 QPair<QString, QString> QgsVectorLayer::checkedState( int idx )
03125 {
03126   const QgsFields &fields = pendingFields();
03127   if ( idx >= 0 && idx < fields.count() && mCheckedStates.contains( fields[idx].name() ) )
03128     return mCheckedStates[ fields[idx].name()];
03129   else
03130     return QPair<QString, QString>( "1", "0" );
03131 }
03132 
03133 int QgsVectorLayer::fieldNameIndex( const QString& fieldName ) const
03134 {
03135   const QgsFields &theFields = pendingFields();
03136 
03137   for ( int idx = 0; idx < theFields.count(); ++idx )
03138   {
03139     if ( QString::compare( theFields[idx].name(), fieldName, Qt::CaseInsensitive ) == 0 )
03140     {
03141       return idx;
03142     }
03143   }
03144   return -1;
03145 }
03146 
03147 void QgsVectorLayer::addJoin( const QgsVectorJoinInfo& joinInfo )
03148 {
03149   mJoinBuffer->addJoin( joinInfo );
03150   updateFields();
03151 }
03152 
03153 void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
03154 {
03155   removeJoin( theLayerId );
03156 }
03157 
03158 void QgsVectorLayer::removeJoin( const QString& joinLayerId )
03159 {
03160   mJoinBuffer->removeJoin( joinLayerId );
03161   updateFields();
03162 }
03163 
03164 const QList< QgsVectorJoinInfo >& QgsVectorLayer::vectorJoins() const
03165 {
03166   return mJoinBuffer->vectorJoins();
03167 }
03168 
03169 void QgsVectorLayer::updateFields()
03170 {
03171   if ( !mDataProvider )
03172     return;
03173 
03174   mUpdatedFields = mDataProvider->fields();
03175 
03176   // added / removed fields
03177   if ( mEditBuffer )
03178     mEditBuffer->updateFields( mUpdatedFields );
03179 
03180   // joined fields
03181   if ( mJoinBuffer && mJoinBuffer->containsJoins() )
03182     mJoinBuffer->updateFields( mUpdatedFields );
03183 
03184   emit updatedFields();
03185 }
03186 
03187 
03188 void QgsVectorLayer::createJoinCaches()
03189 {
03190   if ( mJoinBuffer->containsJoins() )
03191   {
03192     mJoinBuffer->createJoinCaches();
03193   }
03194 }
03195 
03196 void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
03197 {
03198   uniqueValues.clear();
03199   if ( !mDataProvider )
03200   {
03201     return;
03202   }
03203 
03204   QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
03205 
03206   if ( origin == QgsFields::OriginProvider ) //a provider field
03207   {
03208     return mDataProvider->uniqueValues( index, uniqueValues, limit );
03209   }
03210   else if ( origin == QgsFields::OriginJoin )
03211   {
03212     int sourceLayerIndex;
03213     const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
03214     Q_ASSERT( join );
03215 
03216     QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
03217     Q_ASSERT( vl );
03218 
03219     return vl->dataProvider()->uniqueValues( sourceLayerIndex, uniqueValues, limit );
03220   }
03221   else if ( origin == QgsFields::OriginEdit )
03222   {
03223     // the layer is editable, but in certain cases it can still be avoided going through all features
03224     if ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mAddedFeatures.isEmpty() && !mEditBuffer->mDeletedAttributeIds.contains( index ) && mEditBuffer->mChangedAttributeValues.isEmpty() )
03225     {
03226       return mDataProvider->uniqueValues( index, uniqueValues, limit );
03227     }
03228 
03229     // we need to go through each feature
03230     QgsAttributeList attList;
03231     attList << index;
03232 
03233     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
03234                                           .setFlags( QgsFeatureRequest::NoGeometry )
03235                                           .setSubsetOfAttributes( attList ) );
03236 
03237     QgsFeature f;
03238     QVariant currentValue;
03239     QHash<QString, QVariant> val;
03240     while ( fit.nextFeature( f ) )
03241     {
03242       currentValue = f.attribute( index );
03243       val.insert( currentValue.toString(), currentValue );
03244       if ( limit >= 0 && val.size() >= limit )
03245       {
03246         break;
03247       }
03248     }
03249 
03250     uniqueValues = val.values();
03251     return;
03252   }
03253 
03254   Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
03255 }
03256 
03257 QVariant QgsVectorLayer::minimumValue( int index )
03258 {
03259   if ( !mDataProvider )
03260   {
03261     return QVariant();
03262   }
03263 
03264   QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
03265 
03266   if ( origin == QgsFields::OriginProvider ) //a provider field
03267   {
03268     return mDataProvider->minimumValue( index );
03269   }
03270   else if ( origin == QgsFields::OriginJoin )
03271   {
03272     int sourceLayerIndex;
03273     const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
03274     Q_ASSERT( join );
03275 
03276     QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
03277     Q_ASSERT( vl );
03278 
03279     return vl->minimumValue( sourceLayerIndex );
03280   }
03281   else if ( origin == QgsFields::OriginEdit )
03282   {
03283     // the layer is editable, but in certain cases it can still be avoided going through all features
03284     if ( mEditBuffer->mDeletedFeatureIds.isEmpty() && mEditBuffer->mAddedFeatures.isEmpty() && !mEditBuffer->mDeletedAttributeIds.contains( index ) && mEditBuffer->mChangedAttributeValues.isEmpty() )
03285     {
03286       return mDataProvider->minimumValue( index );
03287     }
03288 
03289     // we need to go through each feature
03290     QgsAttributeList attList;
03291     attList << index;
03292 
03293     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
03294                                           .setFlags( QgsFeatureRequest::NoGeometry )
03295                                           .setSubsetOfAttributes( attList ) );
03296 
03297     QgsFeature f;
03298     double minimumValue = std::numeric_limits<double>::max();
03299     double currentValue = 0;
03300     while ( fit.nextFeature( f ) )
03301     {
03302       currentValue = f.attribute( index ).toDouble();
03303       if ( currentValue < minimumValue )
03304       {
03305         minimumValue = currentValue;
03306       }
03307     }
03308     return QVariant( minimumValue );
03309   }
03310 
03311   Q_ASSERT_X( false, "QgsVectorLayer::minimumValue()", "Unknown source of the field!" );
03312   return QVariant();
03313 }
03314 
03315 QVariant QgsVectorLayer::maximumValue( int index )
03316 {
03317   if ( !mDataProvider )
03318   {
03319     return QVariant();
03320   }
03321 
03322   QgsFields::FieldOrigin origin = mUpdatedFields.fieldOrigin( index );
03323 
03324   if ( origin == QgsFields::OriginProvider ) //a provider field
03325   {
03326     return mDataProvider->maximumValue( index );
03327   }
03328   else if ( origin == QgsFields::OriginJoin )
03329   {
03330     int sourceLayerIndex;
03331     const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, mUpdatedFields, sourceLayerIndex );
03332     Q_ASSERT( join );
03333 
03334     QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
03335     Q_ASSERT( vl );
03336 
03337     return vl->maximumValue( sourceLayerIndex );
03338   }
03339   else if ( origin == QgsFields::OriginEdit )
03340   {
03341     // the layer is editable, but in certain cases it can still be avoided going through all features
03342     if ( mEditBuffer->mDeletedFeatureIds.isEmpty() &&
03343          mEditBuffer->mAddedFeatures.isEmpty() &&
03344          !mEditBuffer->mDeletedAttributeIds.contains( index ) &&
03345          mEditBuffer->mChangedAttributeValues.isEmpty() )
03346     {
03347       return mDataProvider->maximumValue( index );
03348     }
03349 
03350     // we need to go through each feature
03351     QgsAttributeList attList;
03352     attList << index;
03353 
03354     QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
03355                                           .setFlags( QgsFeatureRequest::NoGeometry )
03356                                           .setSubsetOfAttributes( attList ) );
03357 
03358     QgsFeature f;
03359     double maximumValue = -std::numeric_limits<double>::max();
03360     double currentValue = 0;
03361     while ( fit.nextFeature( f ) )
03362     {
03363       currentValue = f.attribute( index ).toDouble();
03364       if ( currentValue > maximumValue )
03365       {
03366         maximumValue = currentValue;
03367       }
03368     }
03369     return QVariant( maximumValue );
03370   }
03371 
03372   Q_ASSERT_X( false, "QgsVectorLayer::maximumValue()", "Unknown source of the field!" );
03373   return QVariant();
03374 }
03375 
03377 void QgsVectorLayer::setFeatureBlendMode( const QPainter::CompositionMode featureBlendMode )
03378 {
03379   mFeatureBlendMode = featureBlendMode;
03380 }
03381 
03383 QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
03384 {
03385   return mFeatureBlendMode;
03386 }
03387 
03389 void QgsVectorLayer::setLayerTransparency( int layerTransparency )
03390 {
03391   mLayerTransparency = layerTransparency;
03392 }
03393 
03395 int QgsVectorLayer::layerTransparency() const
03396 {
03397   return mLayerTransparency;
03398 }
03399 
03400 void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
03401 {
03402   mRendererV2->stopRender( rendererContext );
03403   if ( selRenderer )
03404   {
03405     selRenderer->stopRender( rendererContext );
03406     delete selRenderer;
03407   }
03408 }
03409 
03410 void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling )
03411 {
03412   if ( !rendererContext.labelingEngine() )
03413     return;
03414 
03415   QSet<int> attrIndex;
03416   if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
03417   {
03418     QSet<int>::const_iterator attIt = attrIndex.constBegin();
03419     for ( ; attIt != attrIndex.constEnd(); ++attIt )
03420     {
03421       if ( !attributes.contains( *attIt ) )
03422       {
03423         attributes << *attIt;
03424       }
03425     }
03426     labeling = true;
03427   }
03428 
03429   if ( labeling )
03430   {
03431     // see if feature count limit is set for labeling
03432     QgsPalLayerSettings& palyr = rendererContext.labelingEngine()->layer( this->id() );
03433     if ( palyr.limitNumLabels && palyr.maxNumLabels > 0 )
03434     {
03435       QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
03436                                             .setFilterRect( rendererContext.extent() )
03437                                             .setSubsetOfAttributes( QgsAttributeList() ) );
03438 
03439       // total number of features that may be labeled
03440       QgsFeature f;
03441       int nFeatsToLabel = 0;
03442       while ( fit.nextFeature( f ) )
03443       {
03444         nFeatsToLabel++;
03445       }
03446       palyr.mFeaturesToLabel = nFeatsToLabel;
03447     }
03448   }
03449 
03450   //register diagram layers
03451   if ( mDiagramRenderer && mDiagramLayerSettings )
03452   {
03453     mDiagramLayerSettings->renderer = mDiagramRenderer;
03454     rendererContext.labelingEngine()->addDiagramLayer( this, mDiagramLayerSettings );
03455     //add attributes needed by the diagram renderer
03456     QList<int> att = mDiagramRenderer->diagramAttributes();
03457     QList<int>::const_iterator attIt = att.constBegin();
03458     for ( ; attIt != att.constEnd(); ++attIt )
03459     {
03460       if ( !attributes.contains( *attIt ) )
03461       {
03462         attributes << *attIt;
03463       }
03464     }
03465     //and the ones needed for data defined diagram positions
03466     if ( mDiagramLayerSettings->xPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->xPosColumn ) )
03467     {
03468       attributes << mDiagramLayerSettings->xPosColumn;
03469     }
03470     if ( mDiagramLayerSettings->yPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->yPosColumn ) )
03471     {
03472       attributes << mDiagramLayerSettings->yPosColumn;
03473     }
03474   }
03475 }
03476 
03477 void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings& s )
03478 {
03479   if ( !mDiagramLayerSettings )
03480     mDiagramLayerSettings = new QgsDiagramLayerSettings();
03481   *mDiagramLayerSettings = s;
03482 }
03483 
03484 QString QgsVectorLayer::metadata()
03485 {
03486   QString myMetadata = "<html><body>";
03487 
03488   //-------------
03489 
03490   myMetadata += "<p class=\"subheaderglossy\">";
03491   myMetadata += tr( "General" );
03492   myMetadata += "</p>\n";
03493 
03494   // data comment
03495   if ( !( dataComment().isEmpty() ) )
03496   {
03497     myMetadata += "<p class=\"glossy\">" + tr( "Layer comment" ) + "</p>\n";
03498     myMetadata += "<p>";
03499     myMetadata += dataComment();
03500     myMetadata += "</p>\n";
03501   }
03502 
03503   //storage type
03504   myMetadata += "<p class=\"glossy\">" + tr( "Storage type of this layer" ) + "</p>\n";
03505   myMetadata += "<p>";
03506   myMetadata += storageType();
03507   myMetadata += "</p>\n";
03508 
03509   // data source
03510   myMetadata += "<p class=\"glossy\">" + tr( "Source for this layer" ) + "</p>\n";
03511   myMetadata += "<p>";
03512   myMetadata += publicSource();
03513   myMetadata += "</p>\n";
03514 
03515   //geom type
03516 
03517   QGis::GeometryType type = geometryType();
03518 
03519   if ( type < 0 || type > QGis::NoGeometry )
03520   {
03521     QgsDebugMsg( "Invalid vector type" );
03522   }
03523   else
03524   {
03525     QString typeString( QGis::vectorGeometryType( geometryType() ) );
03526 
03527     myMetadata += "<p class=\"glossy\">" + tr( "Geometry type of the features in this layer" ) + "</p>\n";
03528     myMetadata += "<p>";
03529     myMetadata += typeString;
03530     myMetadata += "</p>\n";
03531   }
03532 
03533   QgsAttributeList pkAttrList = pendingPkAttributesList();
03534   if ( !pkAttrList.isEmpty() )
03535   {
03536     myMetadata += "<p class=\"glossy\">" + tr( "Primary key attributes" ) + "</p>\n";
03537     myMetadata += "<p>";
03538     foreach ( int idx, pkAttrList )
03539     {
03540       myMetadata += pendingFields()[ idx ].name() + " ";
03541     }
03542     myMetadata += "</p>\n";
03543   }
03544 
03545 
03546   //feature count
03547   myMetadata += "<p class=\"glossy\">" + tr( "The number of features in this layer" ) + "</p>\n";
03548   myMetadata += "<p>";
03549   myMetadata += QString::number( featureCount() );
03550   myMetadata += "</p>\n";
03551   //capabilities
03552   myMetadata += "<p class=\"glossy\">" + tr( "Editing capabilities of this layer" ) + "</p>\n";
03553   myMetadata += "<p>";
03554   myMetadata += capabilitiesString();
03555   myMetadata += "</p>\n";
03556 
03557   //-------------
03558 
03559   QgsRectangle myExtent = extent();
03560   myMetadata += "<p class=\"subheaderglossy\">";
03561   myMetadata += tr( "Extents" );
03562   myMetadata += "</p>\n";
03563 
03564   //extents in layer cs  TODO...maybe make a little nested table to improve layout...
03565   myMetadata += "<p class=\"glossy\">" + tr( "In layer spatial reference system units" ) + "</p>\n";
03566   myMetadata += "<p>";
03567   // Try to be a bit clever over what number format we use for the
03568   // extents. Some people don't like it using scientific notation when the
03569   // numbers get large, but for small numbers this is the more practical
03570   // option (so we can't force the format to 'f' for all values).
03571   // The scheme:
03572   // - for all numbers with more than 5 digits, force non-scientific notation
03573   // and 2 digits after the decimal point.
03574   // - for all smaller numbers let the OS decide which format to use (it will
03575   // generally use non-scientific unless the number gets much less than 1).
03576 
03577   if ( !myExtent.isEmpty() )
03578   {
03579     QString xMin, yMin, xMax, yMax;
03580     double changeoverValue = 99999; // The 'largest' 5 digit number
03581     if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
03582     {
03583       xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
03584     }
03585     else
03586     {
03587       xMin = QString( "%1" ).arg( myExtent.xMinimum() );
03588     }
03589     if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
03590     {
03591       yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
03592     }
03593     else
03594     {
03595       yMin = QString( "%1" ).arg( myExtent.yMinimum() );
03596     }
03597     if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
03598     {
03599       xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
03600     }
03601     else
03602     {
03603       xMax = QString( "%1" ).arg( myExtent.xMaximum() );
03604     }
03605     if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
03606     {
03607       yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
03608     }
03609     else
03610     {
03611       yMax = QString( "%1" ).arg( myExtent.yMaximum() );
03612     }
03613 
03614     myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
03615                   .arg( xMin ).arg( yMin ).arg( xMax ).arg( yMax );
03616   }
03617   else
03618   {
03619     myMetadata += tr( "unknown extent" );
03620   }
03621 
03622   myMetadata += "</p>\n";
03623 
03624   //extents in project cs
03625 
03626   try
03627   {
03628 #if 0
03629     // TODO: currently disabled, will revisit later [MD]
03630     QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
03631     myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
03632     myMetadata += "<p>";
03633     myMetadata += tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
03634                   .arg( myProjectedExtent.xMinimum() )
03635                   .arg( myProjectedExtent.yMinimum() )
03636                   .arg( myProjectedExtent.xMaximum() )
03637                   .arg( myProjectedExtent.yMaximum() );
03638     myMetadata += "</p>\n";
03639 #endif
03640 
03641     //
03642     // Display layer spatial ref system
03643     //
03644     myMetadata += "<p class=\"glossy\">" + tr( "Layer Spatial Reference System" ) + "</p>\n";
03645     myMetadata += "<p>";
03646     myMetadata += crs().toProj4().replace( QRegExp( "\"" ), " \"" );
03647     myMetadata += "</p>\n";
03648 
03649     //
03650     // Display project (output) spatial ref system
03651     //
03652 #if 0
03653     // TODO: disabled for now, will revisit later [MD]
03654     //myMetadata += "<tr><td bgcolor=\"gray\">";
03655     myMetadata += "<p class=\"glossy\">" + tr( "Project (Output) Spatial Reference System" ) + "</p>\n";
03656     myMetadata += "<p>";
03657     myMetadata += coordinateTransform->destCRS().toProj4().replace( QRegExp( "\"" ), " \"" );
03658     myMetadata += "</p>\n";
03659 #endif
03660   }
03661   catch ( QgsCsException &cse )
03662   {
03663     Q_UNUSED( cse );
03664     QgsDebugMsg( cse.what() );
03665 
03666     myMetadata += "<p class=\"glossy\">" + tr( "In project spatial reference system units" ) + "</p>\n";
03667     myMetadata += "<p>";
03668     myMetadata += tr( "(Invalid transformation of layer extents)" );
03669     myMetadata += "</p>\n";
03670 
03671   }
03672 
03673 #if 0
03674   //
03675   // Add the info about each field in the attribute table
03676   //
03677   myMetadata += "<p class=\"glossy\">" + tr( "Attribute field info" ) + "</p>\n";
03678   myMetadata += "<p>";
03679 
03680   // Start a nested table in this trow
03681   myMetadata += "<table width=\"100%\">";
03682   myMetadata += "<tr><th>";
03683   myMetadata += tr( "Field" );
03684   myMetadata += "</th>";
03685   myMetadata += "<th>";
03686   myMetadata += tr( "Type" );
03687   myMetadata += "</th>";
03688   myMetadata += "<th>";
03689   myMetadata += tr( "Length" );
03690   myMetadata += "</th>";
03691   myMetadata += "<th>";
03692   myMetadata += tr( "Precision" );
03693   myMetadata += "</th>";
03694   myMetadata += "<th>";
03695   myMetadata += tr( "Comment" );
03696   myMetadata += "</th>";
03697 
03698   //get info for each field by looping through them
03699   const QgsFieldMap& myFields = pendingFields();
03700   for ( QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it )
03701   {
03702     const QgsField& myField = *it;
03703 
03704     myMetadata += "<tr><td>";
03705     myMetadata += myField.name();
03706     myMetadata += "</td>";
03707     myMetadata += "<td>";
03708     myMetadata += myField.typeName();
03709     myMetadata += "</td>";
03710     myMetadata += "<td>";
03711     myMetadata += QString( "%1" ).arg( myField.length() );
03712     myMetadata += "</td>";
03713     myMetadata += "<td>";
03714     myMetadata += QString( "%1" ).arg( myField.precision() );
03715     myMetadata += "</td>";
03716     myMetadata += "<td>";
03717     myMetadata += QString( "%1" ).arg( myField.comment() );
03718     myMetadata += "</td></tr>";
03719   }
03720 
03721   //close field list
03722   myMetadata += "</table>"; //end of nested table
03723 #endif
03724 
03725   myMetadata += "</body></html>";
03726   return myMetadata;
03727 }
03728 
03729 void QgsVectorLayer::onCacheImageDelete()
03730 {
03731   if ( mCurrentRendererContext )
03732     mCurrentRendererContext->setRenderingStopped( true );
03733 }
03734 
03735 QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx )
03736 {
03737   const QgsFields &fields = pendingFields();
03738 
03739   // FIXME: throw an exception!?
03740   static QgsVectorLayer::ValueRelationData invalidData;
03741   if ( idx < 0 || idx >= fields.count() )
03742   {
03743     QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) );
03744     return invalidData;
03745   }
03746   QString fieldName = fields[idx].name();
03747 
03748   if ( !mValueRelations.contains( fieldName ) )
03749   {
03750     mValueRelations[fieldName] = ValueRelationData();
03751   }
03752 
03753   return mValueRelations[fieldName];
03754 }
03755 
03756 QList<QgsAttributeEditorElement*> &QgsVectorLayer::attributeEditorElements()
03757 {
03758   return mAttributeEditorElements;
03759 }
03760 
03761 void QgsVectorLayer::clearAttributeEditorWidgets()
03762 {
03763   mAttributeEditorElements.clear();
03764 }
03765 
03766 QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
03767 {
03768   QDomElement elem = doc.createElement( "attributeEditorContainer" );
03769   elem.setAttribute( "name", mName );
03770   for ( QList< QgsAttributeEditorElement* >::const_iterator it = mChildren.begin(); it != mChildren.end(); ++it )
03771   {
03772     elem.appendChild(( *it )->toDomElement( doc ) );
03773   }
03774   return elem;
03775 }
03776 
03777 
03778 void QgsAttributeEditorContainer::addChildElement( QgsAttributeEditorElement *widget )
03779 {
03780   mChildren.append( widget );
03781 }
03782 
03783 QDomElement QgsAttributeEditorField::toDomElement( QDomDocument& doc ) const
03784 {
03785   QDomElement elem = doc.createElement( "attributeEditorField" );
03786   elem.setAttribute( "name", mName );
03787   elem.setAttribute( "index", mIdx );
03788   return elem;
03789 }
03790 
03791 int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
03792 {
03793   QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
03794   QLibrary *myLib = pReg->providerLibrary( mProviderKey );
03795   if ( !myLib )
03796   {
03797     msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
03798     return -1;
03799   }
03800   listStyles_t* listStylesExternalMethod = ( listStyles_t * ) cast_to_fptr( myLib->resolve( "listStyles" ) );
03801 
03802   if ( !listStylesExternalMethod )
03803   {
03804     delete myLib;
03805     msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "listStyles" );
03806     return -1;
03807   }
03808 
03809   return listStylesExternalMethod( mDataSource, ids, names, descriptions, msgError );
03810 }
03811 
03812 QString QgsVectorLayer::getStyleFromDatabase( QString styleId, QString &msgError )
03813 {
03814   QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
03815   QLibrary *myLib = pReg->providerLibrary( mProviderKey );
03816   if ( !myLib )
03817   {
03818     msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
03819     return QObject::tr( "" );
03820   }
03821   getStyleById_t* getStyleByIdMethod = ( getStyleById_t * ) cast_to_fptr( myLib->resolve( "getStyleById" ) );
03822 
03823   if ( !getStyleByIdMethod )
03824   {
03825     delete myLib;
03826     msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "getStyleById" );
03827     return QObject::tr( "" );
03828   }
03829 
03830   return getStyleByIdMethod( mDataSource, styleId, msgError );
03831 }
03832 
03833 
03834 void QgsVectorLayer::saveStyleToDatabase( QString name, QString description,
03835     bool useAsDefault, QString uiFileContent,  QString &msgError )
03836 {
03837 
03838   QString sldStyle, qmlStyle;
03839   QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
03840   QLibrary *myLib = pReg->providerLibrary( mProviderKey );
03841   if ( !myLib )
03842   {
03843     msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
03844     return;
03845   }
03846   saveStyle_t* saveStyleExternalMethod = ( saveStyle_t * ) cast_to_fptr( myLib->resolve( "saveStyle" ) );
03847 
03848   if ( !saveStyleExternalMethod )
03849   {
03850     delete myLib;
03851     msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey ).arg( "saveStyle" );
03852     return;
03853   }
03854 
03855   QDomDocument qmlDocument, sldDocument;
03856   this->exportNamedStyle( qmlDocument, msgError );
03857   if ( !msgError.isNull() )
03858   {
03859     return;
03860   }
03861   qmlStyle = qmlDocument.toString();
03862 
03863   this->exportSldStyle( sldDocument, msgError );
03864   if ( !msgError.isNull() )
03865   {
03866     return;
03867   }
03868   sldStyle = sldDocument.toString();
03869 
03870   saveStyleExternalMethod( mDataSource, qmlStyle, sldStyle, name,
03871                            description, uiFileContent, useAsDefault, msgError );
03872 }
03873 
03874 
03875 
03876 QString QgsVectorLayer::loadNamedStyle( const QString theURI, bool &theResultFlag )
03877 {
03878   return loadNamedStyle( theURI, theResultFlag, false );
03879 }
03880 
03881 QString QgsVectorLayer::loadNamedStyle( const QString theURI, bool &theResultFlag , bool loadFromLocalDB )
03882 {
03883   QgsDataSourceURI dsUri( theURI );
03884   if ( !loadFromLocalDB && !dsUri.database().isEmpty() )
03885   {
03886     QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
03887     QLibrary *myLib = pReg->providerLibrary( mProviderKey );
03888     if ( myLib )
03889     {
03890       loadStyle_t* loadStyleExternalMethod = ( loadStyle_t * ) cast_to_fptr( myLib->resolve( "loadStyle" ) );
03891       if ( loadStyleExternalMethod )
03892       {
03893         QString qml, errorMsg;
03894         qml = loadStyleExternalMethod( mDataSource, errorMsg );
03895         if ( !qml.isEmpty() )
03896         {
03897           theResultFlag = this->applyNamedStyle( qml, errorMsg );
03898         }
03899       }
03900     }
03901 
03902   }
03903   if ( !theResultFlag )
03904   {
03905     return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
03906   }
03907   return QObject::tr( "Loaded from Provider" );
03908 }
03909 
03910 bool QgsVectorLayer::applyNamedStyle( QString namedStyle, QString errorMsg )
03911 {
03912   QDomDocument myDocument( "qgis" );
03913   myDocument.setContent( namedStyle );
03914 
03915   QDomElement myRoot = myDocument.firstChildElement( "qgis" );
03916 
03917   if ( myRoot.isNull() )
03918   {
03919     errorMsg = tr( "Error: qgis element could not be found" );
03920     return false;
03921   }
03922   toggleScaleBasedVisibility( myRoot.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
03923   setMinimumScale( myRoot.attribute( "minimumScale" ).toFloat() );
03924   setMaximumScale( myRoot.attribute( "maximumScale" ).toFloat() );
03925 
03926 #if 0
03927   //read transparency level
03928   QDomNode transparencyNode = myRoot.namedItem( "transparencyLevelInt" );
03929   if ( ! transparencyNode.isNull() )
03930   {
03931     // set transparency level only if it's in project
03932     // (otherwise it sets the layer transparent)
03933     QDomElement myElement = transparencyNode.toElement();
03934     setTransparency( myElement.text().toInt() );
03935   }
03936 #endif
03937 
03938   return readSymbology( myRoot, errorMsg );
03939 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines