QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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"
21 #include "qgsvectordataprovider.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsvectorlayerutils.h"
24 #include "qgsmessagelog.h"
25 
26 
28 template <class Key, class T> void mapToReversedLists( const QMap< Key, T > &map, QList<Key> &ks, QList<T> &vs )
29 {
30  ks.reserve( map.size() );
31  vs.reserve( map.size() );
32  typename QMap<Key, T>::const_iterator i = map.constEnd();
33  while ( i-- != map.constBegin() )
34  {
35  ks.append( i.key() );
36  vs.append( i.value() );
37  }
38 }
39 
40 
42  : L( layer )
43 {
44  connect( L->undoStack(), &QUndoStack::indexChanged, this, &QgsVectorLayerEditBuffer::undoIndexChanged ); // TODO[MD]: queued?
45 }
46 
48 {
49  return !L->undoStack()->isClean();
50 }
51 
52 
54 {
55  QgsDebugMsgLevel( QStringLiteral( "undo index changed %1" ).arg( index ), 4 );
56  Q_UNUSED( index )
57  emit layerModified();
58 }
59 
60 
62 {
63  // delete attributes from the higher indices to lower indices
64  for ( int i = mDeletedAttributeIds.count() - 1; i >= 0; --i )
65  {
66  fields.remove( mDeletedAttributeIds.at( i ) );
67  }
68 
69  // rename fields
70  QgsFieldNameMap::const_iterator renameIt = mRenamedAttributes.constBegin();
71  for ( ; renameIt != mRenamedAttributes.constEnd(); ++renameIt )
72  {
73  fields.rename( renameIt.key(), renameIt.value() );
74  }
75 
76  // add new fields
77  for ( int i = 0; i < mAddedAttributes.count(); ++i )
78  {
79  fields.append( mAddedAttributes.at( i ), QgsFields::OriginEdit, i );
80  }
81 }
82 
84 {
85  return mEditBufferGroup;
86 }
87 
89 {
91 }
92 
94 {
95  if ( mChangedGeometries.contains( f.id() ) )
97 }
98 
99 
101 {
102  QgsAttributes attrs = f.attributes();
103 
104  // remove all attributes that will disappear - from higher indices to lower
105  for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
106  {
107  attrs.remove( mDeletedAttributeIds[idx] );
108  }
109 
110  // adjust size to accommodate added attributes
111  attrs.resize( attrs.count() + mAddedAttributes.count() );
112 
113  // update changed attributes
114  if ( mChangedAttributeValues.contains( f.id() ) )
115  {
116  const QgsAttributeMap &map = mChangedAttributeValues[f.id()];
117  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
118  attrs[it.key()] = it.value();
119  }
120 
121  f.setAttributes( attrs );
122 }
123 
124 
125 
126 
128 {
130  {
131  return false;
132  }
133  if ( L->mFields.count() != f.attributes().count() )
134  {
135  QgsMessageLog::logMessage( tr( "cannot add feature, wrong field count: layer: %1 feature: %2:" ).arg( L->mFields.count() ).arg( f.attributes().count() ) );
136  return false;
137  }
138 
139  // TODO: check correct geometry type
140 
141  L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) );
142  return true;
143 }
144 
145 
147 {
149  return false;
150 
151  bool result = true;
152  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
153  {
154  result = result && addFeature( *iter );
155  }
156 
157  L->updateExtents();
158  return result;
159 }
160 
161 
162 
164 {
166  {
167  QgsDebugMsg( QStringLiteral( "Cannot delete features (missing DeleteFeature capability)" ) );
168  return false;
169  }
170 
171  if ( FID_IS_NEW( fid ) )
172  {
173  if ( !mAddedFeatures.contains( fid ) )
174  {
175  QgsDebugMsg( QStringLiteral( "Cannot delete features (in the list of added features)" ) );
176  return false;
177  }
178  }
179  else // existing feature
180  {
181  if ( mDeletedFeatureIds.contains( fid ) )
182  {
183  QgsDebugMsg( QStringLiteral( "Cannot delete features (in the list of deleted features)" ) );
184  return false;
185  }
186  }
187 
188  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteFeature( this, fid ) );
189  return true;
190 }
191 
193 {
195  {
196  QgsDebugMsg( QStringLiteral( "Cannot delete features (missing DeleteFeatures capability)" ) );
197  return false;
198  }
199 
200  bool ok = true;
201  const auto constFids = fids;
202  for ( QgsFeatureId fid : constFids )
203  ok = deleteFeature( fid ) && ok;
204 
205  return ok;
206 }
207 
208 
210 {
211  if ( !L->isSpatial() )
212  {
213  return false;
214  }
215 
216  if ( FID_IS_NEW( fid ) )
217  {
218  if ( !mAddedFeatures.contains( fid ) )
219  return false;
220  }
222  return false;
223 
224  // TODO: check compatible geometry
225 
226  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeGeometry( this, fid, geom ) );
227  return true;
228 }
229 
231 {
232  bool success = true;
233  for ( auto it = newValues.constBegin() ; it != newValues.constEnd(); ++it )
234  {
235  const int field = it.key();
236  const QVariant newValue = it.value();
237  QVariant oldValue;
238 
239  if ( oldValues.contains( field ) )
240  oldValue = oldValues[field];
241 
242  success &= changeAttributeValue( fid, field, newValue, oldValue );
243  }
244 
245  return success;
246 }
247 
248 bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
249 {
250  if ( FID_IS_NEW( fid ) )
251  {
252  if ( !mAddedFeatures.contains( fid ) )
253  return false;
254  }
256  {
257  return false;
258  }
259 
260  if ( field < 0 || field >= L->fields().count() ||
263  return false;
264 
265  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeAttribute( this, fid, field, newValue, oldValue ) );
266  return true;
267 }
268 
269 
271 {
273  return false;
274 
275  if ( field.name().isEmpty() )
276  return false;
277 
278  const QgsFields fields = L->fields();
279  for ( const QgsField &updatedField : fields )
280  {
281  if ( updatedField.name() == field.name() )
282  return false;
283  }
284 
285  if ( !L->dataProvider()->supportedType( field ) )
286  return false;
287 
288  L->undoStack()->push( new QgsVectorLayerUndoCommandAddAttribute( this, field ) );
289  return true;
290 }
291 
292 
294 {
296  return false;
297 
298  if ( index < 0 || index >= L->fields().count() )
299  return false;
300 
301  // find out source of the field
302  QgsFields::FieldOrigin origin = L->fields().fieldOrigin( index );
303  int originIndex = L->fields().fieldOriginIndex( index );
304 
305  if ( origin == QgsFields::OriginProvider && mDeletedAttributeIds.contains( originIndex ) )
306  return false;
307 
308  if ( origin == QgsFields::OriginJoin )
309  return false;
310 
311  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteAttribute( this, index ) );
312  return true;
313 }
314 
315 bool QgsVectorLayerEditBuffer::renameAttribute( int index, const QString &newName )
316 {
318  return false;
319 
320  if ( newName.isEmpty() )
321  return false;
322 
323  if ( index < 0 || index >= L->fields().count() )
324  return false;
325 
326  const QgsFields fields = L->fields();
327  for ( const QgsField &updatedField : fields )
328  {
329  if ( updatedField.name() == newName )
330  return false;
331  }
332 
333  L->undoStack()->push( new QgsVectorLayerUndoCommandRenameAttribute( this, index, newName ) );
334  return true;
335 }
336 
337 
338 bool QgsVectorLayerEditBuffer::commitChanges( QStringList &commitErrors )
339 {
340  commitErrors.clear();
341 
342  bool success = true;
343 
344  // geometry updates attribute updates
345  // yes no => changeGeometryValues
346  // no yes => changeAttributeValues
347  // yes yes => changeFeatures
348 
349  // Check geometry types
350  // to fix https://github.com/qgis/QGIS/issues/23663
351  if ( !mAddedFeatures.isEmpty() )
352  success &= commitChangesCheckGeometryTypeCompatibility( commitErrors );
353 
354  const QgsFields oldFields = L->fields();
355 
356  //
357  // delete attributes
358  //
359  bool attributesChanged = false;
360  if ( success && !mDeletedAttributeIds.isEmpty() )
361  {
362  bool attributesDeleted = false;
363  success &= commitChangesDeleteAttributes( attributesDeleted, commitErrors );
364  attributesChanged |= attributesDeleted;
365  }
366 
367  // rename attributes
368  if ( success && !mRenamedAttributes.isEmpty() )
369  {
370  bool attributesRenamed = false;
371  success &= commitChangesRenameAttributes( attributesRenamed, commitErrors );
372  attributesChanged |= attributesRenamed;
373  }
374 
375  //
376  // add attributes
377  //
378  if ( success && !mAddedAttributes.isEmpty() )
379  {
380  bool attributesAdded = false;
381  success &= commitChangesAddAttributes( attributesAdded, commitErrors );
382  attributesChanged |= attributesAdded;
383  }
384 
385  //
386  // check that addition/removal went as expected
387  //
388  if ( success && attributesChanged )
389  success &= commitChangesCheckAttributesModifications( oldFields, commitErrors );
390 
391  //
392  // change attributes
393  //
394  if ( success && ( !mChangedAttributeValues.isEmpty() || !mChangedGeometries.isEmpty() ) )
395  {
396  bool attributesChanged;
397  success &= commitChangesChangeAttributes( attributesChanged, commitErrors );
398  }
399 
400  //
401  // delete features
402  //
403  if ( success && !mDeletedFeatureIds.isEmpty() )
404  {
405  bool featuresDeleted;
406  success &= commitChangesDeleteFeatures( featuresDeleted, commitErrors );
407  }
408 
409  //
410  // add features
411  //
412  if ( success && !mAddedFeatures.isEmpty() )
413  {
414  bool featuresAdded;
415  success &= commitChangesAddFeatures( featuresAdded, commitErrors );
416  }
417 
418  QgsVectorDataProvider *provider = L->dataProvider();
419  if ( !success && provider->hasErrors() )
420  {
421  commitErrors << tr( "\n Provider errors:" );
422  const auto constErrors = provider->errors();
423  for ( QString e : constErrors )
424  {
425  commitErrors << " " + e.replace( '\n', QLatin1String( "\n " ) );
426  }
427  provider->clearErrors();
428  }
429 
430  return success;
431 }
432 
433 
435 {
436  if ( !isModified() )
437  return;
438 
439  // limit canvas redraws to one by jumping to beginning of stack
440  // see QgsUndoWidget::indexChanged
441  L->undoStack()->setIndex( 0 );
442 
443  Q_ASSERT( mAddedAttributes.isEmpty() );
444  Q_ASSERT( mDeletedAttributeIds.isEmpty() );
445  Q_ASSERT( mChangedAttributeValues.isEmpty() );
446  Q_ASSERT( mChangedGeometries.isEmpty() );
447  Q_ASSERT( mAddedFeatures.isEmpty() );
448 }
449 
451 {
452  return qgis::listToSet( mAddedFeatures.keys() ).unite( qgis::listToSet( mChangedAttributeValues.keys() ) ).unite( qgis::listToSet( mChangedGeometries.keys() ) );
453 }
454 
455 #if 0
456 QString QgsVectorLayerEditBuffer::dumpEditBuffer()
457 {
458  QString msg;
459  if ( !mChangedGeometries.isEmpty() )
460  {
461  msg += "CHANGED GEOMETRIES:\n";
462  for ( QgsGeometryMap::const_iterator it = mChangedGeometries.begin(); it != mChangedGeometries.end(); ++it )
463  {
464  // QgsFeatureId, QgsGeometry
465  msg += QString( "- FID %1: %2" ).arg( it.key() ).arg( it.value().to );
466  }
467  }
468  return msg;
469 }
470 #endif
471 
473 {
474  // go through the changed attributes map and adapt indices
475  QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
476  for ( ; it != mChangedAttributeValues.end(); ++it )
477  {
478  updateAttributeMapIndex( it.value(), index, + 1 );
479  }
480 
481  // go through added features and adapt attributes
482  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
483  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
484  {
485  QgsAttributes attrs = featureIt->attributes();
486  attrs.insert( index, QVariant() );
487  featureIt->setAttributes( attrs );
488  }
489 
490  // go through renamed attributes and adapt
491  QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
492  //sort keys
493  std::sort( sortedRenamedIndices.begin(), sortedRenamedIndices.end(), std::greater< int >() );
494  const auto constSortedRenamedIndices = sortedRenamedIndices;
495  for ( int renameIndex : constSortedRenamedIndices )
496  {
497  if ( renameIndex >= index )
498  {
499  mRenamedAttributes[ renameIndex + 1 ] = mRenamedAttributes.value( renameIndex );
500  }
501  }
502  //remove last
503  mRenamedAttributes.remove( index );
504 }
505 
507 {
508  // go through the changed attributes map and adapt indices
509  QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
510  for ( ; it != mChangedAttributeValues.end(); ++it )
511  {
512  QgsAttributeMap &attrMap = it.value();
513  // remove the attribute
514  if ( attrMap.contains( index ) )
515  attrMap.remove( index );
516 
517  // update attribute indices
518  updateAttributeMapIndex( attrMap, index, -1 );
519  }
520 
521  // go through added features and adapt attributes
522  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
523  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
524  {
525  QgsAttributes attrs = featureIt->attributes();
526  attrs.remove( index );
527  featureIt->setAttributes( attrs );
528  }
529 
530  // go through rename attributes and adapt
531  QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
532  //sort keys
533  std::sort( sortedRenamedIndices.begin(), sortedRenamedIndices.end() );
534  int last = -1;
535  mRenamedAttributes.remove( index );
536  const auto constSortedRenamedIndices = sortedRenamedIndices;
537  for ( int renameIndex : constSortedRenamedIndices )
538  {
539  if ( renameIndex > index )
540  {
541  mRenamedAttributes.insert( renameIndex - 1, mRenamedAttributes.value( renameIndex ) );
542  last = renameIndex;
543  }
544  }
545  //remove last
546  if ( last > -1 )
547  mRenamedAttributes.remove( last );
548 }
549 
550 
551 
553 {
554  QgsAttributeMap updatedMap;
555  for ( QgsAttributeMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
556  {
557  int attrIndex = it.key();
558  updatedMap.insert( attrIndex < index ? attrIndex : attrIndex + offset, it.value() );
559  }
560  map = updatedMap;
561 }
562 
563 
564 
566 {
567  L->updateFields();
568 }
569 
570 bool QgsVectorLayerEditBuffer::commitChangesCheckGeometryTypeCompatibility( QStringList &commitErrors )
571 {
572  if ( mAddedFeatures.isEmpty() )
573  return true;
574 
576  {
578  {
579  for ( const QgsFeature &f : std::as_const( mAddedFeatures ) )
580  {
581  if ( ( ! f.hasGeometry() ) ||
582  ( f.geometry().wkbType() == L->dataProvider()->wkbType() ) )
583  continue;
584 
585  if ( L->dataProvider()->convertToProviderType( f.geometry() ).isNull() )
586  {
587  commitErrors << tr( "ERROR: %n feature(s) not added - geometry type is not compatible with the current layer.", "not added features count", mAddedFeatures.size() );
588  return false;
589  }
590  }
591  }
592  }
593  else
594  {
595  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
596  return false;
597  }
598 
599  return true;
600 }
601 
602 bool QgsVectorLayerEditBuffer::commitChangesDeleteAttributes( bool &attributesDeleted, QStringList &commitErrors )
603 {
604  attributesDeleted = false;
605 
606  if ( mDeletedAttributeIds.isEmpty() )
607  return true;
608 
610  {
611  commitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
612 
614 
615  mDeletedAttributeIds.clear();
616  attributesDeleted = true;
617  }
618  else
619  {
620  commitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
621 #if 0
622  QString list = "ERROR: Pending attribute deletes:";
623  const auto constMDeletedAttributeIds = mDeletedAttributeIds;
624  for ( int idx : constMDeletedAttributeIds )
625  {
626  list.append( ' ' + L->fields().at( idx ).name() );
627  }
628  commitErrors << list;
629 #endif
630  return false;
631  }
632 
633  return true;
634 }
635 
636 bool QgsVectorLayerEditBuffer::commitChangesRenameAttributes( bool &attributesRenamed, QStringList &commitErrors )
637 {
638  attributesRenamed = false;
639 
640  if ( mRenamedAttributes.isEmpty() )
641  return true;
642 
644  {
645  commitErrors << tr( "SUCCESS: %n attribute(s) renamed.", "renamed attributes count", mRenamedAttributes.size() );
646 
648 
649  mRenamedAttributes.clear();
650  attributesRenamed = true;
651  }
652  else
653  {
654  commitErrors << tr( "ERROR: %n attribute(s) not renamed", "not renamed attributes count", mRenamedAttributes.size() );
655  return false;
656  }
657 
658  return true;
659 }
660 
661 bool QgsVectorLayerEditBuffer::commitChangesAddAttributes( bool &attributesAdded, QStringList &commitErrors )
662 {
663  attributesAdded = false;
664 
665  if ( mAddedAttributes.isEmpty() )
666  return true;
667 
669  {
670  commitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributes.size() );
672  mAddedAttributes.clear();
673  attributesAdded = true;
674  }
675  else
676  {
677  commitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributes.size() );
678 #if 0
679  QString list = "ERROR: Pending adds:";
680  const auto constMAddedAttributes = mAddedAttributes;
681  for ( QgsField f : constMAddedAttributes )
682  {
683  list.append( ' ' + f.name() );
684  }
685  commitErrors << list;
686 #endif
687  return false;
688  }
689 
690  return true;
691 }
692 
693 bool QgsVectorLayerEditBuffer::commitChangesCheckAttributesModifications( const QgsFields oldFields, QStringList &commitErrors )
694 {
695  L->updateFields();
696  QgsFields newFields = L->fields();
697 
698  if ( oldFields.count() != newFields.count() )
699  {
700  commitErrors << tr( "ERROR: the count of fields is incorrect after addition/removal of fields!" );
701  return false; // don't try attribute updates - they'll fail.
702  }
703 
704  for ( int i = 0; i < std::min( oldFields.count(), newFields.count() ); ++i )
705  {
706  QgsField oldField = oldFields.at( i );
707  QgsField newField = newFields.at( i );
708  if ( oldField != newField )
709  {
710  commitErrors
711  << tr( "ERROR: field with index %1 is not the same!" ).arg( i )
712  << tr( "Provider: %1" ).arg( L->providerType() )
713  << tr( "Storage: %1" ).arg( L->storageType() )
714  << QStringLiteral( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
715  .arg( tr( "expected field" ),
716  oldField.name(),
717  QVariant::typeToName( oldField.type() ),
718  oldField.typeName() )
719  .arg( oldField.length() )
720  .arg( oldField.precision() )
721  << QStringLiteral( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
722  .arg( tr( "retrieved field" ),
723  newField.name(),
724  QVariant::typeToName( newField.type() ),
725  newField.typeName() )
726  .arg( newField.length() )
727  .arg( newField.precision() );
728  return false; // don't try attribute updates - they'll fail.
729  }
730  }
731 
732  return true;
733 }
734 
735 bool QgsVectorLayerEditBuffer::commitChangesChangeAttributes( bool &attributesChanged, QStringList &commitErrors )
736 {
737  attributesChanged = false;
738 
740  {
742 
744  {
745  commitErrors << tr( "SUCCESS: %1 attribute value(s) and %2 geometries changed." ).arg( mChangedAttributeValues.size(), mChangedGeometries.size() );
746  attributesChanged = true;
748  mChangedAttributeValues.clear();
749 
751  mChangedGeometries.clear();
752  }
753  else
754  {
755  commitErrors << tr( "ERROR: %1 attributes and %2 geometries not changed.", "not changed attributes and geometries count" ).arg( mChangedAttributeValues.size() ).arg( mChangedGeometries.size() );
756  return false;
757  }
758  }
759 
760  if ( !mChangedGeometries.isEmpty() )
761  {
764  {
765  commitErrors << tr( "ERROR: %1 geometries not changed. Data provider '%2' does not have ChangeFeatures or ChangeGeometries capabilities", "not changed geometries count" )
766  .arg( mChangedGeometries.size() )
767  .arg( L->dataProvider()->name() );
768  return false;
769  }
770 
772  {
773  commitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
774  attributesChanged = true;
776  mChangedGeometries.clear();
777  }
778  else
779  {
780  commitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
781  return false;
782  }
783  }
784 
785  if ( !mChangedAttributeValues.isEmpty() )
786  {
789  {
790  commitErrors << tr( "ERROR: %1 attribute value change(s) not applied. Data provider '%2' does not have ChangeFeatures or ChangeAttributeValues capabilities", "not changed attribute values count" )
791  .arg( mChangedAttributeValues.size() )
792  .arg( L->dataProvider()->name() );
793  return false;
794  }
795 
797  {
798  commitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
799  attributesChanged = true;
801  mChangedAttributeValues.clear();
802  }
803  else
804  {
805  commitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
806 #if 0
807  QString list = "ERROR: pending changes:";
808  const auto constKeys = mChangedAttributeValues.keys();
809  for ( QgsFeatureId id : constKeys )
810  {
811  list.append( "\n " + FID_TO_STRING( id ) + '[' );
812  const auto constKeys = mChangedAttributeValues[ id ].keys();
813  for ( int idx : constKeys )
814  {
815  list.append( QString( " %1:%2" ).arg( L->fields().at( idx ).name() ).arg( mChangedAttributeValues[id][idx].toString() ) );
816  }
817  list.append( " ]" );
818  }
819  commitErrors << list;
820 #endif
821  return false;
822  }
823  }
824 
825  return true;
826 }
827 
828 bool QgsVectorLayerEditBuffer::commitChangesDeleteFeatures( bool &featuresDeleted, QStringList &commitErrors )
829 {
830  featuresDeleted = false;
831 
832  if ( mDeletedFeatureIds.isEmpty() )
833  return true;
834 
836  {
837  commitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
838  featuresDeleted = true;
839  // TODO[MD]: we should not need this here
840  for ( QgsFeatureId id : std::as_const( mDeletedFeatureIds ) )
841  {
842  mChangedAttributeValues.remove( id );
843  mChangedGeometries.remove( id );
844  }
845 
847 
848  mDeletedFeatureIds.clear();
849  }
850  else
851  {
852  commitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
853 #if 0
854  QString list = "ERROR: pending deletes:";
855  const auto constMDeletedFeatureIds = mDeletedFeatureIds;
856  for ( QgsFeatureId id : constMDeletedFeatureIds )
857  {
858  list.append( ' ' + FID_TO_STRING( id ) );
859  }
860  commitErrors << list;
861 #endif
862  return false;
863  }
864 
865  return true;
866 }
867 
868 bool QgsVectorLayerEditBuffer::commitChangesAddFeatures( bool &featuresAdded, QStringList &commitErrors )
869 {
870  featuresAdded = false;
871 
872  if ( mAddedFeatures.isEmpty() )
873  return true;
874 
876  {
877  QList<QgsFeatureId> ids;
878  QgsFeatureList featuresToAdd;
879  // get the list of added features in reversed order
880  // 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)
881  mapToReversedLists( mAddedFeatures, ids, featuresToAdd );
882 
883  // we need to strip any extra attributes here -- e.g. virtual fields, which should
884  // not be sent to the data provider. Refs #18784
885  for ( int i = 0; i < featuresToAdd.count(); ++i )
886  {
888  }
889 
890  if ( L->dataProvider()->addFeatures( featuresToAdd, QgsFeatureSink::Flag::RollBackOnErrors ) )
891  {
892  commitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", featuresToAdd.size() );
893  featuresAdded = true;
894  emit committedFeaturesAdded( L->id(), featuresToAdd );
895 
896  // notify everyone that the features with temporary ids were updated with permanent ids
897  for ( int i = 0; i < featuresToAdd.count(); ++i )
898  {
899  if ( featuresToAdd[i].id() != ids[i] )
900  {
901  //update selection
902  if ( L->mSelectedFeatureIds.contains( ids[i] ) )
903  {
904  L->mSelectedFeatureIds.remove( ids[i] );
905  L->mSelectedFeatureIds.insert( featuresToAdd[i].id() );
906  }
907  emit featureDeleted( ids[i] );
908  emit featureAdded( featuresToAdd[i].id() );
909  }
910  }
911 
912  mAddedFeatures.clear();
913  }
914  else
915  {
916  commitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
917 #if 0
918  QString list = "ERROR: pending adds:";
919  const auto constMAddedFeatures = mAddedFeatures;
920  for ( QgsFeature f : constMAddedFeatures )
921  {
922  list.append( ' ' + FID_TO_STRING( f.id() ) + '[' );
923  for ( int i = 0; i < L->fields().size(); i++ )
924  {
925  list.append( QString( " %1:%2" ).arg( L->fields().at( i ).name() ).arg( f.attributes()[i].toString() ) );
926  }
927  list.append( " ]" );
928  }
929  commitErrors << list;
930 #endif
931  return false;
932  }
933  }
934  else
935  {
936  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
937  return false;
938  }
939 
940  return true;
941 }
mapToReversedLists
void mapToReversedLists(const QMap< Key, T > &map, QList< Key > &ks, QList< T > &vs)
populate two lists (ks, vs) from map - in reverse order
Definition: qgsvectorlayereditbuffer.cpp:28
QgsFields::OriginProvider
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfields.h:51
QgsFields::FieldOrigin
FieldOrigin
Definition: qgsfields.h:48
QgsFields::OriginEdit
@ OriginEdit
Field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfields.h:53
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandChangeAttribute
friend class QgsVectorLayerUndoCommandChangeAttribute
Definition: qgsvectorlayereditbuffer.h:290
qgsvectorlayereditbuffergroup.h
QgsVectorDataProvider::DeleteFeatures
@ DeleteFeatures
Allows deletion of features.
Definition: qgsvectordataprovider.h:76
QgsVectorLayerEditBuffer::mAddedAttributes
QList< QgsField > mAddedAttributes
Added attributes fields which are not committed.
Definition: qgsvectorlayereditbuffer.h:323
QgsVectorDataProvider::deleteFeatures
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features from the provider.
Definition: qgsvectordataprovider.cpp:109
QgsVectorDataProvider::hasErrors
bool hasErrors() const
Provider has errors to report.
Definition: qgsvectordataprovider.cpp:734
QgsVectorLayer::updateExtents
virtual void updateExtents(bool force=false)
Update the extents for the layer.
Definition: qgsvectorlayer.cpp:862
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:676
QgsVectorLayerEditBuffer::isModified
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
Definition: qgsvectorlayereditbuffer.cpp:47
QgsVectorLayer::updateFields
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
Definition: qgsvectorlayer.cpp:3963
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandAddFeature
friend class QgsVectorLayerUndoCommandAddFeature
Definition: qgsvectorlayereditbuffer.h:287
QgsVectorDataProvider::DeleteAttributes
@ DeleteAttributes
Allows deletion of attributes (fields)
Definition: qgsvectordataprovider.h:79
QgsField::length
int length
Definition: qgsfield.h:56
QgsVectorLayerEditBuffer::mDeletedFeatureIds
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not committed.
Definition: qgsvectorlayereditbuffer.h:311
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsVectorLayerEditBuffer::addAttribute
virtual bool addAttribute(const QgsField &field)
Adds an attribute field (but does not commit it) returns true if the field was added.
Definition: qgsvectorlayereditbuffer.cpp:270
QgsVectorLayerEditBuffer::committedGeometriesChanges
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandAddAttribute
friend class QgsVectorLayerUndoCommandAddAttribute
Definition: qgsvectorlayereditbuffer.h:291
QgsVectorDataProvider::fields
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QgsVectorLayerEditBufferGroup
The edit buffer group manages a group of edit buffers.
Definition: qgsvectorlayereditbuffergroup.h:38
qgsvectorlayerundocommand.h
QgsVectorDataProvider::changeAttributeValues
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
Definition: qgsvectordataprovider.cpp:147
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsVectorLayerEditBuffer::mDeletedAttributeIds
QgsAttributeList mDeletedAttributeIds
Deleted attributes fields which are not committed. The list is kept sorted.
Definition: qgsvectorlayereditbuffer.h:320
QgsVectorLayerEditBuffer::updateAttributeMapIndex
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)
Definition: qgsvectorlayereditbuffer.cpp:552
QgsVectorDataProvider::supportedType
bool supportedType(const QgsField &field) const
check if provider supports type of field
Definition: qgsvectordataprovider.cpp:381
QgsField::typeName
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:139
QgsVectorLayer::isSpatial
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Definition: qgsvectorlayer.cpp:3733
QgsVectorDataProvider::AddAttributes
@ AddAttributes
Allows addition of new attributes (fields)
Definition: qgsvectordataprovider.h:78
QgsVectorDataProvider::doesStrictFeatureTypeCheck
virtual bool doesStrictFeatureTypeCheck() const
Returns true if the provider is strict about the type of inserted features (e.g.
Definition: qgsvectordataprovider.h:503
QgsVectorLayerEditBuffer::addFeature
virtual bool addFeature(QgsFeature &f)
Adds a feature.
Definition: qgsvectorlayereditbuffer.cpp:127
QgsVectorLayerEditBuffer::QgsVectorLayerEditBuffer
QgsVectorLayerEditBuffer()=default
Constructor for QgsVectorLayerEditBuffer.
field
const QgsField & field
Definition: qgsfield.h:463
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsFields::append
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
QgsVectorLayerEditBuffer::layerModified
void layerModified()
Emitted when modifications has been done on layer.
FID_TO_STRING
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:33
QgsVectorLayerEditBuffer::updateChangedAttributes
void updateChangedAttributes(QgsFeature &f)
Update feature with uncommitted attribute updates.
Definition: qgsvectorlayereditbuffer.cpp:100
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandRenameAttribute
friend class QgsVectorLayerUndoCommandRenameAttribute
Definition: qgsvectorlayereditbuffer.h:293
QgsVectorLayerEditBuffer::deleteAttribute
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:293
QgsField::name
QString name
Definition: qgsfield.h:60
QgsVectorLayerEditBuffer::committedAttributesAdded
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
QgsVectorDataProvider::ChangeGeometries
@ ChangeGeometries
Allows modifications of geometries.
Definition: qgsvectordataprovider.h:82
QgsMapLayer::providerType
QString providerType() const
Returns the provider type (provider key) for this layer.
Definition: qgsmaplayer.cpp:1864
QgsVectorLayerEditBuffer::updateLayerFields
void updateLayerFields()
Definition: qgsvectorlayereditbuffer.cpp:565
QgsVectorLayerEditBuffer::changeGeometry
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature's geometry.
Definition: qgsvectorlayereditbuffer.cpp:209
QgsVectorDataProvider::changeFeatures
virtual bool changeFeatures(const QgsChangedAttributesMap &attr_map, const QgsGeometryMap &geometry_map)
Changes attribute values and geometries of existing features.
Definition: qgsvectordataprovider.cpp:185
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsField::precision
int precision
Definition: qgsfield.h:57
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsVectorDataProvider::errors
QStringList errors() const
Gets recorded errors.
Definition: qgsvectordataprovider.cpp:739
QgsVectorDataProvider::capabilities
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
Definition: qgsvectordataprovider.cpp:208
QgsVectorLayerEditBuffer::committedFeaturesAdded
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
QgsVectorLayerEditBuffer::mAddedFeatures
QgsFeatureMap mAddedFeatures
New features which are not committed.
Definition: qgsvectorlayereditbuffer.h:314
QgsVectorLayerEditBuffer::deleteFeature
virtual bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:163
QgsVectorLayerEditBuffer::featureDeleted
void featureDeleted(QgsFeatureId fid)
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsVectorLayerEditBuffer::committedAttributeValuesChanges
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
QgsVectorDataProvider::changeGeometryValues
virtual bool changeGeometryValues(const QgsGeometryMap &geometry_map)
Changes geometries of existing features.
Definition: qgsvectordataprovider.cpp:179
QgsVectorLayerEditBuffer::featureAdded
void featureAdded(QgsFeatureId fid)
QgsVectorLayerEditBuffer::setEditBufferGroup
void setEditBufferGroup(QgsVectorLayerEditBufferGroup *editBufferGroup)
Set the parent edit buffer group for this edit buffer.
Definition: qgsvectorlayereditbuffer.cpp:88
QgsVectorDataProvider::renameAttributes
virtual bool renameAttributes(const QgsFieldNameMap &renamedAttributes)
Renames existing attributes.
Definition: qgsvectordataprovider.cpp:141
QgsFields::fieldOrigin
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Definition: qgsfields.cpp:189
qgsvectordataprovider.h
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
QgsAttributeMap
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QgsVectorLayerEditBuffer::committedFeaturesRemoved
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
qgsvectorlayerutils.h
QgsVectorDataProvider::AddFeatures
@ AddFeatures
Allows adding features.
Definition: qgsvectordataprovider.h:75
QgsVectorLayerEditBuffer::committedAttributesRenamed
void committedAttributesRenamed(const QString &layerId, const QgsFieldNameMap &renamedAttributes)
Emitted after committing an attribute rename.
QgsVectorLayerEditBuffer::rollBack
virtual void rollBack()
Stop editing and discard the edits.
Definition: qgsvectorlayereditbuffer.cpp:434
QgsMapLayer::id
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Definition: qgsmaplayer.cpp:169
QgsVectorLayerEditBuffer::L
QgsVectorLayer * L
Definition: qgsvectorlayereditbuffer.h:284
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:127
QgsVectorLayerEditBuffer::editBufferGroup
QgsVectorLayerEditBufferGroup * editBufferGroup() const
Returns the parent edit buffer group for this edit buffer, or nullptr if not part of a group.
Definition: qgsvectorlayereditbuffer.cpp:83
QgsVectorLayerEditBuffer::renameAttribute
virtual bool renameAttribute(int attr, const QString &newName)
Renames an attribute field (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:315
QgsVectorLayerEditBuffer::undoIndexChanged
void undoIndexChanged(int index)
Definition: qgsvectorlayereditbuffer.cpp:53
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:69
QgsVectorDataProvider::clearErrors
void clearErrors()
Clear recorded errors.
Definition: qgsvectordataprovider.cpp:729
qgsvectorlayer.h
QgsVectorDataProvider::convertToProviderType
QgsGeometry convertToProviderType(const QgsGeometry &geom) const
Converts the geometry to the provider type if possible / necessary.
Definition: qgsvectordataprovider.cpp:776
QgsVectorLayerEditBuffer::committedAttributesDeleted
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
QgsVectorDataProvider::deleteAttributes
virtual bool deleteAttributes(const QgsAttributeIds &attributes)
Deletes existing attributes from the provider.
Definition: qgsvectordataprovider.cpp:135
QgsVectorLayerEditBuffer::mRenamedAttributes
QgsFieldNameMap mRenamedAttributes
Renamed attributes which are not committed.
Definition: qgsvectorlayereditbuffer.h:326
QgsVectorDataProvider::addFeatures
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
Definition: qgsvectordataprovider.cpp:97
QgsVectorLayerEditBuffer::handleAttributeDeleted
void handleAttributeDeleted(int index)
Update added and changed features after removal of an attribute.
Definition: qgsvectorlayereditbuffer.cpp:506
QgsVectorLayerUtils::matchAttributesToFields
static void matchAttributesToFields(QgsFeature &feature, const QgsFields &fields)
Matches the attributes in feature to the specified fields.
Definition: qgsvectorlayerutils.cpp:701
QgsVectorLayerEditBuffer::mEditBufferGroup
QgsVectorLayerEditBufferGroup * mEditBufferGroup
Definition: qgsvectorlayereditbuffer.h:331
qgsgeometry.h
QgsFields::OriginExpression
@ OriginExpression
Field is calculated from an expression.
Definition: qgsfields.h:54
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsVectorDataProvider::ChangeAttributeValues
@ ChangeAttributeValues
Allows modification of attribute values.
Definition: qgsvectordataprovider.h:77
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsVectorLayerEditBuffer::changeAttributeValue
virtual bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changed an attribute value (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:248
QgsVectorLayerEditBuffer::allAddedOrEditedFeatures
QgsFeatureIds allAddedOrEditedFeatures() const
Returns a list of the features IDs for all newly added or edited features in the buffer.
Definition: qgsvectorlayereditbuffer.cpp:450
QgsVectorDataProvider::addAttributes
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes to the provider.
Definition: qgsvectordataprovider.cpp:129
QgsFields::fieldOriginIndex
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Definition: qgsfields.cpp:197
QgsVectorLayerEditBuffer::commitChanges
virtual bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
Definition: qgsvectorlayereditbuffer.cpp:338
QgsVectorDataProvider::ChangeFeatures
@ ChangeFeatures
Supports joint updates for attributes and geometry. Providers supporting this should still define Cha...
Definition: qgsvectordataprovider.h:89
QgsMapLayer::undoStack
QUndoStack * undoStack()
Returns pointer to layer's undo stack.
Definition: qgsmaplayer.cpp:1961
QgsVectorLayer::storageType
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
Definition: qgsvectorlayer.cpp:369
QgsVectorDataProvider::RenameAttributes
@ RenameAttributes
Supports renaming attributes (fields). Since QGIS 2.16.
Definition: qgsvectordataprovider.h:90
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsVectorDataProvider
This is the base class for vector data providers.
Definition: qgsvectordataprovider.h:58
QgsFields::rename
bool rename(int fieldIdx, const QString &name)
Renames a name of field.
Definition: qgsfields.cpp:72
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandChangeGeometry
friend class QgsVectorLayerUndoCommandChangeGeometry
Definition: qgsvectorlayereditbuffer.h:289
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsVectorLayerEditBuffer::mChangedGeometries
QgsGeometryMap mChangedGeometries
Changed geometries which are not committed.
Definition: qgsvectorlayereditbuffer.h:329
QgsDataProvider::name
virtual QString name() const =0
Returns a provider name.
qgslogger.h
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
FID_IS_NEW
#define FID_IS_NEW(fid)
Definition: qgsfeatureid.h:31
QgsVectorLayerEditBuffer::deleteFeatures
virtual bool deleteFeatures(const QgsFeatureIds &fid)
Deletes a set of features from the layer (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:192
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsFields::remove
void remove(int fieldIdx)
Removes the field with the given index.
Definition: qgsfields.cpp:101
QgsVectorLayerEditBuffer::updateFields
void updateFields(QgsFields &fields)
Updates fields.
Definition: qgsvectorlayereditbuffer.cpp:61
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandDeleteFeature
friend class QgsVectorLayerUndoCommandDeleteFeature
Definition: qgsvectorlayereditbuffer.h:288
QgsVectorLayerEditBuffer::changeAttributeValues
virtual bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues)
Changes values of attributes (but does not commit it).
Definition: qgsvectorlayereditbuffer.cpp:230
QgsVectorLayerEditBuffer::updateFeatureGeometry
void updateFeatureGeometry(QgsFeature &f)
Update feature with uncommitted geometry updates.
Definition: qgsvectorlayereditbuffer.cpp:93
QgsVectorLayerEditBuffer::handleAttributeAdded
void handleAttributeAdded(int index)
Update added and changed features after addition of an attribute.
Definition: qgsvectorlayereditbuffer.cpp:472
QgsField::type
QVariant::Type type
Definition: qgsfield.h:58
qgsvectorlayereditbuffer.h
QgsFields::OriginJoin
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:52
QgsVectorLayerEditBuffer::addFeatures
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:146
QgsVectorDataProvider::wkbType
QgsWkbTypes::Type wkbType() const override=0
Returns the geometry type which is returned by this layer.
QgsVectorLayerEditBuffer::mChangedAttributeValues
QgsChangedAttributesMap mChangedAttributeValues
Changed attributes values which are not committed.
Definition: qgsvectorlayereditbuffer.h:317
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
qgsmessagelog.h
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandDeleteAttribute
friend class QgsVectorLayerUndoCommandDeleteAttribute
Definition: qgsvectorlayereditbuffer.h:292
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50