QGIS API Documentation  2.9.0-Master
qgsattributetablemodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  QgsAttributeTableModel.cpp
3  --------------------------------------
4  Date : Feb 2009
5  Copyright : (C) 2009 Vita Cizek
6  Email : weetya (at) gmail.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  ***************************************************************************/
15 
16 #include "qgsapplication.h"
17 #include "qgsattributetablemodel.h"
19 
20 #include "qgsattributeaction.h"
22 #include "qgsexpression.h"
23 #include "qgsfield.h"
24 #include "qgslogger.h"
25 #include "qgsmapcanvas.h"
27 #include "qgsmaplayerregistry.h"
28 #include "qgsrendererv2.h"
29 #include "qgsvectorlayer.h"
30 
31 #include <QVariant>
32 
33 #include <limits>
34 
36  : QAbstractTableModel( parent )
37  , mLayerCache( layerCache )
38  , mFieldCount( 0 )
39  , mCachedField( -1 )
40 {
41  QgsDebugMsg( "entered." );
42 
43  if ( layerCache->layer()->geometryType() == QGis::NoGeometry )
44  {
45  mFeatureRequest.setFlags( QgsFeatureRequest::NoGeometry );
46  }
47 
49 
50  if ( !layer()->hasGeometryType() )
51  mFeatureRequest.setFlags( QgsFeatureRequest::NoGeometry );
52 
54 
55  connect( mLayerCache, SIGNAL( attributeValueChanged( QgsFeatureId, int, const QVariant& ) ), this, SLOT( attributeValueChanged( QgsFeatureId, int, const QVariant& ) ) );
56  connect( layer(), SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( featureDeleted( QgsFeatureId ) ) );
57  connect( layer(), SIGNAL( attributeDeleted( int ) ), this, SLOT( attributeDeleted( int ) ) );
58  connect( layer(), SIGNAL( updatedFields() ), this, SLOT( updatedFields() ) );
59  connect( layer(), SIGNAL( editCommandEnded() ), this, SLOT( editCommandEnded() ) );
60  connect( mLayerCache, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( featureAdded( QgsFeatureId ) ) );
61  connect( mLayerCache, SIGNAL( cachedLayerDeleted() ), this, SLOT( layerDeleted() ) );
62 }
63 
64 bool QgsAttributeTableModel::loadFeatureAtId( QgsFeatureId fid ) const
65 {
66  QgsDebugMsgLevel( QString( "loading feature %1" ).arg( fid ), 3 );
67 
68  if ( fid == std::numeric_limits<int>::min() )
69  {
70  return false;
71  }
72 
73  return mLayerCache->featureAtId( fid, mFeat );
74 }
75 
77 {
78  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
79  mFieldCache.remove( fid );
80 
81  int row = idToRow( fid );
82 
83  if ( row != -1 )
84  {
85  beginRemoveRows( QModelIndex(), row, row );
86  removeRow( row );
87  endRemoveRows();
88  }
89 }
90 
91 bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &parent )
92 {
93  Q_UNUSED( parent );
94  QgsDebugMsgLevel( QString( "remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
95 
96  // clean old references
97  for ( int i = row; i < row + count; i++ )
98  {
99  mIdRowMap.remove( mRowIdMap[ i ] );
100  mRowIdMap.remove( i );
101  }
102 
103  // update maps
104  int n = mRowIdMap.size() + count;
105  for ( int i = row + count; i < n; i++ )
106  {
107  QgsFeatureId id = mRowIdMap[i];
108  mIdRowMap[ id ] -= count;
109  mRowIdMap[ i-count ] = id;
110  mRowIdMap.remove( i );
111  }
112 
113 #ifdef QGISDEBUG
114  QgsDebugMsgLevel( QString( "after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
115  QgsDebugMsgLevel( "id->row", 4 );
116  for ( QHash<QgsFeatureId, int>::iterator it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
117  QgsDebugMsgLevel( QString( "%1->%2" ).arg( FID_TO_STRING( it.key() ) ).arg( *it ), 4 );
118 
119  QHash<QgsFeatureId, int>::iterator idit;
120 
121  QgsDebugMsgLevel( "row->id", 4 );
122  for ( QHash<int, QgsFeatureId>::iterator it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
123  QgsDebugMsgLevel( QString( "%1->%2" ).arg( it.key() ).arg( FID_TO_STRING( *it ) ), 4 );
124 #endif
125 
126  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
127 
128  return true;
129 }
130 
132 {
133  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
134  bool featOk = true;
135 
136  if ( mFeat.id() != fid )
137  featOk = loadFeatureAtId( fid );
138 
139  if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
140  {
141  mFieldCache[ fid ] = mFeat.attribute( mCachedField );
142 
143  int n = mRowIdMap.size();
144  beginInsertRows( QModelIndex(), n, n );
145 
146  mIdRowMap.insert( fid, n );
147  mRowIdMap.insert( n, fid );
148 
149  endInsertRows();
150 
151  reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
152  }
153 }
154 
155 void QgsAttributeTableModel::updatedFields()
156 {
157  QgsDebugMsg( "entered." );
158  loadAttributes();
159  emit modelChanged();
160 }
161 
162 void QgsAttributeTableModel::editCommandEnded()
163 {
164  reload( createIndex( mChangedCellBounds.top(), mChangedCellBounds.left() ),
165  createIndex( mChangedCellBounds.bottom(), mChangedCellBounds.right() ) );
166 
167  mChangedCellBounds = QRect();
168 }
169 
170 void QgsAttributeTableModel::attributeDeleted( int idx )
171 {
172  if ( idx == mCachedField )
173  {
174  prefetchColumnData( -1 );
175  }
176 }
177 
179 {
180  QgsDebugMsg( "entered." );
181 
182  beginRemoveRows( QModelIndex(), 0, rowCount() - 1 );
183  removeRows( 0, rowCount() );
184  endRemoveRows();
185 
186  mAttributeWidgetCaches.clear();
187  mAttributes.clear();
188  mWidgetFactories.clear();
189  mWidgetConfigs.clear();
190 }
191 
192 void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
193 {
194  QgsDebugMsgLevel( QString( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 3 );
195 
196  if ( idx == mCachedField )
197  mFieldCache[ fid ] = value;
198 
199  // No filter request: skip all possibly heavy checks
200  if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
201  {
202  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
203  }
204  else
205  {
206  if ( loadFeatureAtId( fid ) )
207  {
208  if ( mFeatureRequest.acceptFeature( mFeat ) )
209  {
210  if ( !mIdRowMap.contains( fid ) )
211  {
212  // Feature changed in such a way, it will be shown now
213  featureAdded( fid );
214  }
215  else
216  {
217  // Update representation
218  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
219  }
220  }
221  else
222  {
223  if ( mIdRowMap.contains( fid ) )
224  {
225  // Feature changed such, that it is no longer shown
226  featureDeleted( fid );
227  }
228  // else: we don't care
229  }
230  }
231  }
232 }
233 
235 {
236  if ( !layer() )
237  {
238  return;
239  }
240 
241  bool ins = false, rm = false;
242 
243  QgsAttributeList attributes;
244  const QgsFields& fields = layer()->pendingFields();
245 
246  mWidgetFactories.clear();
247  mAttributeWidgetCaches.clear();
248  mWidgetConfigs.clear();
249 
250  for ( int idx = 0; idx < fields.count(); ++idx )
251  {
252  const QString widgetType = layer()->editorWidgetV2( idx );
253  QgsEditorWidgetFactory* widgetFactory = QgsEditorWidgetRegistry::instance()->factory( widgetType );
254  if ( widgetFactory && widgetType != "Hidden" )
255  {
256  mWidgetFactories.append( widgetFactory );
257  mWidgetConfigs.append( layer()->editorWidgetV2Config( idx ) );
258  mAttributeWidgetCaches.append( widgetFactory->createCache( layer(), idx, mWidgetConfigs.last() ) );
259 
260  attributes << idx;
261  }
262  }
263 
264  if ( mFieldCount < attributes.size() )
265  {
266  ins = true;
267  beginInsertColumns( QModelIndex(), mFieldCount, attributes.size() - 1 );
268  }
269  else if ( attributes.size() < mFieldCount )
270  {
271  rm = true;
272  beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount - 1 );
273  }
274 
275  mFieldCount = attributes.size();
276  mAttributes = attributes;
277 
278  if ( ins )
279  {
280  endInsertColumns();
281  }
282  else if ( rm )
283  {
284  endRemoveColumns();
285  }
286 }
287 
289 {
290  QgsDebugMsg( "entered." );
291 
292  if ( rowCount() != 0 )
293  {
294  beginRemoveRows( QModelIndex(), 0, rowCount() - 1 );
295  removeRows( 0, rowCount() );
296  endRemoveRows();
297  }
298 
299  QgsFeatureIterator features = mLayerCache->getFeatures( mFeatureRequest );
300 
301  int i = 0;
302 
303  QTime t;
304  t.start();
305 
306  QgsFeature feat;
307  while ( features.nextFeature( feat ) )
308  {
309  ++i;
310 
311  if ( t.elapsed() > 1000 )
312  {
313  bool cancel = false;
314  emit progress( i, cancel );
315  if ( cancel )
316  break;
317 
318  t.restart();
319  }
320  mFeat = feat;
321  featureAdded( feat.id() );
322  }
323 
324  emit finished();
325 
326  mFieldCount = mAttributes.size();
327 }
328 
330 {
331  if ( a == b )
332  return;
333 
334  int rowA = idToRow( a );
335  int rowB = idToRow( b );
336 
337  //emit layoutAboutToBeChanged();
338 
339  mRowIdMap.remove( rowA );
340  mRowIdMap.remove( rowB );
341  mRowIdMap.insert( rowA, b );
342  mRowIdMap.insert( rowB, a );
343 
344  mIdRowMap.remove( a );
345  mIdRowMap.remove( b );
346  mIdRowMap.insert( a, rowB );
347  mIdRowMap.insert( b, rowA );
348 
349  //emit layoutChanged();
350 }
351 
353 {
354  if ( !mIdRowMap.contains( id ) )
355  {
356  QgsDebugMsg( QString( "idToRow: id %1 not in the map" ).arg( id ) );
357  return -1;
358  }
359 
360  return mIdRowMap[id];
361 }
362 
364 {
365  return index( idToRow( id ), 0 );
366 }
367 
369 {
370  QModelIndexList indexes;
371 
372  int row = idToRow( id );
373  for ( int column = 0; column < columnCount(); ++column )
374  {
375  indexes.append( index( row, column ) );
376  }
377 
378  return indexes;
379 }
380 
382 {
383  if ( !mRowIdMap.contains( row ) )
384  {
385  QgsDebugMsg( QString( "rowToId: row %1 not in the map" ).arg( row ) );
386  // return negative infinite (to avoid collision with newly added features)
388  }
389 
390  return mRowIdMap[row];
391 }
392 
394 {
395  return mAttributes[ col ];
396 }
397 
399 {
400  return mAttributes.indexOf( idx );
401 }
402 
403 int QgsAttributeTableModel::rowCount( const QModelIndex &parent ) const
404 {
405  Q_UNUSED( parent );
406  return mRowIdMap.size();
407 }
408 
409 int QgsAttributeTableModel::columnCount( const QModelIndex &parent ) const
410 {
411  Q_UNUSED( parent );
412  return qMax( 1, mFieldCount ); // if there are zero columns all model indices will be considered invalid
413 }
414 
415 QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
416 {
417  if ( !layer() )
418  return QVariant();
419 
420  if ( role == Qt::DisplayRole )
421  {
422  if ( orientation == Qt::Vertical ) //row
423  {
424  return QVariant( section );
425  }
426  else if ( section >= 0 && section < mFieldCount )
427  {
428  QString attributeName = layer()->attributeAlias( mAttributes[section] );
429  if ( attributeName.isEmpty() )
430  {
431  QgsField field = layer()->pendingFields()[ mAttributes[section] ];
432  attributeName = field.name();
433  }
434  return QVariant( attributeName );
435  }
436  else
437  {
438  return tr( "feature id" );
439  }
440  }
441  else
442  {
443  return QVariant();
444  }
445 }
446 
447 QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) const
448 {
449  if ( !index.isValid() ||
450  ( role != Qt::TextAlignmentRole
451  && role != Qt::DisplayRole
452  && role != Qt::EditRole
453  && role != SortRole
454  && role != FeatureIdRole
455  && role != FieldIndexRole
456  )
457  )
458  return QVariant();
459 
460  QgsFeatureId rowId = rowToId( index.row() );
461 
462  if ( role == FeatureIdRole )
463  return rowId;
464 
465  if ( index.column() >= mFieldCount )
466  return role == Qt::DisplayRole ? rowId : QVariant();
467 
468  int fieldId = mAttributes[ index.column()];
469 
470  if ( role == FieldIndexRole )
471  return fieldId;
472 
473  const QgsField& field = layer()->pendingFields()[ fieldId ];
474 
475  QVariant::Type fldType = field.type();
476  bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
477 
478  if ( role == Qt::TextAlignmentRole )
479  {
480  if ( fldNumeric )
481  return QVariant( Qt::AlignRight );
482  else
483  return QVariant( Qt::AlignLeft );
484  }
485 
486  QVariant val;
487 
488  // if we don't have the row in current cache, load it from layer first
489  if ( mCachedField == fieldId )
490  {
491  val = mFieldCache[ rowId ];
492  }
493  else
494  {
495  if ( mFeat.id() != rowId || !mFeat.isValid() )
496  {
497  if ( !loadFeatureAtId( rowId ) )
498  return QVariant( "ERROR" );
499 
500  if ( mFeat.id() != rowId )
501  return QVariant( "ERROR" );
502  }
503 
504  val = mFeat.attribute( fieldId );
505  }
506 
507  if ( role == Qt::DisplayRole )
508  {
509  return mWidgetFactories[ index.column()]->representValue( layer(), fieldId, mWidgetConfigs[ index.column()], mAttributeWidgetCaches[ index.column()], val );
510  }
511 
512  return val;
513 }
514 
515 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
516 {
517  Q_UNUSED( value )
518 
519  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !layer()->isEditable() )
520  return false;
521 
522  if ( !layer()->isModified() )
523  return false;
524 
525  if ( mChangedCellBounds.isNull() )
526  {
527  mChangedCellBounds = QRect( index.column(), index.row(), 1, 1 );
528  }
529  else
530  {
531  if ( index.column() < mChangedCellBounds.left() )
532  {
533  mChangedCellBounds.setLeft( index.column() );
534  }
535  if ( index.row() < mChangedCellBounds.top() )
536  {
537  mChangedCellBounds.setTop( index.row() );
538  }
539  if ( index.column() > mChangedCellBounds.right() )
540  {
541  mChangedCellBounds.setRight( index.column() );
542  }
543  if ( index.row() > mChangedCellBounds.bottom() )
544  {
545  mChangedCellBounds.setBottom( index.row() );
546  }
547  }
548 
549  return true;
550 }
551 
552 Qt::ItemFlags QgsAttributeTableModel::flags( const QModelIndex &index ) const
553 {
554  if ( !index.isValid() )
555  return Qt::ItemIsEnabled;
556 
557  if ( index.column() >= mFieldCount )
558  return Qt::NoItemFlags;
559 
560  Qt::ItemFlags flags = QAbstractItemModel::flags( index );
561 
562  if ( layer()->isEditable() &&
563  layer()->fieldEditable( mAttributes[ index.column()] ) )
564  flags |= Qt::ItemIsEditable;
565 
566  return flags;
567 }
568 
569 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
570 {
572  emit dataChanged( index1, index2 );
573 }
574 
576 {
577  beginResetModel();
578  endResetModel();
579 }
580 
581 void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
582 {
583  QgsFeature f = feature( idx );
584  layer()->actions()->doAction( action, f, fieldIdx( idx.column() ) );
585 }
586 
587 void QgsAttributeTableModel::executeMapLayerAction( QgsMapLayerAction* action, const QModelIndex &idx ) const
588 {
589  QgsFeature f = feature( idx );
590  action->triggerForFeature( layer(), &f );
591 }
592 
593 QgsFeature QgsAttributeTableModel::feature( const QModelIndex &idx ) const
594 {
595  QgsFeature f;
596  f.initAttributes( mAttributes.size() );
597  f.setFeatureId( rowToId( idx.row() ) );
598  for ( int i = 0; i < mAttributes.size(); i++ )
599  {
600  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
601  }
602 
603  return f;
604 }
605 
607 {
608  mFieldCache.clear();
609 
610  if ( column == -1 )
611  {
612  mCachedField = -1;
613  }
614  else
615  {
616  if ( column >= mAttributes.count() )
617  return;
618  int fieldId = mAttributes[ column ];
619  const QgsFields& fields = layer()->pendingFields();
620  QStringList fldNames;
621  fldNames << fields[ fieldId ].name();
622 
623  QgsFeatureRequest r( mFeatureRequest );
625 
626  QgsFeature f;
627  while ( it.nextFeature( f ) )
628  {
629  mFieldCache.insert( f.id(), f.attribute( fieldId ) );
630  }
631 
632  mCachedField = fieldId;
633  }
634 }
635 
637 {
638  mFeatureRequest = request;
639  if ( layer() && !layer()->hasGeometryType() )
640  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
641 }
642 
644 {
645  return mFeatureRequest;
646 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:51
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:69
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
const Flags & flags() const
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before basing any other models on this model...
QModelIndexList idToIndexList(QgsFeatureId id) const
QHash< int, QgsFeatureId > mRowIdMap
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:168
QgsAttributeAction * actions()
QgsEditorWidgetFactory * factory(const QString &widgetId)
Get a factory for the given widget type id.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual void layerDeleted()
Launched when layer has been deleted.
void reload(const QModelIndex &index1, const QModelIndex &index2)
Reloads the model data between indices.
#define FID_TO_STRING(fid)
Definition: qgsfeature.h:89
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QModelIndex idToIndex(QgsFeatureId id) const
Container of fields for a vector layer.
Definition: qgsfield.h:173
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
Definition: qgsfeature.cpp:192
QgsVectorLayer * layer()
Returns the layer to which this cache belongs.
const QgsFeatureRequest & request() const
Get the the feature request.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:119
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
static QgsEditorWidgetRegistry * instance()
This class is a singleton and has therefore to be accessed with this method instead of a constructor...
void resetModel()
Resets the model.
virtual QVariant createCache(QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config)
Create a cache for a given field.
QgsVectorLayerCache * mLayerCache
virtual void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Launched when attribute value has been changed.
virtual QVariant data(const QModelIndex &index, int role) const override
Returns data on the given index.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Returns header data.
void executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx) const
Execute a QgsMapLayerAction.
void setFeatureId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:81
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns.
QVector< QgsEditorWidgetFactory * > mWidgetFactories
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:182
const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
Every attribute editor widget needs a factory, which inherits this class.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
QVector< QgsEditorWidgetConfig > mWidgetConfigs
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Remove rows.
int count() const
Return number of items.
Definition: qgsfield.cpp:279
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QHash< QgsFeatureId, int > mIdRowMap
FilterType filterType() const
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:38
QString attributeAlias(int attributeIndex) const
Returns the alias of an attribute name or an empty string if there is no alias.
void executeAction(int action, const QModelIndex &idx) const
Execute an action.
virtual void featureAdded(QgsFeatureId fid)
Launched when a feature has been added.
int min(int a, int b)
Definition: util.h:93
QgsFeature feature(const QModelIndex &idx) const
Return the feature attributes at given model index.
This class caches features of a given QgsVectorLayer.
void progress(int i, bool &cancel)
void modelChanged()
Model has been changed.
QVector< QVariant > mAttributeWidgetCaches
No filter is applied.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:236
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
int fieldCol(int idx) const
get column from field index
virtual void featureDeleted(QgsFeatureId fid)
Launched when a feature has been deleted.
bool featureAtId(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id.
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
virtual void loadAttributes()
Gets mFieldCount, mAttributes and mValueMaps.
int idToRow(QgsFeatureId id) const
Maps feature id to table row.
void doAction(int index, const QgsFeature &feat, int defaultValueIndex=0)
qint64 QgsFeatureId
Definition: qgsfeature.h:31
int fieldIdx(int col) const
get field index from column
QgsFeatureId rowToId(int row) const
Maps row to feature id.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void swapRows(QgsFeatureId a, QgsFeatureId b)
Swaps two rows.
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Updates data on given index.
void triggerForFeature(QgsMapLayer *layer, const QgsFeature *feature)
Triggers the action with the specified layer and feature.
QgsAttributeTableModel(QgsVectorLayerCache *layerCache, QObject *parent=0)
Constructor.
An action which can run on map layers.
void prefetchColumnData(int column)
Caches the entire data for one column.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:74
#define tr(sourceText)