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