QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 "qgsgeometry.h"
19 #include "qgsfeature.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsgeometrycache.h"
23 
24 #include "qgslogger.h"
25 
26 
28  : QgsVectorLayerUndoCommand( buffer )
29 {
30  static int addedIdLowWaterMark = -1;
31 
32  //assign a temporary id to the feature (use negative numbers)
33  addedIdLowWaterMark--;
34 
35  QgsDebugMsg( "Assigned feature id " + QString::number( addedIdLowWaterMark ) );
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.setFeatureId( addedIdLowWaterMark );
41 
42  mFeature = f;
43 }
44 
46 {
47 #ifdef QGISDEBUG
48  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.find( mFeature.id() );
49  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
50 #endif
51  mBuffer->mAddedFeatures.remove( mFeature.id() );
52 
53  if ( mFeature.geometry() )
55 
56  emit mBuffer->featureDeleted( mFeature.id() );
57 }
58 
60 {
62 
63  if ( mFeature.geometry() )
65 
66  emit mBuffer->featureAdded( mFeature.id() );
67 }
68 
69 
70 
72  : QgsVectorLayerUndoCommand( buffer )
73 {
74  mFid = fid;
75 
76  if ( FID_IS_NEW( mFid ) )
77  {
78  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.find( mFid );
79  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
80  mOldAddedFeature = it.value();
81  }
82 }
83 
85 {
86  if ( FID_IS_NEW( mFid ) )
87  {
89  }
90  else
91  {
92  mBuffer->mDeletedFeatureIds.remove( mFid );
93  }
94 
95  emit mBuffer->featureAdded( mFid );
96 }
97 
99 {
100  if ( FID_IS_NEW( mFid ) )
101  {
102  mBuffer->mAddedFeatures.remove( mFid );
103  }
104  else
105  {
106  mBuffer->mDeletedFeatureIds.insert( mFid );
107  }
108 
109  emit mBuffer->featureDeleted( mFid );
110 }
111 
112 
113 
115  : QgsVectorLayerUndoCommand( buffer )
116  , mFid( fid )
117 {
118  if ( FID_IS_NEW( mFid ) )
119  {
120  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.find( mFid );
121  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
122  mOldGeom = new QgsGeometry( *it.value().geometry() );
123  }
124  else
125  {
126  bool changedAlready = mBuffer->mChangedGeometries.contains( mFid );
127  QgsGeometry geom;
128  bool cachedGeom = cache()->geometry( mFid, geom );
129  mOldGeom = ( changedAlready && cachedGeom ) ? new QgsGeometry( geom ) : 0;
130  }
131 
132  mNewGeom = new QgsGeometry( *newGeom );
133 }
134 
136 {
137  return 1;
138 }
139 
140 bool QgsVectorLayerUndoCommandChangeGeometry::mergeWith( const QUndoCommand *other )
141 {
142  if ( other->id() != id() )
143  return false;
144 
145  const QgsVectorLayerUndoCommandChangeGeometry *merge = dynamic_cast<const QgsVectorLayerUndoCommandChangeGeometry *>( other );
146  if ( !merge )
147  return false;
148 
149  if ( merge->mFid != mFid )
150  return false;
151 
152  delete mNewGeom;
153  mNewGeom = merge->mNewGeom;
154  merge->mNewGeom = 0;
155 
156  return true;
157 }
158 
160 {
161  delete mOldGeom;
162  delete mNewGeom;
163 }
164 
166 {
167  if ( FID_IS_NEW( mFid ) )
168  {
169  // modify added features
170  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
171  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
172  it.value().setGeometry( *mOldGeom );
173 
176  }
177  else
178  {
179  // existing feature
180 
181  if ( !mOldGeom )
182  {
183  mBuffer->mChangedGeometries.remove( mFid );
184 
185  QgsFeature f;
186  if ( layer()->getFeatures( QgsFeatureRequest().setFilterFid( mFid ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) && f.geometry() )
187  {
188  cache()->cacheGeometry( mFid, *f.geometry() );
189  emit mBuffer->geometryChanged( mFid, *f.geometry() );
190  }
191  }
192  else
193  {
197  }
198  }
199 
200 }
201 
203 {
204  if ( FID_IS_NEW( mFid ) )
205  {
206  // modify added features
207  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
208  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
209  it.value().setGeometry( *mNewGeom );
210  }
211  else
212  {
214  }
217 }
218 
219 
221  : QgsVectorLayerUndoCommand( buffer )
222  , mFid( fid )
223  , mFieldIndex( fieldIndex )
224  , mNewValue( newValue )
225  , mFirstChange( true )
226 {
227  if ( FID_IS_NEW( mFid ) )
228  {
229  // work with added feature
230  QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.find( mFid );
231  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
232  if ( it.value().attribute( mFieldIndex ).isValid() )
233  {
234  mOldValue = it.value().attribute( mFieldIndex );
235  mFirstChange = false;
236  }
237  }
238  else
239  {
241  {
243  mFirstChange = false;
244  }
245  }
246 
247 }
248 
250 {
251  QVariant original = mOldValue;
252 
253  if ( FID_IS_NEW( mFid ) )
254  {
255  // added feature
256  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
257  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
258  it.value().setAttribute( mFieldIndex, mOldValue );
259  }
260  else
261  {
262  // existing feature
263  if ( mFirstChange )
264  {
266  if ( mBuffer->mChangedAttributeValues[mFid].isEmpty() )
268 
269  // get old value from provider
270  QgsFeature tmp;
271  QgsFeatureRequest request;
272  request.setFilterFid( mFid );
275  QgsFeatureIterator fi = layer()->getFeatures( request );
276  if ( fi.nextFeature( tmp ) )
277  original = tmp.attribute( mFieldIndex );
278  }
279  else
280  {
282  }
283  }
284 
285  emit mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
286 }
287 
289 {
290  if ( FID_IS_NEW( mFid ) )
291  {
292  // updated added feature
293  QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid );
294  Q_ASSERT( it != mBuffer->mAddedFeatures.end() );
295  it.value().setAttribute( mFieldIndex, mNewValue );
296  }
297  else
298  {
299  // changed attribute of existing feature
300  if ( !mBuffer->mChangedAttributeValues.contains( mFid ) )
301  {
303  }
304 
306  }
307 
309 }
310 
311 
313  : QgsVectorLayerUndoCommand( buffer )
314  , mField( field )
315 {
317 }
318 
320 {
321  int index = layer()->pendingFields().fieldOriginIndex( mFieldIndex );
322 
323  mBuffer->mAddedAttributes.removeAt( index );
326 
328 }
329 
331 {
332  mBuffer->mAddedAttributes.append( mField );
335 
337 }
338 
339 
341  : QgsVectorLayerUndoCommand( buffer )
342  , mFieldIndex( fieldIndex )
343 {
344  const QgsFields& fields = layer()->pendingFields();
348 
349  if ( !mProviderField )
350  {
351  // need to store the field definition
353  }
354 
355  // save values of new features
356  for ( QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.begin(); it != mBuffer->mAddedFeatures.end(); ++it )
357  {
358  const QgsFeature& f = it.value();
359  mDeletedValues.insert( f.id(), f.attribute( mFieldIndex ) );
360  }
361 
362  // save changed values
363  for ( QgsChangedAttributesMap::const_iterator it = mBuffer->mChangedAttributeValues.begin(); it != mBuffer->mChangedAttributeValues.end(); ++it )
364  {
365  const QgsAttributeMap& attrs = it.value();
366  if ( attrs.contains( mFieldIndex ) )
367  mDeletedValues.insert( it.key(), attrs[mFieldIndex] );
368  }
369 }
370 
372 {
373  if ( mProviderField )
374  {
376  }
377  else
378  {
379  // newly added attribute
381  }
382 
384  mBuffer->handleAttributeAdded( mFieldIndex ); // update changed attributes + new features
385 
386  // set previously used attributes of new features
387  for ( QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.begin(); it != mBuffer->mAddedFeatures.end(); ++it )
388  {
389  QgsFeature& f = it.value();
390  f.setAttribute( mFieldIndex, mDeletedValues.value( f.id() ) );
391  }
392  // set previously used changed attributes
393  for ( QMap<QgsFeatureId, QVariant>::const_iterator it = mDeletedValues.begin(); it != mDeletedValues.end(); ++it )
394  {
395  if ( !FID_IS_NEW( it.key() ) )
396  {
397  QgsAttributeMap& attrs = mBuffer->mChangedAttributeValues[it.key()]; // also adds record if nonexistant
398  attrs.insert( mFieldIndex, it.value() );
399  }
400  }
401 
403 }
404 
406 {
407  if ( mProviderField )
408  {
410  qSort( mBuffer->mDeletedAttributeIds ); // keep it sorted
411  }
412  else
413  {
414  // newly added attribute
415  mBuffer->mAddedAttributes.removeAt( mOriginIndex ); // removing temporary attribute
416  }
417 
419  mBuffer->handleAttributeDeleted( mFieldIndex ); // update changed attributes + new features
421 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:101
Wrapper for iterator of features from vector data provider or vector layer.
void handleAttributeDeleted(int index)
update added and changed features after removal of an attribute
QgsVectorLayerUndoCommandAddFeature(QgsVectorLayerEditBuffer *buffer, QgsFeature &f)
QMap< int, QVariant > QgsAttributeMap
Definition: qgsfeature.h:98
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void attributeDeleted(int idx)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:113
QgsVectorLayerEditBuffer * mBuffer
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Container of fields for a vector layer.
Definition: qgsfield.h:162
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:72
bool setAttribute(int field, const QVariant &attr)
Set an attribute by id.
Definition: qgsfeature.cpp:191
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not commited.
field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfield.h:169
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:114
QgsVectorLayerUndoCommandAddAttribute(QgsVectorLayerEditBuffer *buffer, const QgsField &field)
QgsVectorLayerUndoCommandDeleteAttribute(QgsVectorLayerEditBuffer *buffer, int fieldIndex)
void featureAdded(QgsFeatureId fid)
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
void removeGeometry(QgsFeatureId fid)
get rid of the cached geometry
void setFeatureId(QgsFeatureId id)
Set the feature id for this feature.
Definition: qgsfeature.cpp:129
void attributeAdded(int idx)
void geometryChanged(QgsFeatureId fid, QgsGeometry &geom)
bool geometry(QgsFeatureId fid, QgsGeometry &geometry)
fetch geometry from cache, return true if successful
int fieldOriginIndex(int fieldIdx) const
Get field's origin index (its meaning is specific to each type of origin)
Definition: qgsfield.h:214
QgsGeometryMap mChangedGeometries
Changed geometries which are not commited.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
void handleAttributeAdded(int index)
update added and changed features after addition of an attribute
int count() const
Return number of items.
Definition: qgsfield.h:196
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not commited.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:29
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:231
QList< QgsField > mAddedAttributes
added attributes fields which are not commited
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
Definition: qgsfield.h:212
QgsVectorLayerUndoCommandChangeAttribute(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int fieldIndex, const QVariant &newValue)
void cacheGeometry(QgsFeatureId fid, const QgsGeometry &geom)
store a geometry in the cache
qint64 QgsFeatureId
Definition: qgsfeature.h:30
#define FID_IS_NEW(fid)
Definition: qgsfeature.h:81
virtual bool mergeWith(const QUndoCommand *)
QgsVectorLayerUndoCommandChangeGeometry(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, QgsGeometry *newGeom)
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsVectorLayerUndoCommandDeleteFeature(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid)
bool nextFeature(QgsFeature &f)
Do not fetch geometry.
QgsFeatureMap mAddedFeatures
New features which are not commited.
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
QgsAttributeList mDeletedAttributeIds
deleted attributes fields which are not commited.
void featureDeleted(QgsFeatureId fid)