QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 #include "qgsvectorlayerutils.h"
23 #include "qgsmessagelog.h"
24 
25 
27 template <class Key, class T> void mapToReversedLists( const QMap< Key, T > &map, QList<Key> &ks, QList<T> &vs )
28 {
29  ks.reserve( map.size() );
30  vs.reserve( map.size() );
31  typename QMap<Key, T>::const_iterator i = map.constEnd();
32  while ( i-- != map.constBegin() )
33  {
34  ks.append( i.key() );
35  vs.append( i.value() );
36  }
37 }
38 
39 
41  : L( layer )
42 {
43  connect( L->undoStack(), &QUndoStack::indexChanged, this, &QgsVectorLayerEditBuffer::undoIndexChanged ); // TODO[MD]: queued?
44 }
45 
47 {
48  return !L->undoStack()->isClean();
49 }
50 
51 
53 {
54  QgsDebugMsgLevel( QStringLiteral( "undo index changed %1" ).arg( index ), 4 );
55  Q_UNUSED( index )
56  emit layerModified();
57 }
58 
59 
61 {
62  // delete attributes from the higher indices to lower indices
63  for ( int i = mDeletedAttributeIds.count() - 1; i >= 0; --i )
64  {
65  fields.remove( mDeletedAttributeIds.at( i ) );
66  }
67 
68  // rename fields
69  QgsFieldNameMap::const_iterator renameIt = mRenamedAttributes.constBegin();
70  for ( ; renameIt != mRenamedAttributes.constEnd(); ++renameIt )
71  {
72  fields.rename( renameIt.key(), renameIt.value() );
73  }
74 
75  // add new fields
76  for ( int i = 0; i < mAddedAttributes.count(); ++i )
77  {
78  fields.append( mAddedAttributes.at( i ), QgsFields::OriginEdit, i );
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  {
125  QgsMessageLog::logMessage( tr( "cannot add feature, wrong field count: layer: %1 feature: %2:" ).arg( L->mFields.count() ).arg( f.attributes().count() ) );
126  return false;
127  }
128 
129  // TODO: check correct geometry type
130 
131  L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) );
132  return true;
133 }
134 
135 
137 {
139  return false;
140 
141  bool result = true;
142  for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
143  {
144  result = result && addFeature( *iter );
145  }
146 
147  L->updateExtents();
148  return result;
149 }
150 
151 
152 
154 {
156  {
157  QgsDebugMsg( QStringLiteral( "Cannot delete features (missing DeleteFeature capability)" ) );
158  return false;
159  }
160 
161  if ( FID_IS_NEW( fid ) )
162  {
163  if ( !mAddedFeatures.contains( fid ) )
164  {
165  QgsDebugMsg( QStringLiteral( "Cannot delete features (in the list of added features)" ) );
166  return false;
167  }
168  }
169  else // existing feature
170  {
171  if ( mDeletedFeatureIds.contains( fid ) )
172  {
173  QgsDebugMsg( QStringLiteral( "Cannot delete features (in the list of deleted features)" ) );
174  return false;
175  }
176  }
177 
178  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteFeature( this, fid ) );
179  return true;
180 }
181 
183 {
185  {
186  QgsDebugMsg( QStringLiteral( "Cannot delete features (missing DeleteFeatures capability)" ) );
187  return false;
188  }
189 
190  bool ok = true;
191  const auto constFids = fids;
192  for ( QgsFeatureId fid : constFids )
193  ok = deleteFeature( fid ) && ok;
194 
195  return ok;
196 }
197 
198 
200 {
201  if ( !L->isSpatial() )
202  {
203  return false;
204  }
205 
206  if ( FID_IS_NEW( fid ) )
207  {
208  if ( !mAddedFeatures.contains( fid ) )
209  return false;
210  }
212  return false;
213 
214  // TODO: check compatible geometry
215 
216  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeGeometry( this, fid, geom ) );
217  return true;
218 }
219 
221 {
222  bool success = true;
223  for ( auto it = newValues.constBegin() ; it != newValues.constEnd(); ++it )
224  {
225  const int field = it.key();
226  const QVariant newValue = it.value();
227  QVariant oldValue;
228 
229  if ( oldValues.contains( field ) )
230  oldValue = oldValues[field];
231 
232  success &= changeAttributeValue( fid, field, newValue, oldValue );
233  }
234 
235  return success;
236 }
237 
238 bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
239 {
240  if ( FID_IS_NEW( fid ) )
241  {
242  if ( !mAddedFeatures.contains( fid ) )
243  return false;
244  }
246  {
247  return false;
248  }
249 
250  if ( field < 0 || field >= L->fields().count() ||
253  return false;
254 
255  L->undoStack()->push( new QgsVectorLayerUndoCommandChangeAttribute( this, fid, field, newValue, oldValue ) );
256  return true;
257 }
258 
259 
261 {
263  return false;
264 
265  if ( field.name().isEmpty() )
266  return false;
267 
268  const QgsFields fields = L->fields();
269  for ( const QgsField &updatedField : fields )
270  {
271  if ( updatedField.name() == field.name() )
272  return false;
273  }
274 
275  if ( !L->dataProvider()->supportedType( field ) )
276  return false;
277 
278  L->undoStack()->push( new QgsVectorLayerUndoCommandAddAttribute( this, field ) );
279  return true;
280 }
281 
282 
284 {
286  return false;
287 
288  if ( index < 0 || index >= L->fields().count() )
289  return false;
290 
291  // find out source of the field
292  QgsFields::FieldOrigin origin = L->fields().fieldOrigin( index );
293  int originIndex = L->fields().fieldOriginIndex( index );
294 
295  if ( origin == QgsFields::OriginProvider && mDeletedAttributeIds.contains( originIndex ) )
296  return false;
297 
298  if ( origin == QgsFields::OriginJoin )
299  return false;
300 
301  L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteAttribute( this, index ) );
302  return true;
303 }
304 
305 bool QgsVectorLayerEditBuffer::renameAttribute( int index, const QString &newName )
306 {
308  return false;
309 
310  if ( newName.isEmpty() )
311  return false;
312 
313  if ( index < 0 || index >= L->fields().count() )
314  return false;
315 
316  const QgsFields fields = L->fields();
317  for ( const QgsField &updatedField : fields )
318  {
319  if ( updatedField.name() == newName )
320  return false;
321  }
322 
323  L->undoStack()->push( new QgsVectorLayerUndoCommandRenameAttribute( this, index, newName ) );
324  return true;
325 }
326 
327 
328 bool QgsVectorLayerEditBuffer::commitChanges( QStringList &commitErrors )
329 {
330  QgsVectorDataProvider *provider = L->dataProvider();
331  commitErrors.clear();
332 
333  int cap = provider->capabilities();
334  bool success = true;
335 
336  // geometry updates attribute updates
337  // yes no => changeGeometryValues
338  // no yes => changeAttributeValues
339  // yes yes => changeFeatures
340 
341  // to fix https://github.com/qgis/QGIS/issues/23663
342  // first of all check if feature to add is compatible with provider type
343  // this check have to be done before all checks to avoid to clear internal
344  // buffer if some of next steps success.
345  if ( success && !mAddedFeatures.isEmpty() )
346  {
348  {
349  if ( provider->doesStrictFeatureTypeCheck() )
350  {
351  for ( const QgsFeature &f : qgis::as_const( mAddedFeatures ) )
352  {
353  if ( ( ! f.hasGeometry() ) ||
354  ( f.geometry().wkbType() == provider->wkbType() ) )
355  continue;
356 
357  if ( provider->convertToProviderType( f.geometry() ).isNull() )
358  {
359  commitErrors << tr( "ERROR: %n feature(s) not added - geometry type is not compatible with the current layer.", "not added features count", mAddedFeatures.size() );
360  success = false;
361  break;
362  }
363  }
364  }
365  }
366  else
367  {
368  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
369  success = false;
370  }
371  }
372 
373  //
374  // update geometries
375  //
376  if ( !mChangedGeometries.isEmpty() && ( ( cap & QgsVectorDataProvider::ChangeFeatures ) == 0 || mChangedAttributeValues.isEmpty() ) )
377  {
378  if ( provider->changeGeometryValues( mChangedGeometries ) )
379  {
380  commitErrors << tr( "SUCCESS: %n geometries were changed.", "changed geometries count", mChangedGeometries.size() );
381 
383  mChangedGeometries.clear();
384  }
385  else
386  {
387  commitErrors << tr( "ERROR: %n geometries not changed.", "not changed geometries count", mChangedGeometries.size() );
388  success = false;
389  }
390  }
391 
392  QgsFields oldFields = L->fields();
393 
394  //
395  // delete attributes
396  //
397  bool attributesChanged = false;
398  if ( !mDeletedAttributeIds.isEmpty() )
399  {
400  if ( ( cap & QgsVectorDataProvider::DeleteAttributes ) && provider->deleteAttributes( qgis::listToSet( mDeletedAttributeIds ) ) )
401  {
402  commitErrors << tr( "SUCCESS: %n attribute(s) deleted.", "deleted attributes count", mDeletedAttributeIds.size() );
403 
405 
406  mDeletedAttributeIds.clear();
407  attributesChanged = true;
408  }
409  else
410  {
411  commitErrors << tr( "ERROR: %n attribute(s) not deleted.", "not deleted attributes count", mDeletedAttributeIds.size() );
412 #if 0
413  QString list = "ERROR: Pending attribute deletes:";
414  const auto constMDeletedAttributeIds = mDeletedAttributeIds;
415  for ( int idx : constMDeletedAttributeIds )
416  {
417  list.append( ' ' + L->fields().at( idx ).name() );
418  }
419  commitErrors << list;
420 #endif
421  success = false;
422  }
423  }
424 
425  // rename attributes
426  if ( !mRenamedAttributes.isEmpty() )
427  {
429  {
430  commitErrors << tr( "SUCCESS: %n attribute(s) renamed.", "renamed attributes count", mRenamedAttributes.size() );
431 
433 
434  mRenamedAttributes.clear();
435  attributesChanged = true;
436  }
437  else
438  {
439  commitErrors << tr( "ERROR: %n attribute(s) not renamed", "not renamed attributes count", mRenamedAttributes.size() );
440  success = false;
441  }
442  }
443 
444  //
445  // add attributes
446  //
447  if ( !mAddedAttributes.isEmpty() )
448  {
450  {
451  commitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributes.size() );
452 
454 
455  mAddedAttributes.clear();
456  attributesChanged = true;
457  }
458  else
459  {
460  commitErrors << tr( "ERROR: %n new attribute(s) not added", "not added attributes count", mAddedAttributes.size() );
461 #if 0
462  QString list = "ERROR: Pending adds:";
463  const auto constMAddedAttributes = mAddedAttributes;
464  for ( QgsField f : constMAddedAttributes )
465  {
466  list.append( ' ' + f.name() );
467  }
468  commitErrors << list;
469 #endif
470  success = false;
471  }
472  }
473 
474  //
475  // check that addition/removal went as expected
476  //
477  bool attributeChangesOk = true;
478  if ( attributesChanged )
479  {
480  L->updateFields();
481  QgsFields newFields = L->fields();
482 
483  if ( oldFields.count() != newFields.count() )
484  {
485  commitErrors << tr( "ERROR: the count of fields is incorrect after addition/removal of fields!" );
486  attributeChangesOk = false; // don't try attribute updates - they'll fail.
487  }
488 
489  for ( int i = 0; i < std::min( oldFields.count(), newFields.count() ); ++i )
490  {
491  QgsField oldField = oldFields.at( i );
492  QgsField newField = newFields.at( i );
493  if ( attributeChangesOk && oldField != newField )
494  {
495  commitErrors
496  << tr( "ERROR: field with index %1 is not the same!" ).arg( i )
497  << tr( "Provider: %1" ).arg( L->providerType() )
498  << tr( "Storage: %1" ).arg( L->storageType() )
499  << QStringLiteral( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
500  .arg( tr( "expected field" ),
501  oldField.name(),
502  QVariant::typeToName( oldField.type() ),
503  oldField.typeName() )
504  .arg( oldField.length() )
505  .arg( oldField.precision() )
506  << QStringLiteral( "%1: name=%2 type=%3 typeName=%4 len=%5 precision=%6" )
507  .arg( tr( "retrieved field" ),
508  newField.name(),
509  QVariant::typeToName( newField.type() ),
510  newField.typeName() )
511  .arg( newField.length() )
512  .arg( newField.precision() );
513  attributeChangesOk = false; // don't try attribute updates - they'll fail.
514  }
515  }
516  }
517 
518  if ( attributeChangesOk )
519  {
521  {
523 
525  {
526  commitErrors << tr( "SUCCESS: %1 attribute value(s) and %2 geometries changed." ).arg( mChangedAttributeValues.size(), mChangedGeometries.size() );
528  mChangedAttributeValues.clear();
529 
531  mChangedGeometries.clear();
532  }
533  else
534  {
535  success = false;
536  }
537  }
538  else
539  {
540  //
541  // change attributes
542  //
543  if ( !mChangedAttributeValues.isEmpty() && ( ( cap & QgsVectorDataProvider::ChangeFeatures ) == 0 || mChangedGeometries.isEmpty() ) )
544  {
546  {
547  commitErrors << tr( "SUCCESS: %n attribute value(s) changed.", "changed attribute values count", mChangedAttributeValues.size() );
548 
550  mChangedAttributeValues.clear();
551  }
552  else
553  {
554  commitErrors << tr( "ERROR: %n attribute value change(s) not applied.", "not changed attribute values count", mChangedAttributeValues.size() );
555 #if 0
556  QString list = "ERROR: pending changes:";
557  const auto constKeys = mChangedAttributeValues.keys();
558  for ( QgsFeatureId id : constKeys )
559  {
560  list.append( "\n " + FID_TO_STRING( id ) + '[' );
561  const auto constKeys = mChangedAttributeValues[ id ].keys();
562  for ( int idx : constKeys )
563  {
564  list.append( QString( " %1:%2" ).arg( L->fields().at( idx ).name() ).arg( mChangedAttributeValues[id][idx].toString() ) );
565  }
566  list.append( " ]" );
567  }
568  commitErrors << list;
569 #endif
570  success = false;
571  }
572  }
573  }
574 
575  //
576  // delete features
577  //
578  if ( success && !mDeletedFeatureIds.isEmpty() )
579  {
581  {
582  commitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
583  // TODO[MD]: we should not need this here
584  for ( QgsFeatureId id : qgis::as_const( mDeletedFeatureIds ) )
585  {
586  mChangedAttributeValues.remove( id );
587  mChangedGeometries.remove( id );
588  }
589 
591 
592  mDeletedFeatureIds.clear();
593  }
594  else
595  {
596  commitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
597 #if 0
598  QString list = "ERROR: pending deletes:";
599  const auto constMDeletedFeatureIds = mDeletedFeatureIds;
600  for ( QgsFeatureId id : constMDeletedFeatureIds )
601  {
602  list.append( ' ' + FID_TO_STRING( id ) );
603  }
604  commitErrors << list;
605 #endif
606  success = false;
607  }
608  }
609 
610  //
611  // add features
612  //
613  if ( success && !mAddedFeatures.isEmpty() )
614  {
616  {
617  QList<QgsFeatureId> ids;
618  QgsFeatureList featuresToAdd;
619  // get the list of added features in reversed order
620  // 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)
621  mapToReversedLists( mAddedFeatures, ids, featuresToAdd );
622 
623  // we need to strip any extra attributes here -- e.g. virtual fields, which should
624  // not be sent to the data provider. Refs #18784
625  for ( int i = 0; i < featuresToAdd.count(); ++i )
626  {
627  QgsVectorLayerUtils::matchAttributesToFields( featuresToAdd[i], provider->fields() );
628  }
629 
630  if ( provider->addFeatures( featuresToAdd, QgsFeatureSink::Flag::RollBackOnErrors ) )
631  {
632  commitErrors << tr( "SUCCESS: %n feature(s) added.", "added features count", featuresToAdd.size() );
633 
634  emit committedFeaturesAdded( L->id(), featuresToAdd );
635 
636  // notify everyone that the features with temporary ids were updated with permanent ids
637  for ( int i = 0; i < featuresToAdd.count(); ++i )
638  {
639  if ( featuresToAdd[i].id() != ids[i] )
640  {
641  //update selection
642  if ( L->mSelectedFeatureIds.contains( ids[i] ) )
643  {
644  L->mSelectedFeatureIds.remove( ids[i] );
645  L->mSelectedFeatureIds.insert( featuresToAdd[i].id() );
646  }
647  emit featureDeleted( ids[i] );
648  emit featureAdded( featuresToAdd[i].id() );
649  }
650  }
651 
652  mAddedFeatures.clear();
653  }
654  else
655  {
656  commitErrors << tr( "ERROR: %n feature(s) not added.", "not added features count", mAddedFeatures.size() );
657 #if 0
658  QString list = "ERROR: pending adds:";
659  const auto constMAddedFeatures = mAddedFeatures;
660  for ( QgsFeature f : constMAddedFeatures )
661  {
662  list.append( ' ' + FID_TO_STRING( f.id() ) + '[' );
663  for ( int i = 0; i < L->fields().size(); i++ )
664  {
665  list.append( QString( " %1:%2" ).arg( L->fields().at( i ).name() ).arg( f.attributes()[i].toString() ) );
666  }
667  list.append( " ]" );
668  }
669  commitErrors << list;
670 #endif
671  success = false;
672  }
673  }
674  else
675  {
676  commitErrors << tr( "ERROR: %n feature(s) not added - provider doesn't support adding features.", "not added features count", mAddedFeatures.size() );
677  success = false;
678  }
679  }
680  }
681  else
682  {
683  success = false;
684  }
685 
686  if ( !success && provider->hasErrors() )
687  {
688  commitErrors << tr( "\n Provider errors:" );
689  const auto constErrors = provider->errors();
690  for ( QString e : constErrors )
691  {
692  commitErrors << " " + e.replace( '\n', QLatin1String( "\n " ) );
693  }
694  provider->clearErrors();
695  }
696 
697  return success;
698 }
699 
700 
702 {
703  if ( !isModified() )
704  return;
705 
706  // limit canvas redraws to one by jumping to beginning of stack
707  // see QgsUndoWidget::indexChanged
708  L->undoStack()->setIndex( 0 );
709 
710  Q_ASSERT( mAddedAttributes.isEmpty() );
711  Q_ASSERT( mDeletedAttributeIds.isEmpty() );
712  Q_ASSERT( mChangedAttributeValues.isEmpty() );
713  Q_ASSERT( mChangedGeometries.isEmpty() );
714  Q_ASSERT( mAddedFeatures.isEmpty() );
715 }
716 
717 #if 0
718 QString QgsVectorLayerEditBuffer::dumpEditBuffer()
719 {
720  QString msg;
721  if ( !mChangedGeometries.isEmpty() )
722  {
723  msg += "CHANGED GEOMETRIES:\n";
724  for ( QgsGeometryMap::const_iterator it = mChangedGeometries.begin(); it != mChangedGeometries.end(); ++it )
725  {
726  // QgsFeatureId, QgsGeometry
727  msg += QString( "- FID %1: %2" ).arg( it.key() ).arg( it.value().to );
728  }
729  }
730  return msg;
731 }
732 #endif
733 
735 {
736  // go through the changed attributes map and adapt indices
737  QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
738  for ( ; it != mChangedAttributeValues.end(); ++it )
739  {
740  updateAttributeMapIndex( it.value(), index, + 1 );
741  }
742 
743  // go through added features and adapt attributes
744  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
745  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
746  {
747  QgsAttributes attrs = featureIt->attributes();
748  attrs.insert( index, QVariant() );
749  featureIt->setAttributes( attrs );
750  }
751 
752  // go through renamed attributes and adapt
753  QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
754  //sort keys
755  std::sort( sortedRenamedIndices.begin(), sortedRenamedIndices.end(), std::greater< int >() );
756  const auto constSortedRenamedIndices = sortedRenamedIndices;
757  for ( int renameIndex : constSortedRenamedIndices )
758  {
759  if ( renameIndex >= index )
760  {
761  mRenamedAttributes[ renameIndex + 1 ] = mRenamedAttributes.value( renameIndex );
762  }
763  }
764  //remove last
765  mRenamedAttributes.remove( index );
766 }
767 
769 {
770  // go through the changed attributes map and adapt indices
771  QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
772  for ( ; it != mChangedAttributeValues.end(); ++it )
773  {
774  QgsAttributeMap &attrMap = it.value();
775  // remove the attribute
776  if ( attrMap.contains( index ) )
777  attrMap.remove( index );
778 
779  // update attribute indices
780  updateAttributeMapIndex( attrMap, index, -1 );
781  }
782 
783  // go through added features and adapt attributes
784  QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
785  for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
786  {
787  QgsAttributes attrs = featureIt->attributes();
788  attrs.remove( index );
789  featureIt->setAttributes( attrs );
790  }
791 
792  // go through rename attributes and adapt
793  QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
794  //sort keys
795  std::sort( sortedRenamedIndices.begin(), sortedRenamedIndices.end() );
796  int last = -1;
797  mRenamedAttributes.remove( index );
798  const auto constSortedRenamedIndices = sortedRenamedIndices;
799  for ( int renameIndex : constSortedRenamedIndices )
800  {
801  if ( renameIndex > index )
802  {
803  mRenamedAttributes.insert( renameIndex - 1, mRenamedAttributes.value( renameIndex ) );
804  last = renameIndex;
805  }
806  }
807  //remove last
808  if ( last > -1 )
809  mRenamedAttributes.remove( last );
810 }
811 
812 
813 
815 {
816  QgsAttributeMap updatedMap;
817  for ( QgsAttributeMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
818  {
819  int attrIndex = it.key();
820  updatedMap.insert( attrIndex < index ? attrIndex : attrIndex + offset, it.value() );
821  }
822  map = updatedMap;
823 }
824 
825 
826 
828 {
829  L->updateFields();
830 }
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:27
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:49
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:266
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:299
QgsFeature::id
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QgsVectorDataProvider::deleteFeatures
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features from the provider.
Definition: qgsvectordataprovider.cpp:99
QgsVectorDataProvider::hasErrors
bool hasErrors() const
Provider has errors to report.
Definition: qgsvectordataprovider.cpp:720
QgsVectorLayer::updateExtents
virtual void updateExtents(bool force=false)
Update the extents for the layer.
Definition: qgsvectorlayer.cpp:801
QgsVectorLayerEditBuffer::isModified
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
Definition: qgsvectorlayereditbuffer.cpp:46
QgsVectorLayer::updateFields
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
Definition: qgsvectorlayer.cpp:3771
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandAddFeature
friend class QgsVectorLayerUndoCommandAddFeature
Definition: qgsvectorlayereditbuffer.h:263
QgsVectorDataProvider::DeleteAttributes
@ DeleteAttributes
Allows deletion of attributes (fields)
Definition: qgsvectordataprovider.h:79
QgsField::length
int length
Definition: qgsfield.h:55
QgsVectorLayerEditBuffer::mDeletedFeatureIds
QgsFeatureIds mDeletedFeatureIds
Deleted feature IDs which are not committed.
Definition: qgsvectorlayereditbuffer.h:287
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsVectorLayerEditBuffer::addAttribute
virtual bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
Definition: qgsvectorlayereditbuffer.cpp:260
QgsVectorLayerEditBuffer::committedGeometriesChanges
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandAddAttribute
friend class QgsVectorLayerUndoCommandAddAttribute
Definition: qgsvectorlayereditbuffer.h:267
QgsVectorDataProvider::fields
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
qgsvectorlayerundocommand.h
QgsVectorDataProvider::changeAttributeValues
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
Definition: qgsvectordataprovider.cpp:137
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsVectorLayerEditBuffer::mDeletedAttributeIds
QgsAttributeList mDeletedAttributeIds
Deleted attributes fields which are not committed. The list is kept sorted.
Definition: qgsvectorlayereditbuffer.h:296
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:814
QgsVectorDataProvider::supportedType
bool supportedType(const QgsField &field) const
check if provider supports type of field
Definition: qgsvectordataprovider.cpp:366
QgsField::typeName
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:138
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:3599
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:493
QgsVectorLayerEditBuffer::addFeature
virtual bool addFeature(QgsFeature &f)
Adds a feature.
Definition: qgsvectorlayereditbuffer.cpp:117
QgsVectorLayerEditBuffer::QgsVectorLayerEditBuffer
QgsVectorLayerEditBuffer()=default
Constructor for QgsVectorLayerEditBuffer.
field
const QgsField & field
Definition: qgsfield.h:456
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:90
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandRenameAttribute
friend class QgsVectorLayerUndoCommandRenameAttribute
Definition: qgsvectorlayereditbuffer.h:269
QgsVectorLayerEditBuffer::deleteAttribute
virtual bool deleteAttribute(int attr)
Delete an attribute field (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:283
QgsField::name
QString name
Definition: qgsfield.h:59
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:1617
QgsVectorLayerEditBuffer::updateLayerFields
void updateLayerFields()
Definition: qgsvectorlayereditbuffer.cpp:827
QgsVectorLayerEditBuffer::changeGeometry
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature's geometry.
Definition: qgsvectorlayereditbuffer.cpp:199
QgsVectorDataProvider::changeFeatures
virtual bool changeFeatures(const QgsChangedAttributesMap &attr_map, const QgsGeometryMap &geometry_map)
Changes attribute values and geometries of existing features.
Definition: qgsvectordataprovider.cpp:175
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
QgsField::precision
int precision
Definition: qgsfield.h:56
QgsVectorDataProvider::errors
QStringList errors() const
Gets recorded errors.
Definition: qgsvectordataprovider.cpp:725
QgsVectorDataProvider::capabilities
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
Definition: qgsvectordataprovider.cpp:198
QgsVectorLayerEditBuffer::committedFeaturesAdded
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
QgsVectorLayerEditBuffer::mAddedFeatures
QgsFeatureMap mAddedFeatures
New features which are not committed.
Definition: qgsvectorlayereditbuffer.h:290
QgsVectorLayerEditBuffer::deleteFeature
virtual bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:153
QgsVectorLayerEditBuffer::featureDeleted
void featureDeleted(QgsFeatureId fid)
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:139
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:169
QgsVectorLayerEditBuffer::featureAdded
void featureAdded(QgsFeatureId fid)
QgsVectorDataProvider::renameAttributes
virtual bool renameAttributes(const QgsFieldNameMap &renamedAttributes)
Renames existing attributes.
Definition: qgsvectordataprovider.cpp:131
QgsFields::fieldOrigin
FieldOrigin fieldOrigin(int fieldIdx) const
Gets field's origin (value from an enumeration)
Definition: qgsfields.cpp:189
qgsvectordataprovider.h
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:583
QgsAttributeMap
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QgsVectorLayerEditBuffer::committedFeaturesRemoved
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
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:701
QgsMapLayer::id
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Definition: qgsmaplayer.cpp:148
QgsVectorLayerEditBuffer::L
QgsVectorLayer * L
Definition: qgsvectorlayereditbuffer.h:259
QgsVectorLayerEditBuffer::renameAttribute
virtual bool renameAttribute(int attr, const QString &newName)
Renames an attribute field (but does not commit it)
Definition: qgsvectorlayereditbuffer.cpp:305
QgsVectorLayerEditBuffer::undoIndexChanged
void undoIndexChanged(int index)
Definition: qgsvectorlayereditbuffer.cpp:52
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsVectorDataProvider::clearErrors
void clearErrors()
Clear recorded errors.
Definition: qgsvectordataprovider.cpp:715
qgsvectorlayer.h
QgsVectorDataProvider::convertToProviderType
QgsGeometry convertToProviderType(const QgsGeometry &geom) const
Converts the geometry to the provider type if possible / necessary.
Definition: qgsvectordataprovider.cpp:762
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:125
QgsVectorLayerEditBuffer::mRenamedAttributes
QgsFieldNameMap mRenamedAttributes
Renamed attributes which are not committed.
Definition: qgsvectorlayereditbuffer.h:302
QgsVectorDataProvider::addFeatures
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
Definition: qgsvectordataprovider.cpp:87
QgsVectorLayerEditBuffer::handleAttributeDeleted
void handleAttributeDeleted(int index)
Update added and changed features after removal of an attribute.
Definition: qgsvectorlayereditbuffer.cpp:768
QgsVectorLayerUtils::matchAttributesToFields
static void matchAttributesToFields(QgsFeature &feature, const QgsFields &fields)
Matches the attributes in feature to the specified fields.
Definition: qgsvectorlayerutils.cpp:699
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:387
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:238
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:627
QgsVectorDataProvider::addAttributes
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes to the provider.
Definition: qgsvectordataprovider.cpp:119
QgsFields::fieldOriginIndex
int fieldOriginIndex(int fieldIdx) const
Gets 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:328
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:1693
QgsVectorLayer::storageType
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
Definition: qgsvectorlayer.cpp:340
QgsVectorDataProvider::RenameAttributes
@ RenameAttributes
Supports renaming attributes (fields). Since QGIS 2.16.
Definition: qgsvectordataprovider.h:90
QgsAttributes
A vector of attributes.
Definition: qgsattributes.h:58
QgsVectorDataProvider
This is the base class for vector data providers.
Definition: qgsvectordataprovider.h:59
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:265
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsVectorLayerEditBuffer::mChangedGeometries
QgsGeometryMap mChangedGeometries
Changed geometries which are not committed.
Definition: qgsvectorlayereditbuffer.h:305
qgslogger.h
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:129
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:182
QgsFields::at
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsFields::remove
void remove(int fieldIdx)
Removes a field with the given index.
Definition: qgsfields.cpp:101
QgsVectorLayerEditBuffer::updateFields
void updateFields(QgsFields &fields)
Definition: qgsvectorlayereditbuffer.cpp:60
QgsVectorLayerEditBuffer::QgsVectorLayerUndoCommandDeleteFeature
friend class QgsVectorLayerUndoCommandDeleteFeature
Definition: qgsvectorlayereditbuffer.h:264
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:220
QgsVectorLayerEditBuffer::updateFeatureGeometry
void updateFeatureGeometry(QgsFeature &f)
Update feature with uncommitted geometry updates.
Definition: qgsvectorlayereditbuffer.cpp:83
QgsVectorLayerEditBuffer::handleAttributeAdded
void handleAttributeAdded(int index)
Update added and changed features after addition of an attribute.
Definition: qgsvectorlayereditbuffer.cpp:734
QgsField::type
QVariant::Type type
Definition: qgsfield.h:57
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:136
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:293
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:268
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50