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