QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgsvectorlayerundocommand.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerundocommand.cpp
3  ---------------------
4  begin : June 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail 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 
17 
18 #include "qgsfeatureiterator.h"
19 #include "qgsgeometry.h"
20 #include "qgsfeature.h"
21 #include "qgsvectorlayer.h"
23 
24 #include "qgslogger.h"
25 
26 
28  : QgsVectorLayerUndoCommand( buffer )
29 {
30  static int sAddedIdLowWaterMark = -1;
31 
32  //assign a temporary id to the feature (use negative numbers)
33  sAddedIdLowWaterMark--;
34 
35  QgsDebugMsgLevel( "Assigned feature id " + QString::number( sAddedIdLowWaterMark ), 4 );
36 
37  // Force a feature ID (to keep other functions in QGIS happy,
38  // providers will use their own new feature ID when we commit the new feature)
39  // and add to the known added features.
40  f.setId( sAddedIdLowWaterMark );
41 
42  mFeature = f;
43 }
44 
46 {
47 #ifndef QT_NO_DEBUG
48  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFeature.id() );
49  Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
50 #endif
51  mBuffer->mAddedFeatures.remove( mFeature.id() );
52 
53  emit mBuffer->featureDeleted( mFeature.id() );
54 }
55 
57 {
58  mBuffer->mAddedFeatures.insert( mFeature.id(), mFeature );
59 
60  emit mBuffer->featureAdded( mFeature.id() );
61 }
62 
63 
64 
66  : QgsVectorLayerUndoCommand( buffer )
67 {
68  mFid = fid;
69 
70  if ( FID_IS_NEW( mFid ) )
71  {
72  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
73  Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
74  mOldAddedFeature = it.value();
75  }
76 }
77 
79 {
80  if ( FID_IS_NEW( mFid ) )
81  {
82  mBuffer->mAddedFeatures.insert( mOldAddedFeature.id(), mOldAddedFeature );
83  }
84  else
85  {
86  mBuffer->mDeletedFeatureIds.remove( mFid );
87  }
88 
89  emit mBuffer->featureAdded( mFid );
90 }
91 
93 {
94  if ( FID_IS_NEW( mFid ) )
95  {
96  mBuffer->mAddedFeatures.remove( mFid );
97  }
98  else
99  {
100  mBuffer->mDeletedFeatureIds.insert( mFid );
101  }
102 
103  emit mBuffer->featureDeleted( mFid );
104 }
105 
106 
107 
109  : QgsVectorLayerUndoCommand( buffer )
110  , mFid( fid )
111  , mNewGeom( newGeom )
112 {
113  if ( FID_IS_NEW( mFid ) )
114  {
115  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
116  Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
117  mOldGeom = ( it.value().geometry() );
118  }
119  else
120  {
121  mOldGeom = mBuffer->mChangedGeometries.value( mFid, QgsGeometry() );
122  }
123 }
124 
126 {
127  return 1;
128 }
129 
130 bool QgsVectorLayerUndoCommandChangeGeometry::mergeWith( const QUndoCommand *other )
131 {
132  if ( other->id() != id() )
133  return false;
134 
135  const QgsVectorLayerUndoCommandChangeGeometry *merge = dynamic_cast<const QgsVectorLayerUndoCommandChangeGeometry *>( other );
136  if ( !merge )
137  return false;
138 
139  if ( merge->mFid != mFid )
140  return false;
141 
142  mNewGeom = merge->mNewGeom;
143  merge->mNewGeom = QgsGeometry();
144 
145  return true;
146 }
147 
149 {
150  if ( FID_IS_NEW( mFid ) )
151  {
152  // modify added features
153  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
154  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
155  it.value().setGeometry( mOldGeom );
156 
157  emit mBuffer->geometryChanged( mFid, mOldGeom );
158  }
159  else
160  {
161  // existing feature
162 
163  if ( mOldGeom.isNull() )
164  {
165  mBuffer->mChangedGeometries.remove( mFid );
166 
167  QgsFeature f;
168  if ( layer()->getFeatures( QgsFeatureRequest().setFilterFid( mFid ).setNoAttributes() ).nextFeature( f ) && f.hasGeometry() )
169  {
170  emit mBuffer->geometryChanged( mFid, f.geometry() );
171  }
172  }
173  else
174  {
175  mBuffer->mChangedGeometries[mFid] = mOldGeom;
176  emit mBuffer->geometryChanged( mFid, mOldGeom );
177  }
178  }
179 
180 }
181 
183 {
184  if ( FID_IS_NEW( mFid ) )
185  {
186  // modify added features
187  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
188  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
189  it.value().setGeometry( mNewGeom );
190  }
191  else
192  {
193  mBuffer->mChangedGeometries[ mFid ] = mNewGeom;
194  }
195  emit mBuffer->geometryChanged( mFid, mNewGeom );
196 }
197 
198 
199 QgsVectorLayerUndoCommandChangeAttribute::QgsVectorLayerUndoCommandChangeAttribute( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int fieldIndex, const QVariant &newValue, const QVariant &oldValue )
200  : QgsVectorLayerUndoCommand( buffer )
201  , mFid( fid )
202  , mFieldIndex( fieldIndex )
203  , mOldValue( oldValue )
204  , mNewValue( newValue )
205  , mFirstChange( true )
206 {
207  if ( FID_IS_NEW( mFid ) )
208  {
209  // work with added feature
210  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
211  Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
212  if ( it.value().attribute( mFieldIndex ).isValid() )
213  {
214  mOldValue = it.value().attribute( mFieldIndex );
215  mFirstChange = false;
216  }
217  }
218  else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( mFieldIndex ) )
219  {
220  mOldValue = mBuffer->mChangedAttributeValues[mFid][mFieldIndex];
221  mFirstChange = false;
222  }
223 
224 }
225 
227 {
228  QVariant original = mOldValue;
229 
230  if ( FID_IS_NEW( mFid ) )
231  {
232  // added feature
233  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
234  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
235  it.value().setAttribute( mFieldIndex, mOldValue );
236  }
237  else if ( mFirstChange )
238  {
239  // existing feature
240  mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex );
241  if ( mBuffer->mChangedAttributeValues[mFid].isEmpty() )
242  mBuffer->mChangedAttributeValues.remove( mFid );
243 
244  if ( !mOldValue.isValid() )
245  {
246  // get old value from provider
247  QgsFeature tmp;
248  QgsFeatureRequest request;
249  request.setFilterFid( mFid );
251  request.setSubsetOfAttributes( QgsAttributeList() << mFieldIndex );
252  QgsFeatureIterator fi = layer()->getFeatures( request );
253  if ( fi.nextFeature( tmp ) )
254  original = tmp.attribute( mFieldIndex );
255  }
256  }
257  else
258  {
259  mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue;
260  }
261 
262  emit mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
263 }
264 
266 {
267  if ( FID_IS_NEW( mFid ) )
268  {
269  // updated added feature
270  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
271  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
272  it.value().setAttribute( mFieldIndex, mNewValue );
273  }
274  else
275  {
276  // changed attribute of existing feature
277  if ( !mBuffer->mChangedAttributeValues.contains( mFid ) )
278  {
280  }
281 
282  mBuffer->mChangedAttributeValues[mFid].insert( mFieldIndex, mNewValue );
283  }
284 
285  emit mBuffer->attributeValueChanged( mFid, mFieldIndex, mNewValue );
286 }
287 
288 
290  : QgsVectorLayerUndoCommand( buffer )
291  , mField( field )
292 {
293  const QgsFields &fields = layer()->fields();
294  int i;
295  for ( i = 0; i < fields.count() && fields.fieldOrigin( i ) != QgsFields::OriginJoin; i++ )
296  ;
297  mFieldIndex = i;
298 }
299 
301 {
302  int index = layer()->fields().fieldOriginIndex( mFieldIndex );
303 
304  mBuffer->mAddedAttributes.removeAt( index );
305  mBuffer->handleAttributeDeleted( mFieldIndex );
307 
308  emit mBuffer->attributeDeleted( mFieldIndex );
309 }
310 
312 {
313  mBuffer->mAddedAttributes.append( mField );
314  mBuffer->handleAttributeAdded( mFieldIndex );
316 
317  emit mBuffer->attributeAdded( mFieldIndex );
318 }
319 
320 
322  : QgsVectorLayerUndoCommand( buffer )
323  , mFieldIndex( fieldIndex )
324 {
325  const QgsFields &fields = layer()->fields();
326  QgsFields::FieldOrigin origin = fields.fieldOrigin( mFieldIndex );
327  mOriginIndex = fields.fieldOriginIndex( mFieldIndex );
328  mProviderField = ( origin == QgsFields::OriginProvider );
329  mFieldName = fields.field( mFieldIndex ).name();
330 
331  if ( !mProviderField )
332  {
333  // need to store the field definition
334  mOldField = mBuffer->mAddedAttributes[mOriginIndex];
335  }
336 
337  if ( mBuffer->mRenamedAttributes.contains( fieldIndex ) )
338  {
339  mOldName = mBuffer->mRenamedAttributes.value( fieldIndex );
340  }
341 
342  // save values of new features
343  for ( QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constBegin(); it != mBuffer->mAddedFeatures.constEnd(); ++it )
344  {
345  const QgsFeature &f = it.value();
346  mDeletedValues.insert( f.id(), f.attribute( mFieldIndex ) );
347  }
348 
349  // save changed values
350  for ( QgsChangedAttributesMap::const_iterator it = mBuffer->mChangedAttributeValues.constBegin(); it != mBuffer->mChangedAttributeValues.constEnd(); ++it )
351  {
352  const QgsAttributeMap &attrs = it.value();
353  if ( attrs.contains( mFieldIndex ) )
354  mDeletedValues.insert( it.key(), attrs[mFieldIndex] );
355  }
356 }
357 
359 {
360  if ( mProviderField )
361  {
362  mBuffer->mDeletedAttributeIds.removeOne( mOriginIndex );
363  }
364  else
365  {
366  // newly added attribute
367  mBuffer->mAddedAttributes.insert( mOriginIndex, mOldField );
368  }
369 
371  mBuffer->handleAttributeAdded( mFieldIndex ); // update changed attributes + new features
372 
373  if ( !mOldName.isEmpty() )
374  {
375  mBuffer->mRenamedAttributes[ mFieldIndex ] = mOldName;
377  }
378 
379  // set previously used attributes of new features
380  for ( QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.begin(); it != mBuffer->mAddedFeatures.end(); ++it )
381  {
382  QgsFeature &f = it.value();
383  f.setAttribute( mFieldIndex, mDeletedValues.value( f.id() ) );
384  }
385  // set previously used changed attributes
386  for ( QMap<QgsFeatureId, QVariant>::const_iterator it = mDeletedValues.constBegin(); it != mDeletedValues.constEnd(); ++it )
387  {
388  if ( !FID_IS_NEW( it.key() ) )
389  {
390  QgsAttributeMap &attrs = mBuffer->mChangedAttributeValues[it.key()]; // also adds record if nonexistent
391  attrs.insert( mFieldIndex, it.value() );
392  }
393  }
394 
395  QgsEditFormConfig formConfig = mBuffer->L->editFormConfig();
396  mBuffer->L->setEditFormConfig( formConfig );
397 
398  emit mBuffer->attributeAdded( mFieldIndex );
399 }
400 
402 {
403  if ( mProviderField )
404  {
405  mBuffer->mDeletedAttributeIds.append( mOriginIndex );
406  std::sort( mBuffer->mDeletedAttributeIds.begin(), mBuffer->mDeletedAttributeIds.end() ); // keep it sorted
407  }
408  else
409  {
410  // newly added attribute
411  mBuffer->mAddedAttributes.removeAt( mOriginIndex ); // removing temporary attribute
412  }
413 
414  mBuffer->handleAttributeDeleted( mFieldIndex ); // update changed attributes + new features
416  emit mBuffer->attributeDeleted( mFieldIndex );
417 }
418 
419 
421  : QgsVectorLayerUndoCommand( buffer )
422  , mFieldIndex( fieldIndex )
423  , mOldName( layer()->fields().at( fieldIndex ).name() )
424  , mNewName( newName )
425 {
426  const QgsFields &fields = layer()->fields();
427  QgsFields::FieldOrigin origin = fields.fieldOrigin( mFieldIndex );
428  mOriginIndex = fields.fieldOriginIndex( mFieldIndex );
429  mProviderField = ( origin == QgsFields::OriginProvider );
430 }
431 
433 {
434  if ( mProviderField )
435  {
436  mBuffer->mRenamedAttributes[ mFieldIndex ] = mOldName;
437  }
438  else
439  {
440  // newly added attribute
441  mBuffer->mAddedAttributes[mOriginIndex].setName( mOldName );
442  }
444  emit mBuffer->attributeRenamed( mFieldIndex, mOldName );
445 }
446 
448 {
449  if ( mProviderField )
450  {
451  mBuffer->mRenamedAttributes[ mFieldIndex ] = mNewName;
452  }
453  else
454  {
455  // newly added attribute
456  mBuffer->mAddedAttributes[mOriginIndex].setName( mNewName );
457  }
459  emit mBuffer->attributeRenamed( mFieldIndex, mNewName );
460 }
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets feature ID that should be fetched.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
Definition: qgsfeature.cpp:236
void setId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:114
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:204
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:287
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
Container of fields for a vector layer.
Definition: qgsfields.h:45
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:52
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfields.h:51
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
FieldOrigin fieldOrigin(int fieldIdx) const
Gets field's origin (value from an enumeration)
Definition: qgsfields.cpp:189
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:168
int fieldOriginIndex(int fieldIdx) const
Gets field's origin index (its meaning is specific to each type of origin)
Definition: qgsfields.cpp:197
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
void attributeRenamed(int idx, const QString &newName)
Emitted when an attribute has been renamed.
QgsFeatureMap mAddedFeatures
New features which are not committed.
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geom)
Emitted when a feature's geometry is changed.
void handleAttributeDeleted(int index)
Update added and changed features after removal of an attribute.
QgsFieldNameMap mRenamedAttributes
Renamed attributes which are not committed.
QgsGeometryMap mChangedGeometries
Changed geometries which are not committed.
QgsAttributeList mDeletedAttributeIds
Deleted attributes fields which are not committed. The list is kept sorted.
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not committed.
void featureDeleted(QgsFeatureId fid)
void attributeAdded(int idx)
void attributeDeleted(int idx)
void featureAdded(QgsFeatureId fid)
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not committed.
void handleAttributeAdded(int index)
Update added and changed features after addition of an attribute.
QList< QgsField > mAddedAttributes
Added attributes fields which are not committed.
QgsVectorLayerUndoCommandAddAttribute(QgsVectorLayerEditBuffer *buffer, const QgsField &field)
Constructor for QgsVectorLayerUndoCommandAddAttribute.
QgsVectorLayerUndoCommandAddFeature(QgsVectorLayerEditBuffer *buffer, QgsFeature &f)
Constructor for QgsVectorLayerUndoCommandAddFeature.
QgsVectorLayerUndoCommandChangeAttribute(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int fieldIndex, const QVariant &newValue, const QVariant &oldValue)
Constructor for QgsVectorLayerUndoCommandChangeAttribute.
Undo command for modifying the geometry of a feature from a vector layer.
bool mergeWith(const QUndoCommand *) override
QgsVectorLayerUndoCommandChangeGeometry(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsGeometry &newGeom)
Constructor for QgsVectorLayerUndoCommandChangeGeometry.
QgsVectorLayerUndoCommandDeleteAttribute(QgsVectorLayerEditBuffer *buffer, int fieldIndex)
Constructor for QgsVectorLayerUndoCommandDeleteAttribute.
QgsVectorLayerUndoCommandDeleteFeature(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid)
Constructor for QgsVectorLayerUndoCommandDeleteFeature.
QgsVectorLayerUndoCommandRenameAttribute(QgsVectorLayerEditBuffer *buffer, int fieldIndex, const QString &newName)
Constructor for QgsVectorLayerUndoCommandRenameAttribute.
Base class for undo commands within a QgsVectorLayerEditBuffer.
QgsVectorLayer * layer()
Returns the layer associated with the undo command.
QgsVectorLayerEditBuffer * mBuffer
Associated edit buffer.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
void setEditFormConfig(const QgsEditFormConfig &editFormConfig)
Sets the editFormConfig (configuration) of the form used to represent this vector layer.
QgsEditFormConfig editFormConfig
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
#define FID_IS_NEW(fid)
Definition: qgsfeatureid.h:31
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:472
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39