QGIS API Documentation  2.99.0-Master (6a61179)
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 
24 template <class Key, class T> void mapToReversedLists( const QMap< Key, T >& map, QList<Key>& ks, QList<T>& vs )
25 {
26  ks.reserve( map.size() );
27  vs.reserve( map.size() );
28  typename QMap<Key, T>::const_iterator i = map.constEnd();
29  while ( i-- != map.constBegin() )
30  {
31  ks.append( i.key() );
32  vs.append( i.value() );
33  }
34 }
35 
36 
38  : L( layer )
39 {
40  connect( L->undoStack(), &QUndoStack::indexChanged, this, &QgsVectorLayerEditBuffer::undoIndexChanged ); // TODO[MD]: queued?
41 }
42 
44 {
45 }
46 
47 
49 {
50  return !L->undoStack()->isClean();
51 }
52 
53 
55 {
56  QgsDebugMsgLevel( QString( "undo index changed %1" ).arg( index ), 4 );
57  Q_UNUSED( index );
58  emit layerModified();
59 }
60 
61 
63 {
64  // delete attributes from the higher indices to lower indices
65  for ( int i = mDeletedAttributeIds.count() - 1; i >= 0; --i )
66  {
67  fields.remove( mDeletedAttributeIds.at( i ) );
68  }
69  // add new fields
70  for ( int i = 0; i < mAddedAttributes.count(); ++i )
71  {
72  fields.append( mAddedAttributes.at( i ), QgsFields::OriginEdit, i );
73  }
74  // rename fields
75  QgsFieldNameMap::const_iterator renameIt = mRenamedAttributes.constBegin();
76  for ( ; renameIt != mRenamedAttributes.constEnd(); ++renameIt )
77  {
78  fields[ renameIt.key()].setName( renameIt.value() );
79  }
80 }
81 
82 
84 {
85  if ( mChangedGeometries.contains( f.id() ) )
87 }
88 
89 
91 {
92  QgsAttributes attrs = f.attributes();
93 
94  // remove all attributes that will disappear - from higher indices to lower
95  for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
96  {
97  attrs.remove( mDeletedAttributeIds[idx] );
98  }
99 
100  // adjust size to accommodate added attributes
101  attrs.resize( attrs.count() + mAddedAttributes.count() );
102 
103  // update changed attributes
104  if ( mChangedAttributeValues.contains( f.id() ) )
105  {
106  const QgsAttributeMap &map = mChangedAttributeValues[f.id()];
107  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
108  attrs[it.key()] = it.value();
109  }
110 
111  f.setAttributes( attrs );
112 }
113 
114 
115 
116 
118 {
120  {
121  return false;
122  }
123  if ( L->mFields.count() != f.attributes().count() )
124  return false;
125 
126  // TODO: check correct geometry type
127 
128  L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) );
129  return true;
130 }
131 
132 
134 {
136  return false;
137 
138  bool result = true;
139  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
140  {
141  result = result && addFeature( *iter );
142  }
143 
144  L->updateExtents();
145  return result;
146 }
147 
148 
149 
151 {
153  {
154  QgsDebugMsg( "Cannot delete features (missing DeleteFeature capability)" );
155  return false;
156  }
157 
158  if ( FID_IS_NEW( fid ) )
159  {
160  if ( !mAddedFeatures.contains( fid ) )
161  {
162  QgsDebugMsg( "Cannot delete features (in the list of added features)" );
163  return false;
164  }
165  }
166  else // existing feature
167  {
168  if ( mDeletedFeatureIds.contains( fid ) )
169  {
170  QgsDebugMsg( "Cannot delete features (in the list of deleted features)" );
171  return false;
172  }
173  }
174 
175  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteFeature( this, fid ) );
176  return true;
177 }
178 
180 {
182  {
183  QgsDebugMsg( "Cannot delete features (missing DeleteFeatures capability)" );
184  return false;
185  }
186 
187  bool ok = true;
188  Q_FOREACH ( QgsFeatureId fid, fids )
189  ok = deleteFeature( fid ) && ok;
190 
191  return ok;
192 }
193 
194 
196 {
197  if ( !L->hasGeometryType() )
198  {
199  return false;
200  }
201 
202  if ( FID_IS_NEW( fid ) )
203  {
204  if ( !mAddedFeatures.contains( fid ) )
205  return false;
206  }
208  return false;
209 
210  // TODO: check compatible geometry
211 
212  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeGeometry( this, fid, geom ) );
213  return true;
214 }
215 
216 
217 bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
218 {
219  if ( FID_IS_NEW( fid ) )
220  {
221  if ( !mAddedFeatures.contains( fid ) )
222  return false;
223  }
225  {
226  return false;
227  }
228 
229  if ( field < 0 || field >= L->fields().count() ||
230  L->fields().fieldOrigin( field ) == QgsFields::OriginJoin ||
232  return false;
233 
234  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeAttribute( this, fid, field, newValue, oldValue ) );
235  return true;
236 }
237 
238 
240 {
242  return false;
243 
244  if ( field.name().isEmpty() )
245  return false;
246 
247  Q_FOREACH ( const QgsField& updatedField, L->fields() )
248  {
249  if ( updatedField.name() == field.name() )
250  return false;
251  }
252 
253  if ( !L->dataProvider()->supportedType( field ) )
254  return false;
255 
256  L->undoStack()->push( new QgsVectorLayerUndoCommandAddAttribute( this, field ) );
257  return true;
258 }
259 
260 
262 {
264  return false;
265 
266  if ( index < 0 || index >= L->fields().count() )
267  return false;
268 
269  // find out source of the field
270  QgsFields::FieldOrigin origin = L->fields().fieldOrigin( index );
271  int originIndex = L->fields().fieldOriginIndex( index );
272 
273  if ( origin == QgsFields::OriginProvider && mDeletedAttributeIds.contains( originIndex ) )
274  return false;
275 
276  if ( origin == QgsFields::OriginJoin )
277  return false;
278 
279  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteAttribute( this, index ) );
280  return true;
281 }
282 
283 bool QgsVectorLayerEditBuffer::renameAttribute( int index, const QString& newName )
284 {
286  return false;
287 
288  if ( newName.isEmpty() )
289  return false;
290 
291  if ( index < 0 || index >= L->fields().count() )
292  return false;
293 
294  Q_FOREACH ( const QgsField& updatedField, L->fields() )
295  {
296  if ( updatedField.name() == newName )
297  return false;
298  }
299 
300  L->undoStack()->push( new QgsVectorLayerUndoCommandRenameAttribute( this, index, newName ) );
301  return true;
302 }
303 
304 
305 bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
306 {
307  QgsVectorDataProvider* provider = L->dataProvider();
308  commitErrors.clear();
309 
310  int cap = provider->capabilities();
311  bool success = true;
312 
313  // geometry updates attribute updates
314  // yes no => changeGeometryValues
315  // no yes => changeAttributeValues
316  // yes yes => changeFeatures
317 
318  //
319  // update geometries
320  //
321  if ( !mChangedGeometries.isEmpty() && (( cap & QgsVectorDataProvider::ChangeFeatures ) == 0 || mChangedAttributeValues.isEmpty() ) )
322  {
323  if ( provider->changeGeometryValues( mChangedGeometries ) )
324  {
325  commitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
326 
328  mChangedGeometries.clear();
329  }
330  else
331  {
332  commitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
333  success = false;
334  }
335  }
336 
337  QgsFields oldFields = L->fields();
338 
339  //
340  // delete attributes
341  //
342  bool attributesChanged = false;
343  if ( !mDeletedAttributeIds.isEmpty() )
344  {
346  {
347  commitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
348 
350 
351  mDeletedAttributeIds.clear();
352  attributesChanged = true;
353  }
354  else
355  {
356  commitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
357 #if 0
358  QString list = "ERROR: Pending attribute deletes:";
359  Q_FOREACH ( int idx, mDeletedAttributeIds )
360  {
361  list.append( ' ' + L->pendingFields().at( idx ).name() );
362  }
363  commitErrors << list;
364 #endif
365  success = false;
366  }
367  }
368 
369  //
370  // add attributes
371  //
372  if ( !mAddedAttributes.isEmpty() )
373  {
375  {
376  commitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributes.size() );
377 
379 
380  mAddedAttributes.clear();
381  attributesChanged = true;
382  }
383  else
384  {
385  commitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributes.size() );
386 #if 0
387  QString list = "ERROR: Pending adds:";
388  Q_FOREACH ( QgsField f, mAddedAttributes )
389  {
390  list.append( ' ' + f.name() );
391  }
392  commitErrors << list;
393 #endif
394  success = false;
395  }
396  }
397 
398  // rename attributes
399  if ( !mRenamedAttributes.isEmpty() )
400  {
402  {
403  commitErrors << tr( "SUCCESS: %n attribute(s) renamed.", "renamed attributes count", mRenamedAttributes.size() );
404 
406 
407  mRenamedAttributes.clear();
408  attributesChanged = true;
409  }
410  else
411  {
412  commitErrors << tr( "ERROR: %n attribute(s) not renamed", "not renamed attributes count", mRenamedAttributes.size() );
413  success = false;
414  }
415  }
416 
417  //
418  // check that addition/removal went as expected
419  //
420  bool attributeChangesOk = true;
421  if ( attributesChanged )
422  {
423  L->updateFields();
424  QgsFields newFields = L->fields();
425 
426  if ( oldFields.count() != newFields.count() )
427  {
428  commitErrors << tr( "ERROR: the count of fields is incorrect after addition/removal of fields!" );
429  attributeChangesOk = false; // don't try attribute updates - they'll fail.
430  }
431 
432  for ( int i = 0; i < qMin( oldFields.count(), newFields.count() ); ++i )
433  {
434  QgsField oldField = oldFields.at( i );
435  QgsField newField = newFields.at( i );
436  if ( attributeChangesOk && oldField != newField )
437  {
438  commitErrors
439  << tr( "ERROR: field with index %1 is not the same!" ).arg( i )
440  << tr( "Provider: %1" ).arg( L->providerType() )
441  << tr( "Storage: %1" ).arg( L->storageType() )
442  << QStringLiteral( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
443  .arg( tr( "expected field" ),
444  oldField.name(),
445  QVariant::typeToName( oldField.type() ),
446  oldField.typeName() )
447  .arg( oldField.length() )
448  .arg( oldField.precision() )
449  << QStringLiteral( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
450  .arg( tr( "retrieved field" ),
451  newField.name(),
452  QVariant::typeToName( newField.type() ),
453  newField.typeName() )
454  .arg( newField.length() )
455  .arg( newField.precision() );
456  attributeChangesOk = false; // don't try attribute updates - they'll fail.
457  }
458  }
459  }
460 
461  if ( attributeChangesOk )
462  {
464  {
466 
468  {
469  commitErrors << tr( "SUCCESS: %1 attribute value(s) and %2 geometries changed." ).arg( mChangedAttributeValues.size(), mChangedGeometries.size() );
471  mChangedAttributeValues.clear();
472 
474  mChangedGeometries.clear();
475  }
476  else
477  {
478  success = false;
479  }
480  }
481  else
482  {
483  //
484  // change attributes
485  //
486  if ( !mChangedAttributeValues.isEmpty() && (( cap & QgsVectorDataProvider::ChangeFeatures ) == 0 || mChangedGeometries.isEmpty() ) )
487  {
489  {
490  commitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
491 
493  mChangedAttributeValues.clear();
494  }
495  else
496  {
497  commitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
498 #if 0
499  QString list = "ERROR: pending changes:";
500  Q_FOREACH ( QgsFeatureId id, mChangedAttributeValues.keys() )
501  {
502  list.append( "\n " + FID_TO_STRING( id ) + '[' );
503  Q_FOREACH ( int idx, mChangedAttributeValues[ id ].keys() )
504  {
505  list.append( QString( " %1:%2" ).arg( L->pendingFields().at( idx ).name() ).arg( mChangedAttributeValues[id][idx].toString() ) );
506  }
507  list.append( " ]" );
508  }
509  commitErrors << list;
510 #endif
511  success = false;
512  }
513  }
514  }
515 
516  //
517  // delete features
518  //
519  if ( success && !mDeletedFeatureIds.isEmpty() )
520  {
522  {
523  commitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
524  // TODO[MD]: we should not need this here
525  Q_FOREACH ( QgsFeatureId id, mDeletedFeatureIds )
526  {
527  mChangedAttributeValues.remove( id );
528  mChangedGeometries.remove( id );
529  }
530 
532 
533  mDeletedFeatureIds.clear();
534  }
535  else
536  {
537  commitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
538 #if 0
539  QString list = "ERROR: pending deletes:";
540  Q_FOREACH ( QgsFeatureId id, mDeletedFeatureIds )
541  {
542  list.append( ' ' + FID_TO_STRING( id ) );
543  }
544  commitErrors << list;
545 #endif
546  success = false;
547  }
548  }
549 
550  //
551  // add features
552  //
553  if ( success && !mAddedFeatures.isEmpty() )
554  {
556  {
557  QList<QgsFeatureId> ids;
558  QgsFeatureList featuresToAdd;
559  // get the list of added features in reversed order
560  // 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)
561  mapToReversedLists( mAddedFeatures, ids, featuresToAdd );
562 
563  if ( provider->addFeatures( featuresToAdd ) )
564  {
565  commitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", featuresToAdd.size() );
566 
567  emit committedFeaturesAdded( L->id(), featuresToAdd );
568 
569  // notify everyone that the features with temporary ids were updated with permanent ids
570  for ( int i = 0; i < featuresToAdd.count(); ++i )
571  {
572  if ( featuresToAdd[i].id() != ids[i] )
573  {
574  //update selection
575  if ( L->mSelectedFeatureIds.contains( ids[i] ) )
576  {
577  L->mSelectedFeatureIds.remove( ids[i] );
578  L->mSelectedFeatureIds.insert( featuresToAdd[i].id() );
579  }
580  emit featureDeleted( ids[i] );
581  emit featureAdded( featuresToAdd[i].id() );
582  }
583  }
584 
585  mAddedFeatures.clear();
586  }
587  else
588  {
589  commitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
590 #if 0
591  QString list = "ERROR: pending adds:";
592  Q_FOREACH ( QgsFeature f, mAddedFeatures )
593  {
594  list.append( ' ' + FID_TO_STRING( f.id() ) + '[' );
595  for ( int i = 0; i < L->pendingFields().size(); i++ )
596  {
597  list.append( QString( " %1:%2" ).arg( L->pendingFields().at( i ).name() ).arg( f.attributes()[i].toString() ) );
598  }
599  list.append( " ]" );
600  }
601  commitErrors << list;
602 #endif
603  success = false;
604  }
605  }
606  else
607  {
608  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
609  success = false;
610  }
611  }
612  }
613  else
614  {
615  success = false;
616  }
617 
618  if ( !success && provider->hasErrors() )
619  {
620  commitErrors << tr( "\n Provider errors:" );
621  Q_FOREACH ( QString e, provider->errors() )
622  {
623  commitErrors << " " + e.replace( '\n', QLatin1String( "\n " ) );
624  }
625  provider->clearErrors();
626  }
627 
628  return success;
629 }
630 
631 
633 {
634  if ( !isModified() )
635  return;
636 
637  // limit canvas redraws to one by jumping to beginning of stack
638  // see QgsUndoWidget::indexChanged
639  L->undoStack()->setIndex( 0 );
640 
641  Q_ASSERT( mAddedAttributes.isEmpty() );
642  Q_ASSERT( mDeletedAttributeIds.isEmpty() );
643  Q_ASSERT( mChangedAttributeValues.isEmpty() );
644  Q_ASSERT( mChangedGeometries.isEmpty() );
645  Q_ASSERT( mAddedFeatures.isEmpty() );
646 }
647 
648 #if 0
649 QString QgsVectorLayerEditBuffer::dumpEditBuffer()
650 {
651  QString msg;
652  if ( !mChangedGeometries.isEmpty() )
653  {
654  msg += "CHANGED GEOMETRIES:\n";
655  for ( QgsGeometryMap::const_iterator it = mChangedGeometries.begin(); it != mChangedGeometries.end(); ++it )
656  {
657  // QgsFeatureId, QgsGeometry
658  msg += QString( "- FID %1: %2" ).arg( it.key() ).arg( it.value().to );
659  }
660  }
661  return msg;
662 }
663 #endif
664 
666 {
667  // go through the changed attributes map and adapt indices
668  QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
669  for ( ; it != mChangedAttributeValues.end(); ++it )
670  {
671  updateAttributeMapIndex( it.value(), index, + 1 );
672  }
673 
674  // go through added features and adapt attributes
675  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
676  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
677  {
678  QgsAttributes attrs = featureIt->attributes();
679  attrs.insert( index, QVariant() );
680  featureIt->setAttributes( attrs );
681  }
682 
683  // go through renamed attributes and adapt
684  QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
685  //sort keys
686  qSort( sortedRenamedIndices.begin(), sortedRenamedIndices.end(), qGreater< int >() );
687  Q_FOREACH ( int renameIndex, sortedRenamedIndices )
688  {
689  if ( renameIndex >= index )
690  {
691  mRenamedAttributes[ renameIndex + 1 ] = mRenamedAttributes.value( renameIndex );
692  }
693  }
694  //remove last
695  mRenamedAttributes.remove( index );
696 }
697 
699 {
700  // go through the changed attributes map and adapt indices
701  QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
702  for ( ; it != mChangedAttributeValues.end(); ++it )
703  {
704  QgsAttributeMap& attrMap = it.value();
705  // remove the attribute
706  if ( attrMap.contains( index ) )
707  attrMap.remove( index );
708 
709  // update attribute indices
710  updateAttributeMapIndex( attrMap, index, -1 );
711  }
712 
713  // go through added features and adapt attributes
714  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
715  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
716  {
717  QgsAttributes attrs = featureIt->attributes();
718  attrs.remove( index );
719  featureIt->setAttributes( attrs );
720  }
721 
722  // go through rename attributes and adapt
723  QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
724  //sort keys
725  qSort( sortedRenamedIndices.begin(), sortedRenamedIndices.end() );
726  int last = -1;
727  mRenamedAttributes.remove( index );
728  Q_FOREACH ( int renameIndex, sortedRenamedIndices )
729  {
730  if ( renameIndex > index )
731  {
732  mRenamedAttributes.insert( renameIndex - 1, mRenamedAttributes.value( renameIndex ) );
733  last = renameIndex;
734  }
735  }
736  //remove last
737  if ( last > -1 )
738  mRenamedAttributes.remove( last );
739 }
740 
741 
742 
744 {
745  QgsAttributeMap updatedMap;
746  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
747  {
748  int attrIndex = it.key();
749  updatedMap.insert( attrIndex < index ? attrIndex : attrIndex + offset, it.value() );
750  }
751  map = updatedMap;
752 }
753 
754 
755 
757 {
758  L->updateFields();
759 }
void updateFields()
Assembles mUpdatedFields considering provider fields, joined fields and added fields.
void updateChangedAttributes(QgsFeature &f)
Update feature with uncommitted attribute updates.
QgsFeatureId id
Definition: qgsfeature.h:139
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: qgsfields.h:44
virtual bool renameAttribute(int attr, const QString &newName)
Renames an attribute field (but does not commit it)
virtual bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
int size() const
Return number of items.
Definition: qgsfields.cpp:122
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfields.cpp:163
virtual Capabilities capabilities() const
Returns flags containing the supported capabilities.
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
QString name
Definition: qgsfield.h:55
QMap< int, QVariant > QgsAttributeMap
Definition: qgsfeature.h:44
int precision
Definition: qgsfield.h:53
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)
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
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: qgsfields.h:45
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:355
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:360
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features.
virtual bool renameAttributes(const QgsFieldNameMap &renamedAttributes)
Renames existing attributes.
#define FID_TO_STRING(fid)
Definition: qgsfeature.h:40
friend class QgsVectorLayerUndoCommandChangeGeometry
Container of fields for a vector layer.
Definition: qgsfields.h:36
virtual void rollBack()
Stop editing and discard the edits.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:78
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:153
friend class QgsVectorLayerUndoCommandAddAttribute
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not committed.
void updateFeatureGeometry(QgsFeature &f)
Update feature with uncommitted 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: qgsfields.h:43
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:135
QgsFieldNameMap mRenamedAttributes
Renamed attributes which are not committed.
friend class QgsVectorLayerUndoCommandRenameAttribute
virtual bool addFeatures(QgsFeatureList &flist)
Adds a list of features.
int count() const
Return number of items.
Definition: qgsfields.cpp:117
friend class QgsVectorLayerUndoCommandDeleteAttribute
virtual void updateExtents()
Update the extents for the layer.
bool supportedType(const QgsField &field) const
check if provider supports type of field
QgsFields fields() const
Returns the list of fields of this layer.
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:137
int length
Definition: qgsfield.h:52
int fieldOriginIndex(int fieldIdx) const
Get field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfields.cpp:171
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
void featureAdded(QgsFeatureId fid)
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsMapLayerRegistry.
Allows addition of new attributes (fields)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:108
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
virtual bool changeFeatures(const QgsChangedAttributesMap &attr_map, const QgsGeometryMap &geometry_map)
Changes attribute values and geometries of existing features.
QgsGeometryMap mChangedGeometries
Changed geometries which are not committed.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QStringList errors() const
Get recorded errors.
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature&#39;s geometry.
void handleAttributeAdded(int index)
Update added and changed features after addition of an attribute.
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: qgsfields.cpp:61
virtual bool deleteFeatures(const QgsFeatureIds &fid)
Deletes a set of features from the layer (but does not commit it)
void clearErrors()
Clear recorded errors.
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not committed.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:47
virtual bool changeGeometryValues(const QgsGeometryMap &geometry_map)
Changes geometries of existing features.
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) ...
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfields.cpp:85
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
Supports joint updates for attributes and geometry Providers supporting this should still define Chan...
QList< QgsField > mAddedAttributes
Added attributes fields which are not committed.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
void committedAttributesRenamed(const QString &layerId, const QgsFieldNameMap &renamedAttributes)
Emitted after committing an attribute rename.
bool hasErrors() const
Provider has errors to report.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:162
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:32
QgsFields pendingFields() const
Returns the list of fields of this layer.
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:38
QUndoStack * undoStack()
Return pointer to layer&#39;s undo stack.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
QgsVectorDataProvider * dataProvider()
Returns the data provider.
QString providerType() const
Return the provider type for this layer.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
This is the base class for vector data providers.
QgsFeatureMap mAddedFeatures
New features which are not committed.
A vector of attributes.
Definition: qgsfeature.h:55
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.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:98
Field is calculated from an expression.
Definition: qgsfields.h:46
QgsAttributeList mDeletedAttributeIds
Deleted attributes fields which are not committed. The list is kept sorted.
Allows modification of attribute values.
void featureDeleted(QgsFeatureId fid)
QgsAttributes attributes
Definition: qgsfeature.h:140
Supports renaming attributes (fields). Added in QGIS 2.16.
friend class QgsVectorLayerUndoCommandChangeAttribute