|
QGIS API Documentation
master-59fd5e0
|
00001 /*************************************************************************** 00002 qgsvectorlayereditbuffer.cpp 00003 --------------------- 00004 begin : Dezember 2012 00005 copyright : (C) 2012 by Martin Dobias 00006 email : wonder dot sk at gmail dot com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 #include "qgsvectorlayereditbuffer.h" 00016 00017 #include "qgsgeometry.h" 00018 #include "qgslogger.h" 00019 #include "qgsvectorlayerundocommand.h" 00020 #include "qgsvectordataprovider.h" 00021 #include "qgsvectorlayer.h" 00022 00023 00024 QgsVectorLayerEditBuffer::QgsVectorLayerEditBuffer( QgsVectorLayer* layer ) 00025 : L( layer ) 00026 { 00027 connect( L->undoStack(), SIGNAL( indexChanged( int ) ), this, SLOT( undoIndexChanged( int ) ) ); // TODO[MD]: queued? 00028 } 00029 00030 QgsVectorLayerEditBuffer::~QgsVectorLayerEditBuffer() 00031 { 00032 } 00033 00034 00035 bool QgsVectorLayerEditBuffer::isModified() const 00036 { 00037 return !L->undoStack()->isClean(); 00038 } 00039 00040 00041 void QgsVectorLayerEditBuffer::undoIndexChanged( int index ) 00042 { 00043 qDebug( "undo index changed %d", index ); 00044 Q_UNUSED( index ); 00045 emit layerModified(); 00046 } 00047 00048 00049 void QgsVectorLayerEditBuffer::updateFields( QgsFields& fields ) 00050 { 00051 // delete attributes from the higher indices to lower indices 00052 for ( int i = mDeletedAttributeIds.count() - 1; i >= 0; --i ) 00053 { 00054 fields.remove( mDeletedAttributeIds[i] ); 00055 } 00056 // add new fields 00057 for ( int i = 0; i < mAddedAttributes.count(); ++i ) 00058 { 00059 fields.append( mAddedAttributes[i], QgsFields::OriginEdit, i ); 00060 } 00061 } 00062 00063 00064 void QgsVectorLayerEditBuffer::updateFeatureGeometry( QgsFeature &f ) 00065 { 00066 if ( mChangedGeometries.contains( f.id() ) ) 00067 f.setGeometry( mChangedGeometries[f.id()] ); 00068 } 00069 00070 00071 void QgsVectorLayerEditBuffer::updateChangedAttributes( QgsFeature &f ) 00072 { 00073 QgsAttributes& attrs = f.attributes(); 00074 00075 // remove all attributes that will disappear - from higher indices to lower 00076 for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx ) 00077 { 00078 attrs.remove( mDeletedAttributeIds[idx] ); 00079 } 00080 00081 // adjust size to accommodate added attributes 00082 attrs.resize( attrs.count() + mAddedAttributes.count() ); 00083 00084 // update changed attributes 00085 if ( mChangedAttributeValues.contains( f.id() ) ) 00086 { 00087 const QgsAttributeMap &map = mChangedAttributeValues[f.id()]; 00088 for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); it++ ) 00089 attrs[it.key()] = it.value(); 00090 } 00091 } 00092 00093 00094 00095 00096 bool QgsVectorLayerEditBuffer::addFeature( QgsFeature& f ) 00097 { 00098 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures ) ) 00099 { 00100 return false; 00101 } 00102 00103 int layerFieldCount = L->dataProvider()->fields().count() + mAddedAttributes.count() - mDeletedAttributeIds.count(); 00104 if ( layerFieldCount != f.attributes().count() ) 00105 return false; 00106 00107 // TODO: check correct geometry type 00108 00109 L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) ); 00110 return true; 00111 } 00112 00113 00114 bool QgsVectorLayerEditBuffer::addFeatures( QgsFeatureList& features ) 00115 { 00116 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures ) ) 00117 return false; 00118 00119 for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter ) 00120 { 00121 addFeature( *iter ); 00122 } 00123 00124 L->updateExtents(); 00125 return true; 00126 } 00127 00128 00129 00130 bool QgsVectorLayerEditBuffer::deleteFeature( QgsFeatureId fid ) 00131 { 00132 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures ) ) 00133 return false; 00134 00135 if ( FID_IS_NEW( fid ) ) 00136 { 00137 if ( !mAddedFeatures.contains( fid ) ) 00138 return false; 00139 } 00140 else // existing feature 00141 { 00142 if ( mDeletedFeatureIds.contains( fid ) ) 00143 return false; 00144 } 00145 00146 L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteFeature( this, fid ) ); 00147 return true; 00148 } 00149 00150 00151 bool QgsVectorLayerEditBuffer::changeGeometry( QgsFeatureId fid, QgsGeometry* geom ) 00152 { 00153 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeGeometries ) ) 00154 return false; 00155 00156 if ( !L->hasGeometryType() ) 00157 { 00158 return false; 00159 } 00160 00161 if ( FID_IS_NEW( fid ) ) 00162 { 00163 if ( !mAddedFeatures.contains( fid ) ) 00164 return false; 00165 } 00166 00167 // TODO: check compatible geometry 00168 00169 L->undoStack()->push( new QgsVectorLayerUndoCommandChangeGeometry( this, fid, geom ) ); 00170 return true; 00171 } 00172 00173 00174 bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field, QVariant value ) 00175 { 00176 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) ) 00177 return false; 00178 00179 if ( FID_IS_NEW( fid ) ) 00180 { 00181 if ( !mAddedFeatures.contains( fid ) ) 00182 return false; 00183 } 00184 00185 if ( field < 0 || field >= L->pendingFields().count() || 00186 L->pendingFields().fieldOrigin( field ) == QgsFields::OriginJoin ) 00187 return false; 00188 00189 L->undoStack()->push( new QgsVectorLayerUndoCommandChangeAttribute( this, fid, field, value ) ); 00190 return true; 00191 } 00192 00193 00194 bool QgsVectorLayerEditBuffer::addAttribute( const QgsField &field ) 00195 { 00196 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes ) ) 00197 return false; 00198 00199 if ( field.name().isEmpty() ) 00200 return false; 00201 00202 const QgsFields& updatedFields = L->pendingFields(); 00203 for ( int idx = 0; idx < updatedFields.count(); ++idx ) 00204 { 00205 if ( updatedFields[idx].name() == field.name() ) 00206 return false; 00207 } 00208 00209 if ( !L->dataProvider()->supportedType( field ) ) 00210 return false; 00211 00212 L->undoStack()->push( new QgsVectorLayerUndoCommandAddAttribute( this, field ) ); 00213 return true; 00214 } 00215 00216 00217 bool QgsVectorLayerEditBuffer::deleteAttribute( int index ) 00218 { 00219 if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteAttributes ) ) 00220 return false; 00221 00222 if ( index < 0 || index >= L->pendingFields().count() ) 00223 return false; 00224 00225 // find out source of the field 00226 QgsFields::FieldOrigin origin = L->pendingFields().fieldOrigin( index ); 00227 int originIndex = L->pendingFields().fieldOriginIndex( index ); 00228 00229 if ( origin == QgsFields::OriginProvider && mDeletedAttributeIds.contains( originIndex ) ) 00230 return false; 00231 00232 if ( origin == QgsFields::OriginJoin ) 00233 return false; 00234 00235 L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteAttribute( this, index ) ); 00236 return true; 00237 } 00238 00239 00240 bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors ) 00241 { 00242 QgsVectorDataProvider* provider = L->dataProvider(); 00243 commitErrors.clear(); 00244 00245 int cap = provider->capabilities(); 00246 bool success = true; 00247 00248 QgsFields oldFields = L->pendingFields(); 00249 00250 // 00251 // delete attributes 00252 // 00253 bool attributesChanged = false; 00254 if ( !mDeletedAttributeIds.isEmpty() ) 00255 { 00256 if (( cap & QgsVectorDataProvider::DeleteAttributes ) && provider->deleteAttributes( mDeletedAttributeIds.toSet() ) ) 00257 { 00258 commitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() ); 00259 00260 emit committedAttributesDeleted( L->id(), mDeletedAttributeIds ); 00261 00262 mDeletedAttributeIds.clear(); 00263 attributesChanged = true; 00264 } 00265 else 00266 { 00267 commitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() ); 00268 success = false; 00269 } 00270 } 00271 00272 // 00273 // add attributes 00274 // 00275 if ( !mAddedAttributes.isEmpty() ) 00276 { 00277 if (( cap & QgsVectorDataProvider::AddAttributes ) && provider->addAttributes( mAddedAttributes ) ) 00278 { 00279 commitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributes.size() ); 00280 00281 emit committedAttributesAdded( L->id(), mAddedAttributes ); 00282 00283 mAddedAttributes.clear(); 00284 attributesChanged = true; 00285 } 00286 else 00287 { 00288 commitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributes.size() ); 00289 success = false; 00290 } 00291 } 00292 00293 // 00294 // check that addition/removal went as expected 00295 // 00296 bool attributeChangesOk = true; 00297 if ( attributesChanged ) 00298 { 00299 L->updateFields(); 00300 QgsFields newFields = L->pendingFields(); 00301 00302 if ( oldFields.count() != newFields.count() ) 00303 { 00304 commitErrors << tr( "ERROR: the count of fields is incorrect after addition/removal of fields!" ); 00305 attributeChangesOk = false; // don't try attribute updates - they'll fail. 00306 } 00307 00308 for ( int i = 0; i < oldFields.count(); ++i ) 00309 { 00310 const QgsField& oldField = oldFields[i]; 00311 const QgsField& newField = newFields[i]; 00312 if ( attributeChangesOk && oldField != newField ) 00313 { 00314 commitErrors << tr( "ERROR: field with index %1 is not the same!" ).arg( i ); 00315 attributeChangesOk = false; // don't try attribute updates - they'll fail. 00316 } 00317 } 00318 } 00319 00320 if ( attributeChangesOk ) 00321 { 00322 // 00323 // change attributes 00324 // 00325 if ( !mChangedAttributeValues.isEmpty() ) 00326 { 00327 if (( cap & QgsVectorDataProvider::ChangeAttributeValues ) && provider->changeAttributeValues( mChangedAttributeValues ) ) 00328 { 00329 commitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() ); 00330 00331 emit committedAttributeValuesChanges( L->id(), mChangedAttributeValues ); 00332 00333 mChangedAttributeValues.clear(); 00334 } 00335 else 00336 { 00337 commitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() ); 00338 success = false; 00339 } 00340 } 00341 00342 // 00343 // delete features 00344 // 00345 if ( !mDeletedFeatureIds.isEmpty() ) 00346 { 00347 if (( cap & QgsVectorDataProvider::DeleteFeatures ) && provider->deleteFeatures( mDeletedFeatureIds ) ) 00348 { 00349 commitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() ); 00350 // TODO[MD]: we should not need this here 00351 for ( QgsFeatureIds::const_iterator it = mDeletedFeatureIds.begin(); it != mDeletedFeatureIds.end(); it++ ) 00352 { 00353 mChangedAttributeValues.remove( *it ); 00354 mChangedGeometries.remove( *it ); 00355 } 00356 00357 emit committedFeaturesRemoved( L->id(), mDeletedFeatureIds ); 00358 00359 mDeletedFeatureIds.clear(); 00360 } 00361 else 00362 { 00363 commitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() ); 00364 success = false; 00365 } 00366 } 00367 00368 // 00369 // add features 00370 // 00371 if ( !mAddedFeatures.isEmpty() ) 00372 { 00373 if ( cap & QgsVectorDataProvider::AddFeatures ) 00374 { 00375 QList<QgsFeatureId> ids = mAddedFeatures.keys(); 00376 QgsFeatureList featuresToAdd = mAddedFeatures.values(); 00377 00378 if ( provider->addFeatures( featuresToAdd ) ) 00379 { 00380 commitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", featuresToAdd.size() ); 00381 00382 emit committedFeaturesAdded( L->id(), featuresToAdd ); 00383 00384 // notify everyone that the features with temporary ids were updated with permanent ids 00385 for ( int i = 0; i < featuresToAdd.count(); ++i ) 00386 { 00387 if ( featuresToAdd[i].id() != ids[i] ) 00388 { 00389 //update selection 00390 if ( L->mSelectedFeatureIds.contains( ids[i] ) ) 00391 { 00392 L->mSelectedFeatureIds.remove( ids[i] ); 00393 L->mSelectedFeatureIds.insert( featuresToAdd[i].id() ); 00394 } 00395 emit featureDeleted( ids[i] ); 00396 emit featureAdded( featuresToAdd[i].id() ); 00397 } 00398 } 00399 00400 mAddedFeatures.clear(); 00401 } 00402 else 00403 { 00404 commitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() ); 00405 success = false; 00406 } 00407 } 00408 else 00409 { 00410 commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() ); 00411 success = false; 00412 } 00413 } 00414 } 00415 00416 // 00417 // update geometries 00418 // 00419 if ( !mChangedGeometries.isEmpty() ) 00420 { 00421 if (( cap & QgsVectorDataProvider::ChangeGeometries ) && provider->changeGeometryValues( mChangedGeometries ) ) 00422 { 00423 commitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() ); 00424 00425 emit committedGeometriesChanges( L->id(), mChangedGeometries ); 00426 00427 mChangedGeometries.clear(); 00428 } 00429 else 00430 { 00431 commitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() ); 00432 success = false; 00433 } 00434 } 00435 00436 if ( !success ) 00437 { 00438 if ( provider->hasErrors() ) 00439 { 00440 commitErrors << tr( "\n Provider errors:" ) << provider->errors(); 00441 provider->clearErrors(); 00442 } 00443 } 00444 00445 return success; 00446 } 00447 00448 00449 void QgsVectorLayerEditBuffer::rollBack() 00450 { 00451 if ( !isModified() ) 00452 return; 00453 00454 // limit canvas redraws to one by jumping to beginning of stack 00455 // see QgsUndoWidget::indexChanged 00456 L->undoStack()->setIndex( 0 ); 00457 00458 Q_ASSERT( mAddedAttributes.isEmpty() ); 00459 Q_ASSERT( mDeletedAttributeIds.isEmpty() ); 00460 Q_ASSERT( mChangedAttributeValues.isEmpty() ); 00461 Q_ASSERT( mChangedGeometries.isEmpty() ); 00462 Q_ASSERT( mAddedFeatures.isEmpty() ); 00463 } 00464 00465 00466 00467 00468 00469 /*QString QgsVectorLayerEditBuffer::dumpEditBuffer() 00470 { 00471 QString msg; 00472 if (!mChangedGeometries.isEmpty()) 00473 { 00474 msg += "CHANGED GEOMETRIES:\n"; 00475 for (QgsGeometryMap::const_iterator it = mChangedGeometries.begin(); it != mChangedGeometries.end(); ++it) 00476 { 00477 // QgsFeatureId, QgsGeometry 00478 msg += QString("- FID %1: %2").arg(it.key()).arg(it.value().to) 00479 } 00480 } 00481 return msg; 00482 }*/ 00483 00484 00485 00486 00487 void QgsVectorLayerEditBuffer::handleAttributeAdded( int index ) 00488 { 00489 // go through the changed attributes map and adapt indices 00490 for ( int i = 0; i < mChangedAttributeValues.size(); ++i ) 00491 { 00492 updateAttributeMapIndex( mChangedAttributeValues[i], index, + 1 ); 00493 } 00494 00495 // go through added features and adapt attributes 00496 QgsFeatureMap::iterator featureIt = mAddedFeatures.begin(); 00497 for ( ; featureIt != mAddedFeatures.end(); ++featureIt ) 00498 { 00499 QgsAttributes& attrs = featureIt->attributes(); 00500 attrs.insert( index, QVariant() ); 00501 } 00502 } 00503 00504 void QgsVectorLayerEditBuffer::handleAttributeDeleted( int index ) 00505 { 00506 // go through the changed attributes map and adapt indices 00507 for ( int i = 0; i < mChangedAttributeValues.size(); ++i ) 00508 { 00509 QgsAttributeMap& attrMap = mChangedAttributeValues[i]; 00510 // remove the attribute 00511 if ( attrMap.contains( index ) ) 00512 attrMap.remove( index ); 00513 00514 // update attribute indices 00515 updateAttributeMapIndex( attrMap, index, -1 ); 00516 } 00517 00518 // go through added features and adapt attributes 00519 QgsFeatureMap::iterator featureIt = mAddedFeatures.begin(); 00520 for ( ; featureIt != mAddedFeatures.end(); ++featureIt ) 00521 { 00522 QgsAttributes& attrs = featureIt->attributes(); 00523 attrs.remove( index ); 00524 } 00525 } 00526 00527 00528 00529 void QgsVectorLayerEditBuffer::updateAttributeMapIndex( QgsAttributeMap& map, int index, int offset ) const 00530 { 00531 QgsAttributeMap updatedMap; 00532 for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it ) 00533 { 00534 int attrIndex = it.key(); 00535 updatedMap.insert( attrIndex < index ? attrIndex : attrIndex + offset, it.value() ); 00536 } 00537 map = updatedMap; 00538 } 00539 00540 00541 00542 void QgsVectorLayerEditBuffer::updateLayerFields() 00543 { 00544 L->updateFields(); 00545 }