QGIS API Documentation  2.8.6-Wien
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 {
165  if ( !L->hasGeometryType() )
166  {
167  return false;
168  }
169 
170  if ( FID_IS_NEW( fid ) )
171  {
172  if ( !mAddedFeatures.contains( fid ) )
173  return false;
174  }
176  return false;
177 
178  // TODO: check compatible geometry
179 
180  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeGeometry( this, fid, geom ) );
181  return true;
182 }
183 
184 
185 bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
186 {
187  if ( FID_IS_NEW( fid ) )
188  {
189  if ( !mAddedFeatures.contains( fid ) )
190  return false;
191  }
193  {
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  //
262  // update geometries
263  //
264  if ( !mChangedGeometries.isEmpty() )
265  {
267  {
268  commitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
269 
271 
272  mChangedGeometries.clear();
273  }
274  else
275  {
276  commitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
277  success = false;
278  }
279  }
280 
281  QgsFields oldFields = L->pendingFields();
282 
283  //
284  // delete attributes
285  //
286  bool attributesChanged = false;
287  if ( !mDeletedAttributeIds.isEmpty() )
288  {
290  {
291  commitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
292 
294 
295  mDeletedAttributeIds.clear();
296  attributesChanged = true;
297  }
298  else
299  {
300  commitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
301 #if 0
302  QString list = "ERROR: Pending attribute deletes:";
303  foreach ( int idx, mDeletedAttributeIds )
304  {
305  list.append( " " + L->pendingFields()[idx].name() );
306  }
307  commitErrors << list;
308 #endif
309  success = false;
310  }
311  }
312 
313  //
314  // add attributes
315  //
316  if ( !mAddedAttributes.isEmpty() )
317  {
319  {
320  commitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributes.size() );
321 
323 
324  mAddedAttributes.clear();
325  attributesChanged = true;
326  }
327  else
328  {
329  commitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributes.size() );
330 #if 0
331  QString list = "ERROR: Pending adds:";
332  foreach ( QgsField f, mAddedAttributes )
333  {
334  list.append( " " + f.name() );
335  }
336  commitErrors << list;
337 #endif
338  success = false;
339  }
340  }
341 
342  //
343  // check that addition/removal went as expected
344  //
345  bool attributeChangesOk = true;
346  if ( attributesChanged )
347  {
348  L->updateFields();
349  QgsFields newFields = L->pendingFields();
350 
351  if ( oldFields.count() != newFields.count() )
352  {
353  commitErrors << tr( "ERROR: the count of fields is incorrect after addition/removal of fields!" );
354  attributeChangesOk = false; // don't try attribute updates - they'll fail.
355  }
356 
357  for ( int i = 0; i < qMin( oldFields.count(), newFields.count() ); ++i )
358  {
359  const QgsField& oldField = oldFields[i];
360  const QgsField& newField = newFields[i];
361  if ( attributeChangesOk && oldField != newField )
362  {
363  commitErrors
364  << tr( "ERROR: field with index %1 is not the same!" ).arg( i )
365  << tr( "Provider: %1" ).arg( L->providerType() )
366  << tr( "Storage: %1" ).arg( L->storageType() )
367  << QString( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
368  .arg( tr( "expected field" ) )
369  .arg( oldField.name() )
370  .arg( QVariant::typeToName( oldField.type() ) )
371  .arg( oldField.typeName() )
372  .arg( oldField.length() )
373  .arg( oldField.precision() )
374  << QString( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
375  .arg( tr( "retrieved field" ) )
376  .arg( newField.name() )
377  .arg( QVariant::typeToName( newField.type() ) )
378  .arg( newField.typeName() )
379  .arg( newField.length() )
380  .arg( newField.precision() );
381  attributeChangesOk = false; // don't try attribute updates - they'll fail.
382  }
383  }
384  }
385 
386  if ( attributeChangesOk )
387  {
388  //
389  // change attributes
390  //
391  if ( !mChangedAttributeValues.isEmpty() )
392  {
394  {
395  commitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
396 
398 
399  mChangedAttributeValues.clear();
400  }
401  else
402  {
403  commitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
404 #if 0
405  QString list = "ERROR: pending changes:";
406  foreach ( QgsFeatureId id, mChangedAttributeValues.keys() )
407  {
408  list.append( "\n " + FID_TO_STRING( id ) + "[" );
409  foreach ( int idx, mChangedAttributeValues[ id ].keys() )
410  {
411  list.append( QString( " %1:%2" ).arg( L->pendingFields()[idx].name() ).arg( mChangedAttributeValues[id][idx].toString() ) );
412  }
413  list.append( " ]" );
414  }
415  commitErrors << list;
416 #endif
417  success = false;
418  }
419  }
420 
421  //
422  // delete features
423  //
424  if ( success && !mDeletedFeatureIds.isEmpty() )
425  {
427  {
428  commitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
429  // TODO[MD]: we should not need this here
430  for ( QgsFeatureIds::const_iterator it = mDeletedFeatureIds.begin(); it != mDeletedFeatureIds.end(); ++it )
431  {
432  mChangedAttributeValues.remove( *it );
433  mChangedGeometries.remove( *it );
434  }
435 
437 
438  mDeletedFeatureIds.clear();
439  }
440  else
441  {
442  commitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
443 #if 0
444  QString list = "ERROR: pending deletes:";
445  foreach ( QgsFeatureId id, mDeletedFeatureIds )
446  {
447  list.append( " " + FID_TO_STRING( id ) );
448  }
449  commitErrors << list;
450 #endif
451  success = false;
452  }
453  }
454 
455  //
456  // add features
457  //
458  if ( success && !mAddedFeatures.isEmpty() )
459  {
461  {
462  QList<QgsFeatureId> ids;
463  QgsFeatureList featuresToAdd;
464  // get the list of added features in reversed order
465  // 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)
466  mapToReversedLists( mAddedFeatures, ids, featuresToAdd );
467 
468  if ( provider->addFeatures( featuresToAdd ) )
469  {
470  commitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", featuresToAdd.size() );
471 
472  emit committedFeaturesAdded( L->id(), featuresToAdd );
473 
474  // notify everyone that the features with temporary ids were updated with permanent ids
475  for ( int i = 0; i < featuresToAdd.count(); ++i )
476  {
477  if ( featuresToAdd[i].id() != ids[i] )
478  {
479  //update selection
480  if ( L->mSelectedFeatureIds.contains( ids[i] ) )
481  {
482  L->mSelectedFeatureIds.remove( ids[i] );
483  L->mSelectedFeatureIds.insert( featuresToAdd[i].id() );
484  }
485  emit featureDeleted( ids[i] );
486  emit featureAdded( featuresToAdd[i].id() );
487  }
488  }
489 
490  mAddedFeatures.clear();
491  }
492  else
493  {
494  commitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
495 #if 0
496  QString list = "ERROR: pending adds:";
497  foreach ( QgsFeature f, mAddedFeatures )
498  {
499  list.append( " " + FID_TO_STRING( f.id() ) + "[" );
500  for ( int i = 0; i < L->pendingFields().size(); i++ )
501  {
502  list.append( QString( " %1:%2" ).arg( L->pendingFields()[i].name() ).arg( f.attributes()[i].toString() ) );
503  }
504  list.append( " ]" );
505  }
506  commitErrors << list;
507 #endif
508  success = false;
509  }
510  }
511  else
512  {
513  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
514  success = false;
515  }
516  }
517  }
518  else
519  {
520  success = false;
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:60
static unsigned index
void handleAttributeDeleted(int index)
update added and changed features after removal of an attribute
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:180
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.
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:181
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:365
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features.
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:80
#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.
allows deletion of attributes (fields)
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:179
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:156
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)
void setGeometry(const QgsGeometry &geom)
Set this feature&#39;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
allows addition of new attributes (fields)
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.
int fieldOriginIndex(int fieldIdx) const
Get field&#39;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:185
allows modifications of geometries
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:202
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
void clearErrors()
Clear recorded errors.
int count() const
Return number of items.
Definition: qgsfield.h:214
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:226
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
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
const QString & typeName() const
Gets the field type.
Definition: qgsfield.cpp:70
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:75
int size() const
Return number of items.
Definition: qgsfield.h:216
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:247
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
QUndoStack * undoStack()
Return pointer to layer&#39;s undo stack.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
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.
A vector of attributes.
Definition: qgsfeature.h:103
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.
field is calculated from an expression
Definition: qgsfield.h:182
QgsAttributeList mDeletedAttributeIds
deleted attributes fields which are not commited.
allows modification of attribute values
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&#39;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:65
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
#define tr(sourceText)