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