QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsvectorlayereditbuffer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayereditbuffer.cpp
3  ---------------------
4  begin : Dezember 2012
5  copyright : (C) 2012 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  ***************************************************************************/
16 
17 #include "qgsgeometry.h"
18 #include "qgslogger.h"
20 #include "qgsvectordataprovider.h"
21 #include "qgsvectorlayer.h"
22 
23 
25 template <class Key, class T> void mapToReversedLists( const QMap< Key, T >& map, QList<Key>& ks, QList<T>& vs )
26 {
27  ks.reserve( map.size() );
28  vs.reserve( map.size() );
29  typename QMap<Key, T>::const_iterator i = map.constEnd();
30  while ( i-- != map.constBegin() )
31  {
32  ks.append( i.key() );
33  vs.append( i.value() );
34  }
35 }
36 
37 
39  : L( layer )
40 {
41  connect( L->undoStack(), SIGNAL( indexChanged( int ) ), this, SLOT( undoIndexChanged( int ) ) ); // TODO[MD]: queued?
42 }
43 
45 {
46 }
47 
48 
50 {
51  return !L->undoStack()->isClean();
52 }
53 
54 
56 {
57  QgsDebugMsg( QString( "undo index changed %1" ).arg( index ) );
58  Q_UNUSED( index );
59  emit layerModified();
60 }
61 
62 
64 {
65  // delete attributes from the higher indices to lower indices
66  for ( int i = mDeletedAttributeIds.count() - 1; i >= 0; --i )
67  {
68  fields.remove( mDeletedAttributeIds[i] );
69  }
70  // add new fields
71  for ( int i = 0; i < mAddedAttributes.count(); ++i )
72  {
74  }
75 }
76 
77 
79 {
80  if ( mChangedGeometries.contains( f.id() ) )
82 }
83 
84 
86 {
87  QgsAttributes& attrs = f.attributes();
88 
89  // remove all attributes that will disappear - from higher indices to lower
90  for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
91  {
92  attrs.remove( mDeletedAttributeIds[idx] );
93  }
94 
95  // adjust size to accommodate added attributes
96  attrs.resize( attrs.count() + mAddedAttributes.count() );
97 
98  // update changed attributes
99  if ( mChangedAttributeValues.contains( f.id() ) )
100  {
101  const QgsAttributeMap &map = mChangedAttributeValues[f.id()];
102  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
103  attrs[it.key()] = it.value();
104  }
105 }
106 
107 
108 
109 
111 {
113  {
114  return false;
115  }
116  if ( L->mUpdatedFields.count() != f.attributes().count() )
117  return false;
118 
119  // TODO: check correct geometry type
120 
121  L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) );
122  return true;
123 }
124 
125 
127 {
129  return false;
130 
131  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
132  {
133  addFeature( *iter );
134  }
135 
136  L->updateExtents();
137  return true;
138 }
139 
140 
141 
143 {
145  return false;
146 
147  if ( FID_IS_NEW( fid ) )
148  {
149  if ( !mAddedFeatures.contains( fid ) )
150  return false;
151  }
152  else // existing feature
153  {
154  if ( mDeletedFeatureIds.contains( fid ) )
155  return false;
156  }
157 
158  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteFeature( this, fid ) );
159  return true;
160 }
161 
162 
164 {
166  return false;
167 
168  if ( !L->hasGeometryType() )
169  {
170  return false;
171  }
172 
173  if ( FID_IS_NEW( fid ) )
174  {
175  if ( !mAddedFeatures.contains( fid ) )
176  return false;
177  }
178 
179  // TODO: check compatible geometry
180 
181  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeGeometry( this, fid, geom ) );
182  return true;
183 }
184 
185 
186 bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
187 {
189  return false;
190 
191  if ( FID_IS_NEW( fid ) )
192  {
193  if ( !mAddedFeatures.contains( fid ) )
194  return false;
195  }
196 
197  if ( field < 0 || field >= L->pendingFields().count() ||
200  return false;
201 
202  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeAttribute( this, fid, field, newValue, oldValue ) );
203  return true;
204 }
205 
206 
208 {
210  return false;
211 
212  if ( field.name().isEmpty() )
213  return false;
214 
215  const QgsFields& updatedFields = L->pendingFields();
216  for ( int idx = 0; idx < updatedFields.count(); ++idx )
217  {
218  if ( updatedFields[idx].name() == field.name() )
219  return false;
220  }
221 
222  if ( !L->dataProvider()->supportedType( field ) )
223  return false;
224 
225  L->undoStack()->push( new QgsVectorLayerUndoCommandAddAttribute( this, field ) );
226  return true;
227 }
228 
229 
231 {
233  return false;
234 
235  if ( index < 0 || index >= L->pendingFields().count() )
236  return false;
237 
238  // find out source of the field
239  QgsFields::FieldOrigin origin = L->pendingFields().fieldOrigin( index );
240  int originIndex = L->pendingFields().fieldOriginIndex( index );
241 
242  if ( origin == QgsFields::OriginProvider && mDeletedAttributeIds.contains( originIndex ) )
243  return false;
244 
245  if ( origin == QgsFields::OriginJoin )
246  return false;
247 
248  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteAttribute( this, index ) );
249  return true;
250 }
251 
252 
253 bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
254 {
255  QgsVectorDataProvider* provider = L->dataProvider();
256  commitErrors.clear();
257 
258  int cap = provider->capabilities();
259  bool success = true;
260 
261  QgsFields oldFields = L->pendingFields();
262 
263  //
264  // delete attributes
265  //
266  bool attributesChanged = false;
267  if ( !mDeletedAttributeIds.isEmpty() )
268  {
270  {
271  commitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
272 
274 
275  mDeletedAttributeIds.clear();
276  attributesChanged = true;
277  }
278  else
279  {
280  commitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
281 #if 0
282  QString list = "ERROR: Pending attribute deletes:";
283  foreach ( int idx, mDeletedAttributeIds )
284  {
285  list.append( " " + L->pendingFields()[idx].name() );
286  }
287  commitErrors << list;
288 #endif
289  success = false;
290  }
291  }
292 
293  //
294  // add attributes
295  //
296  if ( !mAddedAttributes.isEmpty() )
297  {
299  {
300  commitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributes.size() );
301 
303 
304  mAddedAttributes.clear();
305  attributesChanged = true;
306  }
307  else
308  {
309  commitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributes.size() );
310 #if 0
311  QString list = "ERROR: Pending adds:";
312  foreach ( QgsField f, mAddedAttributes )
313  {
314  list.append( " " + f.name() );
315  }
316  commitErrors << list;
317 #endif
318  success = false;
319  }
320  }
321 
322  //
323  // check that addition/removal went as expected
324  //
325  bool attributeChangesOk = true;
326  if ( attributesChanged )
327  {
328  L->updateFields();
329  QgsFields newFields = L->pendingFields();
330 
331  if ( oldFields.count() != newFields.count() )
332  {
333  commitErrors << tr( "ERROR: the count of fields is incorrect after addition/removal of fields!" );
334  attributeChangesOk = false; // don't try attribute updates - they'll fail.
335  }
336 
337  for ( int i = 0; i < qMin( oldFields.count(), newFields.count() ); ++i )
338  {
339  const QgsField& oldField = oldFields[i];
340  const QgsField& newField = newFields[i];
341  if ( attributeChangesOk && oldField != newField )
342  {
343  commitErrors
344  << tr( "ERROR: field with index %1 is not the same!" ).arg( i )
345  << tr( "Provider: %1" ).arg( L->providerType() )
346  << tr( "Storage: %1" ).arg( L->storageType() )
347  << QString( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
348  .arg( tr( "expected field" ) )
349  .arg( oldField.name() )
350  .arg( QVariant::typeToName( oldField.type() ) )
351  .arg( oldField.typeName() )
352  .arg( oldField.length() )
353  .arg( oldField.precision() )
354  << QString( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
355  .arg( tr( "retrieved field" ) )
356  .arg( newField.name() )
357  .arg( QVariant::typeToName( newField.type() ) )
358  .arg( newField.typeName() )
359  .arg( newField.length() )
360  .arg( newField.precision() );
361  attributeChangesOk = false; // don't try attribute updates - they'll fail.
362  }
363  }
364  }
365 
366  if ( attributeChangesOk )
367  {
368  //
369  // change attributes
370  //
371  if ( !mChangedAttributeValues.isEmpty() )
372  {
374  {
375  commitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
376 
378 
379  mChangedAttributeValues.clear();
380  }
381  else
382  {
383  commitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
384 #if 0
385  QString list = "ERROR: pending changes:";
386  foreach ( QgsFeatureId id, mChangedAttributeValues.keys() )
387  {
388  list.append( "\n " + FID_TO_STRING( id ) + "[" );
389  foreach ( int idx, mChangedAttributeValues[ id ].keys() )
390  {
391  list.append( QString( " %1:%2" ).arg( L->pendingFields()[idx].name() ).arg( mChangedAttributeValues[id][idx].toString() ) );
392  }
393  list.append( " ]" );
394  }
395  commitErrors << list;
396 #endif
397  success = false;
398  }
399  }
400 
401  //
402  // delete features
403  //
404  if ( success && !mDeletedFeatureIds.isEmpty() )
405  {
407  {
408  commitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
409  // TODO[MD]: we should not need this here
410  for ( QgsFeatureIds::const_iterator it = mDeletedFeatureIds.begin(); it != mDeletedFeatureIds.end(); ++it )
411  {
412  mChangedAttributeValues.remove( *it );
413  mChangedGeometries.remove( *it );
414  }
415 
417 
418  mDeletedFeatureIds.clear();
419  }
420  else
421  {
422  commitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
423 #if 0
424  QString list = "ERROR: pending deletes:";
425  foreach ( QgsFeatureId id, mDeletedFeatureIds )
426  {
427  list.append( " " + FID_TO_STRING( id ) );
428  }
429  commitErrors << list;
430 #endif
431  success = false;
432  }
433  }
434 
435  //
436  // add features
437  //
438  if ( success && !mAddedFeatures.isEmpty() )
439  {
441  {
442  QList<QgsFeatureId> ids;
443  QgsFeatureList featuresToAdd;
444  // get the list of added features in reversed order
445  // this will preserve the order how they have been added e.g. (-1, -2, -3) while in the map they are ordered (-3, -2, -1)
446  mapToReversedLists( mAddedFeatures, ids, featuresToAdd );
447 
448  if ( provider->addFeatures( featuresToAdd ) )
449  {
450  commitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", featuresToAdd.size() );
451 
452  emit committedFeaturesAdded( L->id(), featuresToAdd );
453 
454  // notify everyone that the features with temporary ids were updated with permanent ids
455  for ( int i = 0; i < featuresToAdd.count(); ++i )
456  {
457  if ( featuresToAdd[i].id() != ids[i] )
458  {
459  //update selection
460  if ( L->mSelectedFeatureIds.contains( ids[i] ) )
461  {
462  L->mSelectedFeatureIds.remove( ids[i] );
463  L->mSelectedFeatureIds.insert( featuresToAdd[i].id() );
464  }
465  emit featureDeleted( ids[i] );
466  emit featureAdded( featuresToAdd[i].id() );
467  }
468  }
469 
470  mAddedFeatures.clear();
471  }
472  else
473  {
474  commitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
475 #if 0
476  QString list = "ERROR: pending adds:";
477  foreach ( QgsFeature f, mAddedFeatures )
478  {
479  list.append( " " + FID_TO_STRING( f.id() ) + "[" );
480  for ( int i = 0; i < L->pendingFields().size(); i++ )
481  {
482  list.append( QString( " %1:%2" ).arg( L->pendingFields()[i].name() ).arg( f.attributes()[i].toString() ) );
483  }
484  list.append( " ]" );
485  }
486  commitErrors << list;
487 #endif
488  success = false;
489  }
490  }
491  else
492  {
493  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
494  success = false;
495  }
496  }
497  }
498  else
499  {
500  success = false;
501  }
502 
503  //
504  // update geometries
505  //
506  if ( success && !mChangedGeometries.isEmpty() )
507  {
509  {
510  commitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
511 
513 
514  mChangedGeometries.clear();
515  }
516  else
517  {
518  commitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
519  success = false;
520  }
521  }
522 
523  if ( !success && provider->hasErrors() )
524  {
525  commitErrors << tr( "\n Provider errors:" );
526  foreach ( QString e, provider->errors() )
527  {
528  commitErrors << " " + e.replace( "\n", "\n " );
529  }
530  provider->clearErrors();
531  }
532 
533  return success;
534 }
535 
536 
538 {
539  if ( !isModified() )
540  return;
541 
542  // limit canvas redraws to one by jumping to beginning of stack
543  // see QgsUndoWidget::indexChanged
544  L->undoStack()->setIndex( 0 );
545 
546  Q_ASSERT( mAddedAttributes.isEmpty() );
547  Q_ASSERT( mDeletedAttributeIds.isEmpty() );
548  Q_ASSERT( mChangedAttributeValues.isEmpty() );
549  Q_ASSERT( mChangedGeometries.isEmpty() );
550  Q_ASSERT( mAddedFeatures.isEmpty() );
551 }
552 
553 #if 0
554 QString QgsVectorLayerEditBuffer::dumpEditBuffer()
555 {
556  QString msg;
557  if ( !mChangedGeometries.isEmpty() )
558  {
559  msg += "CHANGED GEOMETRIES:\n";
560  for ( QgsGeometryMap::const_iterator it = mChangedGeometries.begin(); it != mChangedGeometries.end(); ++it )
561  {
562  // QgsFeatureId, QgsGeometry
563  msg += QString( "- FID %1: %2" ).arg( it.key() ).arg( it.value().to );
564  }
565  }
566  return msg;
567 }
568 #endif
569 
571 {
572  // go through the changed attributes map and adapt indices
573  for ( int i = 0; i < mChangedAttributeValues.size(); ++i )
574  {
576  }
577 
578  // go through added features and adapt attributes
579  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
580  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
581  {
582  QgsAttributes& attrs = featureIt->attributes();
583  attrs.insert( index, QVariant() );
584  }
585 }
586 
588 {
589  // go through the changed attributes map and adapt indices
590  for ( int i = 0; i < mChangedAttributeValues.size(); ++i )
591  {
593  // remove the attribute
594  if ( attrMap.contains( index ) )
595  attrMap.remove( index );
596 
597  // update attribute indices
598  updateAttributeMapIndex( attrMap, index, -1 );
599  }
600 
601  // go through added features and adapt attributes
602  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
603  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
604  {
605  QgsAttributes& attrs = featureIt->attributes();
606  attrs.remove( index );
607  }
608 }
609 
610 
611 
613 {
614  QgsAttributeMap updatedMap;
615  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
616  {
617  int attrIndex = it.key();
618  updatedMap.insert( attrIndex < index ? attrIndex : attrIndex + offset, it.value() );
619  }
620  map = updatedMap;
621 }
622 
623 
624 
626 {
627  L->updateFields();
628 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
void updateFields()
Assembles mUpdatedFields considering provider fields, joined fields and added fields.
void updateChangedAttributes(QgsFeature &f)
Update feature with uncommited attribute updates.
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:59
allows modification of attribute values
static unsigned index
void handleAttributeDeleted(int index)
update added and changed features after removal of an attribute
allows modifications of geometries
virtual bool addAttribute(const QgsField &field)
add an attribute field (but does not commit it) returns true if the field was added ...
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
void mapToReversedLists(const QMap< Key, T > &map, QList< Key > &ks, QList< T > &vs)
populate two lists (ks, vs) from map - in reverse order
QMap< int, QVariant > QgsAttributeMap
Definition: qgsfeature.h:98
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes.
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
virtual bool addFeature(QgsFeature &f)
Adds a feature.
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:322
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features.
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:79
#define FID_TO_STRING(fid)
Definition: qgsfeature.h:83
friend class QgsVectorLayerUndoCommandChangeGeometry
Container of fields for a vector layer.
Definition: qgsfield.h:172
virtual void rollBack()
Stop editing and discard the edits.
QStringList errors()
Get recorded errors.
friend class QgsVectorLayerUndoCommandAddAttribute
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not commited.
void updateFeatureGeometry(QgsFeature &f)
Update feature with uncommited geometry updates.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
virtual bool addFeatures(QgsFeatureList &flist)
Adds a list of features.
friend class QgsVectorLayerUndoCommandDeleteAttribute
virtual void updateExtents()
Update the extents for the layer.
void featureAdded(QgsFeatureId fid)
field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfield.h:179
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object (deep copy)
Definition: qgsfeature.cpp:134
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
bool supportedType(const QgsField &field) const
check if provider supports type of field
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
bool hasErrors()
Provider has errors to report.
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
allows deletion of attributes (fields)
int fieldOriginIndex(int fieldIdx) const
Get field's origin index (its meaning is specific to each type of origin)
Definition: qgsfield.h:236
QgsGeometryMap mChangedGeometries
Changed geometries which are not commited.
void handleAttributeAdded(int index)
update added and changed features after addition of an attribute
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfield.cpp:177
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:98
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:181
void clearErrors()
Clear recorded errors.
int count() const
Return number of items.
Definition: qgsfield.h:214
field is calculated from an expression
Definition: qgsfield.h:182
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not commited.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:201
virtual bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
virtual bool deleteAttribute(int attr)
delete an attribute field (but does not commit it)
friend class QgsVectorLayerUndoCommandDeleteFeature
virtual bool changeGeometryValues(QgsGeometryMap &geometry_map)
Changes geometries of existing features.
QString providerType() const
Return the provider type for this layer.
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QList< QgsField > mAddedAttributes
added attributes fields which are not commited
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
const QString & typeName() const
Gets the field type.
Definition: qgsfield.cpp:69
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:74
int size() const
Return number of items.
Definition: qgsfield.h:216
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
Definition: qgsfield.cpp:218
virtual bool deleteAttributes(const QgsAttributeIds &attributes)
Deletes existing attributes.
virtual bool deleteFeature(QgsFeatureId fid)
delete a feature from the layer (but does not commit it)
qint64 QgsFeatureId
Definition: qgsfeature.h:30
virtual bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
changed an attribute value (but does not commit it)
#define FID_IS_NEW(fid)
Definition: qgsfeature.h:81
allows addition of new attributes (fields)
QUndoStack * undoStack()
Return pointer to layer's undo stack.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:180
QgsVectorDataProvider * dataProvider()
Returns the data provider.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
This is the base class for vector data providers.
QgsFeatureMap mAddedFeatures
New features which are not commited.
void updateFields(QgsFields &fields)
void layerModified()
This signal is emitted when modifications has been done on layer.
Represents a vector layer which manages a vector based data sets.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QgsAttributeList mDeletedAttributeIds
deleted attributes fields which are not commited.
void updateAttributeMapIndex(QgsAttributeMap &attrs, int index, int offset) const
Updates an index in an attribute map to a new value (for updates of changed attributes) ...
virtual bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
change feature's geometry
void featureDeleted(QgsFeatureId fid)
friend class QgsVectorLayerUndoCommandChangeAttribute
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:64
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
#define tr(sourceText)