Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsvectorlayerundopassthroughcommand.cpp
3 : : ---------------------
4 : : begin : June 2017
5 : : copyright : (C) 2017 by Vincent Mora
6 : : email : vincent dot mora at oslandia dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #include "qgsvectorlayerundopassthroughcommand.h"
17 : :
18 : : #include "qgsfeatureiterator.h"
19 : : #include "qgsgeometry.h"
20 : : #include "qgsfeature.h"
21 : : #include "qgsvectorlayer.h"
22 : : #include "qgsvectorlayereditbuffer.h"
23 : :
24 : : #include "qgslogger.h"
25 : : #include "qgstransaction.h"
26 : :
27 : : #include <QUuid>
28 : :
29 : : // TODO use setObsolete instead of mHasError when upgrading qt version, this will allow auto removal of the command
30 : : // for the moment a errored command is left on the stack
31 : :
32 : 0 : QgsVectorLayerUndoPassthroughCommand::QgsVectorLayerUndoPassthroughCommand( QgsVectorLayerEditBuffer *buffer, const QString &text, bool autocreate )
33 : 0 : : QgsVectorLayerUndoCommand( buffer )
34 : 0 : , mSavePointId( ( mBuffer->L->isEditCommandActive() && !mBuffer->L->dataProvider()->transaction()->savePoints().isEmpty() )
35 : 0 : || !autocreate
36 : 0 : ? mBuffer->L->dataProvider()->transaction()->savePoints().last()
37 : 0 : : mBuffer->L->dataProvider()->transaction()->createSavepoint( mError ) )
38 : 0 : , mHasError( !mError.isEmpty() )
39 : 0 : , mRecreateSavePoint( mBuffer->L->isEditCommandActive()
40 : 0 : ? !mBuffer->L->dataProvider()->transaction()->lastSavePointIsDirty()
41 : : : true )
42 : 0 : {
43 : : // the first command in the undo stack macro will have a clean save point
44 : : // the first command is responsible to re-create the savepoint after undo
45 : 0 : setText( text );
46 : 0 : }
47 : :
48 : :
49 : 0 : void QgsVectorLayerUndoPassthroughCommand::setError()
50 : : {
51 : 0 : if ( !mHasError )
52 : : {
53 : 0 : setText( text() + " " + QObject::tr( "failed" ) );
54 : 0 : mHasError = true;
55 : 0 : }
56 : 0 : }
57 : :
58 : 0 : void QgsVectorLayerUndoPassthroughCommand::setErrorMessage( const QString &errorMessage )
59 : : {
60 : 0 : mError = errorMessage;
61 : 0 : }
62 : :
63 : 0 : QString QgsVectorLayerUndoPassthroughCommand::errorMessage() const
64 : : {
65 : 0 : return mError;
66 : : }
67 : :
68 : 0 : bool QgsVectorLayerUndoPassthroughCommand::setSavePoint( const QString &savePointId )
69 : : {
70 : 0 : if ( !hasError() )
71 : : {
72 : 0 : if ( savePointId.isEmpty() )
73 : : {
74 : : // re-create savepoint only if mRecreateSavePoint and rollBackToSavePoint as occurred
75 : 0 : if ( mRecreateSavePoint && mBuffer->L->dataProvider()->transaction()->savePoints().indexOf( mSavePointId ) == -1 )
76 : : {
77 : 0 : mSavePointId = mBuffer->L->dataProvider()->transaction()->createSavepoint( mSavePointId, mError );
78 : 0 : if ( mSavePointId.isEmpty() )
79 : : {
80 : 0 : setError();
81 : 0 : }
82 : 0 : }
83 : 0 : }
84 : : else
85 : : {
86 : 0 : mSavePointId = savePointId;
87 : : }
88 : 0 : }
89 : 0 : return !hasError();
90 : 0 : }
91 : :
92 : 0 : bool QgsVectorLayerUndoPassthroughCommand::rollBackToSavePoint()
93 : : {
94 : : // rollback only occurs for the last command in undo macro
95 : 0 : if ( !hasError() && mBuffer->L->dataProvider()->transaction()->savePoints().indexOf( mSavePointId ) != -1 )
96 : : {
97 : 0 : if ( !mBuffer->L->dataProvider()->transaction()->rollbackToSavepoint( mSavePointId, mError ) )
98 : : {
99 : 0 : setError();
100 : 0 : }
101 : 0 : }
102 : 0 : return !hasError();
103 : 0 : }
104 : :
105 : :
106 : 0 : QgsVectorLayerUndoPassthroughCommandAddFeatures::QgsVectorLayerUndoPassthroughCommandAddFeatures( QgsVectorLayerEditBuffer *buffer, QgsFeatureList &features )
107 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "add features" ) )
108 : 0 : {
109 : : static int sAddedIdLowWaterMark = -1;
110 : 0 : for ( const QgsFeature &f : std::as_const( features ) )
111 : : {
112 : 0 : mInitialFeatures << f;
113 : : //assign a temporary id to the feature (use negative numbers)
114 : 0 : sAddedIdLowWaterMark--;
115 : 0 : mInitialFeatures.last().setId( sAddedIdLowWaterMark );
116 : : }
117 : 0 : mFeatures = mInitialFeatures;
118 : :
119 : 0 : }
120 : :
121 : 0 : void QgsVectorLayerUndoPassthroughCommandAddFeatures::undo()
122 : : {
123 : 0 : if ( rollBackToSavePoint() )
124 : : {
125 : 0 : for ( const QgsFeature &f : std::as_const( mFeatures ) )
126 : : {
127 : 0 : mBuffer->mAddedFeatures.remove( f.id() );
128 : 0 : emit mBuffer->featureDeleted( f.id() );
129 : : }
130 : 0 : mFeatures = mInitialFeatures;
131 : 0 : }
132 : 0 : }
133 : :
134 : 0 : void QgsVectorLayerUndoPassthroughCommandAddFeatures::redo()
135 : : {
136 : 0 : mFeatures = mInitialFeatures;
137 : 0 : mBuffer->L->dataProvider()->clearErrors();
138 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->addFeatures( mFeatures ) && ! mBuffer->L->dataProvider()->hasErrors() )
139 : : {
140 : 0 : for ( const QgsFeature &f : std::as_const( mFeatures ) )
141 : : {
142 : 0 : mBuffer->mAddedFeatures.insert( f.id(), f );
143 : 0 : emit mBuffer->featureAdded( f.id() );
144 : : }
145 : 0 : }
146 : : else
147 : : {
148 : 0 : setError();
149 : : }
150 : 0 : }
151 : :
152 : 0 : QgsVectorLayerUndoPassthroughCommandDeleteFeatures::QgsVectorLayerUndoPassthroughCommandDeleteFeatures( QgsVectorLayerEditBuffer *buffer, const QgsFeatureIds &fids )
153 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "delete features" ) )
154 : 0 : , mFids( fids )
155 : 0 : {
156 : 0 : }
157 : :
158 : 0 : void QgsVectorLayerUndoPassthroughCommandDeleteFeatures::undo()
159 : : {
160 : 0 : if ( rollBackToSavePoint() )
161 : : {
162 : 0 : for ( const QgsFeatureId &fid : mFids )
163 : : {
164 : 0 : mBuffer->mDeletedFeatureIds.remove( fid );
165 : 0 : if ( mDeletedNewFeatures.contains( fid ) )
166 : : {
167 : 0 : mBuffer->mAddedFeatures.insert( fid, mDeletedNewFeatures.value( fid ) );
168 : 0 : }
169 : 0 : emit mBuffer->featureAdded( fid );
170 : : }
171 : 0 : }
172 : 0 : }
173 : :
174 : 0 : void QgsVectorLayerUndoPassthroughCommandDeleteFeatures::redo()
175 : : {
176 : 0 : mBuffer->L->dataProvider()->clearErrors();
177 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->deleteFeatures( mFids ) && ! mBuffer->L->dataProvider()->hasErrors() )
178 : : {
179 : 0 : mDeletedNewFeatures.clear();
180 : 0 : for ( const QgsFeatureId &fid : mFids )
181 : : {
182 : 0 : if ( mBuffer->mAddedFeatures.contains( fid ) )
183 : : {
184 : 0 : mDeletedNewFeatures.insert( fid, mBuffer->mAddedFeatures[ fid ] );
185 : 0 : mBuffer->mAddedFeatures.remove( fid );
186 : 0 : }
187 : : else
188 : : {
189 : 0 : mBuffer->mDeletedFeatureIds.insert( fid );
190 : : }
191 : 0 : emit mBuffer->featureDeleted( fid );
192 : : }
193 : 0 : }
194 : : else
195 : : {
196 : 0 : setError();
197 : : }
198 : 0 : }
199 : :
200 : 0 : QgsVectorLayerUndoPassthroughCommandChangeGeometry::QgsVectorLayerUndoPassthroughCommandChangeGeometry( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsGeometry &geom )
201 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "change geometry" ) )
202 : 0 : , mFid( fid )
203 : 0 : , mNewGeom( geom )
204 : 0 : , mOldGeom( mBuffer->L->getFeature( mFid ).geometry() )
205 : 0 : , mFirstChange( true )
206 : 0 : {
207 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
208 : : {
209 : 0 : mFirstChange = false;
210 : 0 : }
211 : 0 : else if ( mBuffer->mChangedGeometries.contains( mFid ) )
212 : : {
213 : 0 : mFirstChange = false;
214 : 0 : mOldGeom = mBuffer->mChangedGeometries[mFid];
215 : 0 : }
216 : 0 : }
217 : :
218 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeGeometry::undo()
219 : : {
220 : 0 : if ( rollBackToSavePoint() )
221 : : {
222 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
223 : : {
224 : 0 : mBuffer->mAddedFeatures[ mFid ].setGeometry( mOldGeom );
225 : 0 : }
226 : 0 : else if ( mFirstChange )
227 : : {
228 : 0 : mBuffer->mChangedGeometries.remove( mFid );
229 : 0 : }
230 : : else
231 : : {
232 : 0 : mBuffer->mChangedGeometries[mFid] = mOldGeom;
233 : : }
234 : 0 : emit mBuffer->geometryChanged( mFid, mOldGeom );
235 : 0 : }
236 : 0 : }
237 : :
238 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeGeometry::redo()
239 : : {
240 : 0 : QgsGeometryMap geomMap;
241 : 0 : geomMap.insert( mFid, mNewGeom );
242 : 0 : mBuffer->L->dataProvider()->clearErrors();
243 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->changeGeometryValues( geomMap ) && ! mBuffer->L->dataProvider()->hasErrors() )
244 : : {
245 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
246 : : {
247 : 0 : mBuffer->mAddedFeatures[ mFid ].setGeometry( mNewGeom );
248 : 0 : }
249 : : else
250 : : {
251 : 0 : mBuffer->mChangedGeometries[ mFid ] = mNewGeom;
252 : : }
253 : 0 : emit mBuffer->geometryChanged( mFid, mNewGeom );
254 : 0 : }
255 : : else
256 : : {
257 : 0 : setError();
258 : : }
259 : 0 : }
260 : :
261 : 0 : bool QgsVectorLayerUndoPassthroughCommandChangeGeometry::mergeWith( const QUndoCommand *other )
262 : : {
263 : 0 : if ( other->id() != id() )
264 : 0 : return false;
265 : :
266 : 0 : const QgsVectorLayerUndoPassthroughCommandChangeGeometry *merge = dynamic_cast<const QgsVectorLayerUndoPassthroughCommandChangeGeometry *>( other );
267 : 0 : if ( !merge )
268 : 0 : return false;
269 : :
270 : 0 : if ( merge->mFid != mFid )
271 : 0 : return false;
272 : :
273 : 0 : mNewGeom = merge->mNewGeom;
274 : 0 : merge->mNewGeom = QgsGeometry();
275 : :
276 : 0 : return true;
277 : 0 : }
278 : :
279 : :
280 : :
281 : 0 : QgsVectorLayerUndoPassthroughCommandChangeAttribute::QgsVectorLayerUndoPassthroughCommandChangeAttribute( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int field, const QVariant &newValue )
282 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "change attribute value" ) )
283 : 0 : , mFid( fid )
284 : 0 : , mFieldIndex( field )
285 : 0 : , mNewValue( newValue )
286 : 0 : , mOldValue( mBuffer->L->getFeature( mFid ).attribute( field ) )
287 : 0 : , mFirstChange( true )
288 : 0 : {
289 : :
290 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
291 : : {
292 : : // work with added feature
293 : 0 : QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
294 : : Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
295 : 0 : if ( it.value().attribute( mFieldIndex ).isValid() )
296 : : {
297 : 0 : mOldValue = it.value().attribute( mFieldIndex );
298 : 0 : mFirstChange = false;
299 : 0 : }
300 : 0 : }
301 : 0 : else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( mFieldIndex ) )
302 : : {
303 : 0 : mOldValue = mBuffer->mChangedAttributeValues[mFid][mFieldIndex];
304 : 0 : mFirstChange = false;
305 : 0 : }
306 : 0 : }
307 : :
308 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttribute::undo()
309 : : {
310 : 0 : if ( rollBackToSavePoint() )
311 : : {
312 : 0 : QVariant original = mOldValue;
313 : :
314 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
315 : : {
316 : : // added feature
317 : 0 : QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
318 : : Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
319 : 0 : it.value().setAttribute( mFieldIndex, mOldValue );
320 : 0 : }
321 : 0 : else if ( mFirstChange )
322 : : {
323 : : // existing feature
324 : 0 : mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex );
325 : 0 : if ( mBuffer->mChangedAttributeValues[mFid].isEmpty() )
326 : 0 : mBuffer->mChangedAttributeValues.remove( mFid );
327 : :
328 : 0 : if ( !mOldValue.isValid() )
329 : : {
330 : : // get old value from provider
331 : 0 : QgsFeature tmp;
332 : 0 : QgsFeatureRequest request;
333 : 0 : request.setFilterFid( mFid );
334 : 0 : request.setFlags( QgsFeatureRequest::NoGeometry );
335 : 0 : request.setSubsetOfAttributes( QgsAttributeList() << mFieldIndex );
336 : 0 : std::unique_ptr<QgsVectorLayer> layerClone( layer()->clone() );
337 : 0 : QgsFeatureIterator fi = layerClone->getFeatures( request );
338 : 0 : if ( fi.nextFeature( tmp ) )
339 : 0 : original = tmp.attribute( mFieldIndex );
340 : 0 : }
341 : 0 : }
342 : : else
343 : : {
344 : 0 : mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue;
345 : : }
346 : 0 : emit mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
347 : 0 : }
348 : 0 : }
349 : :
350 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttribute::redo()
351 : : {
352 : 0 : QgsAttributeMap map;
353 : 0 : map.insert( mFieldIndex, mNewValue );
354 : 0 : QgsChangedAttributesMap attribMap;
355 : 0 : attribMap.insert( mFid, map );
356 : 0 : mBuffer->L->dataProvider()->clearErrors();
357 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && ! mBuffer->L->dataProvider()->hasErrors() )
358 : : {
359 : : // Update existing feature
360 : 0 : QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
361 : 0 : if ( it != mBuffer->mAddedFeatures.end() )
362 : : {
363 : 0 : it.value().setAttribute( mFieldIndex, mNewValue );
364 : 0 : }
365 : : else
366 : : {
367 : : // changed attribute of existing feature
368 : 0 : if ( !mBuffer->mChangedAttributeValues.contains( mFid ) )
369 : : {
370 : 0 : mBuffer->mChangedAttributeValues.insert( mFid, QgsAttributeMap() );
371 : 0 : }
372 : :
373 : 0 : mBuffer->mChangedAttributeValues[mFid].insert( mFieldIndex, mNewValue );
374 : : }
375 : 0 : emit mBuffer->attributeValueChanged( mFid, mFieldIndex, mNewValue );
376 : 0 : }
377 : : else
378 : : {
379 : 0 : setError();
380 : : }
381 : 0 : }
382 : :
383 : 0 : QgsVectorLayerUndoPassthroughCommandAddAttribute::QgsVectorLayerUndoPassthroughCommandAddAttribute( QgsVectorLayerEditBuffer *buffer, const QgsField &field )
384 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "add attribute" ) + " " + field.name() )
385 : 0 : , mField( field )
386 : 0 : {
387 : 0 : }
388 : :
389 : 0 : void QgsVectorLayerUndoPassthroughCommandAddAttribute::undo()
390 : : {
391 : : // note that the deleteAttribute here is only necessary to inform the provider that
392 : : // an attribute is removed after the rollBackToSavePoint
393 : 0 : const int attr = mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
394 : 0 : if ( rollBackToSavePoint() )
395 : : {
396 : 0 : mBuffer->L->dataProvider()->deleteAttributes( QgsAttributeIds() << attr );
397 : 0 : mBuffer->mAddedAttributes.removeAll( mField );
398 : 0 : mBuffer->updateLayerFields();
399 : 0 : emit mBuffer->attributeDeleted( attr );
400 : 0 : }
401 : : else
402 : : {
403 : 0 : setError();
404 : : }
405 : 0 : }
406 : :
407 : 0 : void QgsVectorLayerUndoPassthroughCommandAddAttribute::redo()
408 : : {
409 : 0 : mBuffer->L->dataProvider()->clearErrors();
410 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && ! mBuffer->L->dataProvider()->hasErrors() )
411 : : {
412 : 0 : mBuffer->updateLayerFields();
413 : 0 : const int attr = mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
414 : 0 : mBuffer->mAddedAttributes.append( mField );
415 : 0 : emit mBuffer->attributeAdded( attr );
416 : 0 : }
417 : : else
418 : : {
419 : 0 : setError();
420 : : }
421 : 0 : }
422 : :
423 : 0 : QgsVectorLayerUndoPassthroughCommandDeleteAttribute::QgsVectorLayerUndoPassthroughCommandDeleteAttribute( QgsVectorLayerEditBuffer *buffer, int attr )
424 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "delete attribute" ) )
425 : 0 : , mField( mBuffer->L->fields()[ attr ] )
426 : 0 : , mOriginalFieldIndex( attr )
427 : 0 : {
428 : 0 : }
429 : :
430 : 0 : void QgsVectorLayerUndoPassthroughCommandDeleteAttribute::undo()
431 : : {
432 : : // note that the addAttributes here is only necessary to inform the provider that
433 : : // an attribute is added back after the rollBackToSavePoint
434 : 0 : mBuffer->L->dataProvider()->clearErrors();
435 : 0 : if ( mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && rollBackToSavePoint() && ! mBuffer->L->dataProvider()->hasErrors() )
436 : : {
437 : 0 : mBuffer->mDeletedAttributeIds.removeOne( mOriginalFieldIndex );
438 : 0 : mBuffer->updateLayerFields();
439 : 0 : emit mBuffer->attributeAdded( mOriginalFieldIndex );
440 : 0 : }
441 : : else
442 : : {
443 : 0 : setError();
444 : : }
445 : 0 : }
446 : :
447 : 0 : void QgsVectorLayerUndoPassthroughCommandDeleteAttribute::redo()
448 : : {
449 : 0 : mBuffer->L->dataProvider()->clearErrors();
450 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->deleteAttributes( QgsAttributeIds() << mOriginalFieldIndex ) && ! mBuffer->L->dataProvider()->hasErrors() )
451 : : {
452 : 0 : mBuffer->mDeletedAttributeIds.append( mOriginalFieldIndex );
453 : 0 : mBuffer->updateLayerFields();
454 : 0 : emit mBuffer->attributeDeleted( mOriginalFieldIndex );
455 : 0 : }
456 : : else
457 : : {
458 : 0 : setError();
459 : : }
460 : 0 : }
461 : :
462 : 0 : QgsVectorLayerUndoPassthroughCommandRenameAttribute::QgsVectorLayerUndoPassthroughCommandRenameAttribute( QgsVectorLayerEditBuffer *buffer, int attr, const QString &newName )
463 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "rename attribute" ) + " " + newName )
464 : 0 : , mAttr( attr )
465 : 0 : , mNewName( newName )
466 : 0 : , mOldName( mBuffer->L->fields()[ mAttr ].name() )
467 : 0 : {
468 : 0 : }
469 : :
470 : 0 : void QgsVectorLayerUndoPassthroughCommandRenameAttribute::undo()
471 : : {
472 : : // note that the renameAttributes here is only necessary to inform the provider that
473 : : // an attribute is renamed after the rollBackToSavePoint
474 : 0 : QgsFieldNameMap map;
475 : 0 : map[ mAttr ] = mOldName;
476 : 0 : mBuffer->L->dataProvider()->clearErrors();
477 : 0 : if ( mBuffer->L->dataProvider()->renameAttributes( map ) && rollBackToSavePoint() && ! mBuffer->L->dataProvider()->hasErrors() )
478 : : {
479 : 0 : mBuffer->updateLayerFields();
480 : 0 : emit mBuffer->attributeRenamed( mAttr, mOldName );
481 : 0 : }
482 : : else
483 : : {
484 : 0 : setError();
485 : : }
486 : 0 : }
487 : :
488 : 0 : void QgsVectorLayerUndoPassthroughCommandRenameAttribute::redo()
489 : : {
490 : 0 : QgsFieldNameMap map;
491 : 0 : map[ mAttr ] = mNewName;
492 : 0 : mBuffer->L->dataProvider()->clearErrors();
493 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->renameAttributes( map ) && ! mBuffer->L->dataProvider()->hasErrors() )
494 : : {
495 : 0 : mBuffer->updateLayerFields();
496 : 0 : emit mBuffer->attributeRenamed( mAttr, mNewName );
497 : 0 : }
498 : : else
499 : : {
500 : 0 : setError();
501 : : }
502 : 0 : }
503 : :
504 : 0 : QgsVectorLayerUndoPassthroughCommandUpdate::QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer, QgsTransaction *transaction, const QString &sql, const QString &name )
505 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, name.isEmpty() ? QObject::tr( "custom transaction" ) : name, false )
506 : 0 : , mTransaction( transaction )
507 : 0 : , mSql( sql )
508 : 0 : {
509 : 0 : }
510 : :
511 : 0 : void QgsVectorLayerUndoPassthroughCommandUpdate::undo()
512 : : {
513 : 0 : if ( rollBackToSavePoint() )
514 : : {
515 : 0 : mUndone = true;
516 : 0 : emit mBuffer->L->layerModified();
517 : 0 : }
518 : : else
519 : : {
520 : 0 : setError();
521 : : }
522 : 0 : }
523 : :
524 : 0 : void QgsVectorLayerUndoPassthroughCommandUpdate::redo()
525 : : {
526 : : // the first time that the sql query is execute is within QgsTransaction
527 : : // itself. So the redo has to be executed only after an undo action.
528 : 0 : if ( mUndone )
529 : : {
530 : 0 : QString errorMessage;
531 : :
532 : 0 : QString savePointId = mTransaction->createSavepoint( errorMessage );
533 : :
534 : 0 : if ( errorMessage.isEmpty() )
535 : : {
536 : 0 : setSavePoint( savePointId );
537 : :
538 : 0 : if ( mTransaction->executeSql( mSql, errorMessage ) )
539 : : {
540 : 0 : mUndone = false;
541 : 0 : }
542 : : else
543 : : {
544 : 0 : setErrorMessage( errorMessage );
545 : 0 : setError();
546 : : }
547 : 0 : }
548 : : else
549 : : {
550 : 0 : setErrorMessage( errorMessage );
551 : 0 : setError();
552 : : }
553 : 0 : }
554 : 0 : }
555 : :
556 : 0 : QgsVectorLayerUndoPassthroughCommandChangeAttributes::QgsVectorLayerUndoPassthroughCommandChangeAttributes( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues )
557 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "change attribute value" ) )
558 : 0 : , mFid( fid )
559 : 0 : , mNewValues( newValues )
560 : 0 : , mOldValues( oldValues )
561 : 0 : {
562 : 0 : if ( mOldValues.isEmpty() )
563 : : {
564 : 0 : const auto oldAttrs( mBuffer->L->getFeature( mFid ).attributes() );
565 : 0 : for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
566 : : {
567 : 0 : mOldValues[ it.key() ] = oldAttrs[ it.key() ];
568 : 0 : }
569 : 0 : }
570 : 0 : const bool isAdded { mBuffer->mAddedFeatures.contains( mFid ) };
571 : 0 : for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
572 : : {
573 : 0 : if ( isAdded && mBuffer->mAddedFeatures[ mFid ].attribute( it.key() ).isValid() )
574 : : {
575 : 0 : mFirstChanges[ it.key() ] = false;
576 : 0 : }
577 : 0 : else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( it.key() ) )
578 : : {
579 : 0 : mFirstChanges[ it.key() ] = false;
580 : 0 : }
581 : : else
582 : : {
583 : 0 : mFirstChanges[ it.key() ] = true;
584 : : }
585 : 0 : }
586 : 0 : }
587 : :
588 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttributes::undo()
589 : : {
590 : 0 : if ( rollBackToSavePoint() )
591 : : {
592 : 0 : QgsFeatureMap::iterator addedIt = mBuffer->mAddedFeatures.find( mFid );
593 : 0 : for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
594 : : {
595 : 0 : const auto fieldIndex { it.key() };
596 : 0 : if ( addedIt != mBuffer->mAddedFeatures.end() )
597 : : {
598 : 0 : addedIt.value().setAttribute( fieldIndex, mOldValues[ it.key() ] );
599 : 0 : }
600 : 0 : else if ( mFirstChanges.contains( fieldIndex ) && mFirstChanges[ fieldIndex ] )
601 : : {
602 : : // existing feature
603 : 0 : mBuffer->mChangedAttributeValues[mFid].remove( fieldIndex );
604 : 0 : }
605 : : else
606 : : {
607 : : // changed attribute of existing feature
608 : 0 : if ( !mBuffer->mChangedAttributeValues.contains( mFid ) )
609 : : {
610 : 0 : mBuffer->mChangedAttributeValues.insert( mFid, QgsAttributeMap() );
611 : 0 : }
612 : 0 : mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, mOldValues[ it.key() ] );
613 : : }
614 : 0 : emit mBuffer->attributeValueChanged( mFid, it.key(), mOldValues[ it.key() ] );
615 : 0 : }
616 : 0 : if ( mBuffer->mChangedAttributeValues[mFid].isEmpty() )
617 : 0 : mBuffer->mChangedAttributeValues.remove( mFid );
618 : 0 : }
619 : 0 : }
620 : :
621 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttributes::redo()
622 : : {
623 : 0 : QgsChangedAttributesMap attribMap;
624 : 0 : attribMap.insert( mFid, mNewValues );
625 : 0 : mBuffer->L->dataProvider()->clearErrors();
626 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && ! mBuffer->L->dataProvider()->hasErrors() )
627 : : {
628 : 0 : QgsFeatureMap::iterator addedIt = mBuffer->mAddedFeatures.find( mFid );
629 : 0 : for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
630 : : {
631 : 0 : const auto fieldIndex { it.key() };
632 : : // Update existing feature
633 : 0 : if ( addedIt != mBuffer->mAddedFeatures.end() )
634 : : {
635 : 0 : addedIt.value().setAttribute( fieldIndex, it.value() );
636 : 0 : }
637 : : else
638 : : {
639 : : // changed attribute of existing feature
640 : 0 : if ( !mBuffer->mChangedAttributeValues.contains( mFid ) )
641 : : {
642 : 0 : mBuffer->mChangedAttributeValues.insert( mFid, QgsAttributeMap() );
643 : 0 : }
644 : 0 : mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, it.value() );
645 : : }
646 : 0 : emit mBuffer->attributeValueChanged( mFid, it.key(), it.value() );
647 : 0 : }
648 : 0 : }
649 : 0 : }
|