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 : {
206 : 0 : }
207 : :
208 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeGeometry::undo()
209 : : {
210 : 0 : if ( rollBackToSavePoint() )
211 : : {
212 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
213 : : {
214 : 0 : mBuffer->mAddedFeatures[ mFid ].setGeometry( mOldGeom );
215 : 0 : }
216 : : else
217 : : {
218 : 0 : QgsFeature tmp;
219 : 0 : QgsFeatureRequest request;
220 : 0 : request.setFilterFid( mFid );
221 : 0 : request.setSubsetOfAttributes( {} );
222 : 0 : std::unique_ptr<QgsVectorLayer> layerClone( layer()->clone() );
223 : 0 : QgsFeatureIterator fi = layerClone->getFeatures( request );
224 : 0 : if ( fi.nextFeature( tmp ) && tmp.geometry().equals( mOldGeom ) )
225 : : {
226 : 0 : mBuffer->mChangedGeometries.remove( mFid );
227 : 0 : }
228 : : else
229 : : {
230 : 0 : mBuffer->mChangedGeometries[mFid] = mOldGeom;
231 : : }
232 : 0 : }
233 : 0 : }
234 : 0 : }
235 : :
236 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeGeometry::redo()
237 : : {
238 : 0 : QgsGeometryMap geomMap;
239 : 0 : geomMap.insert( mFid, mNewGeom );
240 : 0 : mBuffer->L->dataProvider()->clearErrors();
241 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->changeGeometryValues( geomMap ) && ! mBuffer->L->dataProvider()->hasErrors() )
242 : : {
243 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
244 : : {
245 : 0 : mBuffer->mAddedFeatures[ mFid ].setGeometry( mNewGeom );
246 : 0 : }
247 : : else
248 : : {
249 : 0 : mBuffer->mChangedGeometries[ mFid ] = mNewGeom;
250 : : }
251 : 0 : emit mBuffer->geometryChanged( mFid, mNewGeom );
252 : 0 : }
253 : : else
254 : : {
255 : 0 : setError();
256 : : }
257 : 0 : }
258 : :
259 : 0 : bool QgsVectorLayerUndoPassthroughCommandChangeGeometry::mergeWith( const QUndoCommand *other )
260 : : {
261 : 0 : if ( other->id() != id() )
262 : 0 : return false;
263 : :
264 : 0 : const QgsVectorLayerUndoPassthroughCommandChangeGeometry *merge = dynamic_cast<const QgsVectorLayerUndoPassthroughCommandChangeGeometry *>( other );
265 : 0 : if ( !merge )
266 : 0 : return false;
267 : :
268 : 0 : if ( merge->mFid != mFid )
269 : 0 : return false;
270 : :
271 : 0 : mNewGeom = merge->mNewGeom;
272 : 0 : merge->mNewGeom = QgsGeometry();
273 : :
274 : 0 : return true;
275 : 0 : }
276 : :
277 : :
278 : :
279 : 0 : QgsVectorLayerUndoPassthroughCommandChangeAttribute::QgsVectorLayerUndoPassthroughCommandChangeAttribute( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int field, const QVariant &newValue )
280 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "change attribute value" ) )
281 : 0 : , mFid( fid )
282 : 0 : , mFieldIndex( field )
283 : 0 : , mNewValue( newValue )
284 : 0 : , mOldValue( mBuffer->L->getFeature( mFid ).attribute( field ) )
285 : 0 : , mFirstChange( true )
286 : 0 : {
287 : :
288 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
289 : : {
290 : : // work with added feature
291 : 0 : QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
292 : : Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
293 : 0 : if ( it.value().attribute( mFieldIndex ).isValid() )
294 : : {
295 : 0 : mOldValue = it.value().attribute( mFieldIndex );
296 : 0 : mFirstChange = false;
297 : 0 : }
298 : 0 : }
299 : 0 : else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( mFieldIndex ) )
300 : : {
301 : 0 : mOldValue = mBuffer->mChangedAttributeValues[mFid][mFieldIndex];
302 : 0 : mFirstChange = false;
303 : 0 : }
304 : 0 : }
305 : :
306 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttribute::undo()
307 : : {
308 : 0 : if ( rollBackToSavePoint() )
309 : : {
310 : 0 : QVariant original = mOldValue;
311 : :
312 : 0 : if ( mBuffer->mAddedFeatures.contains( mFid ) )
313 : : {
314 : : // added feature
315 : 0 : QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
316 : : Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
317 : 0 : it.value().setAttribute( mFieldIndex, mOldValue );
318 : 0 : }
319 : 0 : else if ( mFirstChange )
320 : : {
321 : : // existing feature
322 : 0 : mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex );
323 : 0 : if ( mBuffer->mChangedAttributeValues[mFid].isEmpty() )
324 : 0 : mBuffer->mChangedAttributeValues.remove( mFid );
325 : :
326 : 0 : if ( !mOldValue.isValid() )
327 : : {
328 : : // get old value from provider
329 : 0 : QgsFeature tmp;
330 : 0 : QgsFeatureRequest request;
331 : 0 : request.setFilterFid( mFid );
332 : 0 : request.setFlags( QgsFeatureRequest::NoGeometry );
333 : 0 : request.setSubsetOfAttributes( QgsAttributeList() << mFieldIndex );
334 : 0 : std::unique_ptr<QgsVectorLayer> layerClone( layer()->clone() );
335 : 0 : QgsFeatureIterator fi = layerClone->getFeatures( request );
336 : 0 : if ( fi.nextFeature( tmp ) )
337 : 0 : original = tmp.attribute( mFieldIndex );
338 : 0 : }
339 : 0 : }
340 : : else
341 : : {
342 : 0 : mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue;
343 : : }
344 : 0 : emit mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
345 : 0 : }
346 : 0 : }
347 : 0 :
348 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttribute::redo()
349 : : {
350 : 0 : QgsAttributeMap map;
351 : 0 : map.insert( mFieldIndex, mNewValue );
352 : 0 : QgsChangedAttributesMap attribMap;
353 : 0 : attribMap.insert( mFid, map );
354 : 0 : mBuffer->L->dataProvider()->clearErrors();
355 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && ! mBuffer->L->dataProvider()->hasErrors() )
356 : : {
357 : : // Update existing feature
358 : 0 : QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
359 : 0 : if ( it != mBuffer->mAddedFeatures.end() )
360 : : {
361 : 0 : it.value().setAttribute( mFieldIndex, mNewValue );
362 : 0 : }
363 : : else
364 : : {
365 : : // changed attribute of existing feature
366 : 0 : if ( !mBuffer->mChangedAttributeValues.contains( mFid ) )
367 : : {
368 : 0 : mBuffer->mChangedAttributeValues.insert( mFid, QgsAttributeMap() );
369 : 0 : }
370 : :
371 : 0 : mBuffer->mChangedAttributeValues[mFid].insert( mFieldIndex, mNewValue );
372 : : }
373 : 0 : emit mBuffer->attributeValueChanged( mFid, mFieldIndex, mNewValue );
374 : 0 : }
375 : : else
376 : : {
377 : 0 : setError();
378 : : }
379 : 0 : }
380 : :
381 : 0 : QgsVectorLayerUndoPassthroughCommandAddAttribute::QgsVectorLayerUndoPassthroughCommandAddAttribute( QgsVectorLayerEditBuffer *buffer, const QgsField &field )
382 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "add attribute" ) + " " + field.name() )
383 : 0 : , mField( field )
384 : 0 : {
385 : 0 : }
386 : :
387 : 0 : void QgsVectorLayerUndoPassthroughCommandAddAttribute::undo()
388 : : {
389 : : // note that the deleteAttribute here is only necessary to inform the provider that
390 : : // an attribute is removed after the rollBackToSavePoint
391 : 0 : const int attr = mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
392 : 0 : if ( rollBackToSavePoint() )
393 : : {
394 : 0 : mBuffer->L->dataProvider()->deleteAttributes( QgsAttributeIds() << attr );
395 : 0 : mBuffer->mAddedAttributes.removeAll( mField );
396 : 0 : mBuffer->updateLayerFields();
397 : 0 : emit mBuffer->attributeDeleted( attr );
398 : 0 : }
399 : : else
400 : : {
401 : 0 : setError();
402 : : }
403 : 0 : }
404 : :
405 : 0 : void QgsVectorLayerUndoPassthroughCommandAddAttribute::redo()
406 : : {
407 : 0 : mBuffer->L->dataProvider()->clearErrors();
408 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && ! mBuffer->L->dataProvider()->hasErrors() )
409 : : {
410 : 0 : mBuffer->updateLayerFields();
411 : 0 : const int attr = mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
412 : 0 : mBuffer->mAddedAttributes.append( mField );
413 : 0 : emit mBuffer->attributeAdded( attr );
414 : 0 : }
415 : : else
416 : : {
417 : 0 : setError();
418 : : }
419 : 0 : }
420 : :
421 : 0 : QgsVectorLayerUndoPassthroughCommandDeleteAttribute::QgsVectorLayerUndoPassthroughCommandDeleteAttribute( QgsVectorLayerEditBuffer *buffer, int attr )
422 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "delete attribute" ) )
423 : 0 : , mField( mBuffer->L->fields()[ attr ] )
424 : 0 : {
425 : 0 : }
426 : :
427 : 0 : void QgsVectorLayerUndoPassthroughCommandDeleteAttribute::undo()
428 : : {
429 : : // note that the addAttributes here is only necessary to inform the provider that
430 : : // an attribute is added back after the rollBackToSavePoint
431 : 0 : mBuffer->L->dataProvider()->clearErrors();
432 : 0 : if ( mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && rollBackToSavePoint() && ! mBuffer->L->dataProvider()->hasErrors() )
433 : : {
434 : 0 : mBuffer->updateLayerFields();
435 : 0 : const int attr = mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
436 : 0 : emit mBuffer->attributeAdded( attr );
437 : 0 : }
438 : : else
439 : : {
440 : 0 : setError();
441 : : }
442 : 0 : }
443 : :
444 : 0 : void QgsVectorLayerUndoPassthroughCommandDeleteAttribute::redo()
445 : : {
446 : 0 : const int attr = mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
447 : 0 : mBuffer->L->dataProvider()->clearErrors();
448 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->deleteAttributes( QgsAttributeIds() << attr ) && ! mBuffer->L->dataProvider()->hasErrors() )
449 : : {
450 : 0 : mBuffer->updateLayerFields();
451 : 0 : emit mBuffer->attributeDeleted( attr );
452 : 0 : }
453 : : else
454 : : {
455 : 0 : setError();
456 : : }
457 : 0 : }
458 : :
459 : 0 : QgsVectorLayerUndoPassthroughCommandRenameAttribute::QgsVectorLayerUndoPassthroughCommandRenameAttribute( QgsVectorLayerEditBuffer *buffer, int attr, const QString &newName )
460 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "rename attribute" ) + " " + newName )
461 : 0 : , mAttr( attr )
462 : 0 : , mNewName( newName )
463 : 0 : , mOldName( mBuffer->L->fields()[ mAttr ].name() )
464 : 0 : {
465 : 0 : }
466 : :
467 : 0 : void QgsVectorLayerUndoPassthroughCommandRenameAttribute::undo()
468 : : {
469 : : // note that the renameAttributes here is only necessary to inform the provider that
470 : : // an attribute is renamed after the rollBackToSavePoint
471 : 0 : QgsFieldNameMap map;
472 : 0 : map[ mAttr ] = mOldName;
473 : 0 : mBuffer->L->dataProvider()->clearErrors();
474 : 0 : if ( mBuffer->L->dataProvider()->renameAttributes( map ) && rollBackToSavePoint() && ! mBuffer->L->dataProvider()->hasErrors() )
475 : : {
476 : 0 : mBuffer->updateLayerFields();
477 : 0 : emit mBuffer->attributeRenamed( mAttr, mOldName );
478 : 0 : }
479 : : else
480 : : {
481 : 0 : setError();
482 : : }
483 : 0 : }
484 : :
485 : 0 : void QgsVectorLayerUndoPassthroughCommandRenameAttribute::redo()
486 : : {
487 : 0 : QgsFieldNameMap map;
488 : 0 : map[ mAttr ] = mNewName;
489 : 0 : mBuffer->L->dataProvider()->clearErrors();
490 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->renameAttributes( map ) && ! mBuffer->L->dataProvider()->hasErrors() )
491 : : {
492 : 0 : mBuffer->updateLayerFields();
493 : 0 : emit mBuffer->attributeRenamed( mAttr, mNewName );
494 : 0 : }
495 : : else
496 : : {
497 : 0 : setError();
498 : : }
499 : 0 : }
500 : :
501 : 0 : QgsVectorLayerUndoPassthroughCommandUpdate::QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer, QgsTransaction *transaction, const QString &sql, const QString &name )
502 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, name.isEmpty() ? QObject::tr( "custom transaction" ) : name, false )
503 : 0 : , mTransaction( transaction )
504 : 0 : , mSql( sql )
505 : 0 : {
506 : 0 : }
507 : :
508 : 0 : void QgsVectorLayerUndoPassthroughCommandUpdate::undo()
509 : : {
510 : 0 : if ( rollBackToSavePoint() )
511 : : {
512 : 0 : mUndone = true;
513 : 0 : emit mBuffer->L->layerModified();
514 : 0 : }
515 : : else
516 : : {
517 : 0 : setError();
518 : : }
519 : 0 : }
520 : :
521 : 0 : void QgsVectorLayerUndoPassthroughCommandUpdate::redo()
522 : : {
523 : : // the first time that the sql query is execute is within QgsTransaction
524 : : // itself. So the redo has to be executed only after an undo action.
525 : 0 : if ( mUndone )
526 : : {
527 : 0 : QString errorMessage;
528 : :
529 : 0 : QString savePointId = mTransaction->createSavepoint( errorMessage );
530 : :
531 : 0 : if ( errorMessage.isEmpty() )
532 : : {
533 : 0 : setSavePoint( savePointId );
534 : :
535 : 0 : if ( mTransaction->executeSql( mSql, errorMessage ) )
536 : : {
537 : 0 : mUndone = false;
538 : 0 : }
539 : : else
540 : : {
541 : 0 : setErrorMessage( errorMessage );
542 : 0 : setError();
543 : : }
544 : 0 : }
545 : : else
546 : : {
547 : 0 : setErrorMessage( errorMessage );
548 : 0 : setError();
549 : : }
550 : 0 : }
551 : 0 : }
552 : :
553 : 0 : QgsVectorLayerUndoPassthroughCommandChangeAttributes::QgsVectorLayerUndoPassthroughCommandChangeAttributes( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues )
554 : 0 : : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "change attribute value" ) )
555 : 0 : , mFid( fid )
556 : 0 : , mNewValues( newValues )
557 : 0 : , mOldValues( oldValues )
558 : 0 : {
559 : 0 : }
560 : :
561 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttributes::undo()
562 : : {
563 : 0 : if ( rollBackToSavePoint() )
564 : : {
565 : 0 : for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
566 : : {
567 : 0 : emit mBuffer->attributeValueChanged( mFid, it.key(), it.value() );
568 : 0 : }
569 : 0 : }
570 : 0 : }
571 : :
572 : 0 : void QgsVectorLayerUndoPassthroughCommandChangeAttributes::redo()
573 : : {
574 : 0 : QgsChangedAttributesMap attribMap;
575 : 0 : attribMap.insert( mFid, mNewValues );
576 : 0 : mBuffer->L->dataProvider()->clearErrors();
577 : 0 : if ( setSavePoint() && mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && ! mBuffer->L->dataProvider()->hasErrors() )
578 : : {
579 : 0 : for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
580 : : {
581 : 0 : emit mBuffer->attributeValueChanged( mFid, it.key(), it.value() );
582 : 0 : }
583 : 0 : }
584 : 0 : }
|