QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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( featuresDeleted( QgsFeatureIds ) ), this, SLOT( featuresDeleted( QgsFeatureIds ) ) );
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  QList<int> rows;
79 
80  Q_FOREACH ( const QgsFeatureId& fid, fids )
81  {
82  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
83 
84  int row = idToRow( fid );
85  if ( row != -1 )
86  rows << row;
87  }
88 
89  qSort( rows );
90 
91  int lastRow = -1;
92  int beginRow = -1;
93  int currentRowCount = 0;
94  int removedRows = 0;
95  bool reset = false;
96 
97  Q_FOREACH ( int row, rows )
98  {
99 #if 0
100  qDebug() << "Row: " << row << ", begin " << beginRow << ", last " << lastRow << ", current " << currentRowCount << ", removed " << removedRows;
101 #endif
102  if ( lastRow == -1 )
103  {
104  beginRow = row;
105  }
106 
107  if ( row != lastRow + 1 && lastRow != -1 )
108  {
109  if ( rows.count() > 100 && currentRowCount < 10 )
110  {
111  reset = true;
112  break;
113  }
114  removeRows( beginRow - removedRows, currentRowCount );
115 
116  beginRow = row;
117  removedRows += currentRowCount;
118  currentRowCount = 0;
119  }
120 
121  currentRowCount++;
122 
123  lastRow = row;
124  }
125 
126  if ( !reset )
127  removeRows( beginRow - removedRows, currentRowCount );
128  else
129  resetModel();
130 }
131 
132 bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &parent )
133 {
134  beginRemoveRows( parent, row, row + count - 1 );
135 #ifdef QGISDEBUG
136  if ( 3 > QgsLogger::debugLevel() )
137  QgsDebugMsgLevel( QString( "remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
138 #endif
139 
140  // clean old references
141  for ( int i = row; i < row + count; i++ )
142  {
143  mFieldCache.remove( mRowIdMap[i] );
144  mIdRowMap.remove( mRowIdMap[ i ] );
145  mRowIdMap.remove( i );
146  }
147 
148  // update maps
149  int n = mRowIdMap.size() + count;
150  for ( int i = row + count; i < n; i++ )
151  {
152  QgsFeatureId id = mRowIdMap[i];
153  mIdRowMap[ id ] -= count;
154  mRowIdMap[ i-count ] = id;
155  mRowIdMap.remove( i );
156  }
157 
158 #ifdef QGISDEBUG
159  if ( 4 > QgsLogger::debugLevel() )
160  {
161  QgsDebugMsgLevel( QString( "after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
162  QgsDebugMsgLevel( "id->row", 4 );
163  for ( QHash<QgsFeatureId, int>::iterator it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
164  QgsDebugMsgLevel( QString( "%1->%2" ).arg( FID_TO_STRING( it.key() ) ).arg( *it ), 4 );
165 
167 
168  QgsDebugMsgLevel( "row->id", 4 );
169  for ( QHash<int, QgsFeatureId>::iterator it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
170  QgsDebugMsgLevel( QString( "%1->%2" ).arg( it.key() ).arg( FID_TO_STRING( *it ) ), 4 );
171  }
172 #endif
173 
174  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
175 
176  endRemoveRows();
177 
178  return true;
179 }
180 
182 {
183  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
184  bool featOk = true;
185 
186  if ( mFeat.id() != fid )
187  featOk = loadFeatureAtId( fid );
188 
189  if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
190  {
191  mFieldCache[ fid ] = mFeat.attribute( mCachedField );
192 
193  int n = mRowIdMap.size();
194  beginInsertRows( QModelIndex(), n, n );
195 
196  mIdRowMap.insert( fid, n );
197  mRowIdMap.insert( n, fid );
198 
199  endInsertRows();
200 
201  reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
202  }
203 }
204 
205 void QgsAttributeTableModel::updatedFields()
206 {
207  QgsDebugMsg( "entered." );
208  loadAttributes();
209  emit modelChanged();
210 }
211 
212 void QgsAttributeTableModel::editCommandEnded()
213 {
214  reload( createIndex( mChangedCellBounds.top(), mChangedCellBounds.left() ),
215  createIndex( mChangedCellBounds.bottom(), mChangedCellBounds.right() ) );
216 
217  mChangedCellBounds = QRect();
218 }
219 
220 void QgsAttributeTableModel::attributeDeleted( int idx )
221 {
222  if ( idx == mCachedField )
223  {
224  prefetchColumnData( -1 );
225  }
226 }
227 
229 {
230  QgsDebugMsg( "entered." );
231 
232  removeRows( 0, rowCount() );
233 
235  mAttributes.clear();
237  mWidgetConfigs.clear();
238 }
239 
241 {
242  QgsDebugMsgLevel( QString( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 3 );
243 
244  if ( idx == mCachedField )
245  mFieldCache[ fid ] = value;
246 
247  // No filter request: skip all possibly heavy checks
248  if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
249  {
250  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
251  }
252  else
253  {
254  if ( loadFeatureAtId( fid ) )
255  {
256  if ( mFeatureRequest.acceptFeature( mFeat ) )
257  {
258  if ( !mIdRowMap.contains( fid ) )
259  {
260  // Feature changed in such a way, it will be shown now
261  featureAdded( fid );
262  }
263  else
264  {
265  // Update representation
266  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
267  }
268  }
269  else
270  {
271  if ( mIdRowMap.contains( fid ) )
272  {
273  // Feature changed such, that it is no longer shown
274  featuresDeleted( QgsFeatureIds() << fid );
275  }
276  // else: we don't care
277  }
278  }
279  }
280 }
281 
283 {
284  if ( !layer() )
285  {
286  return;
287  }
288 
289  bool ins = false, rm = false;
290 
291  QgsAttributeList attributes;
292  const QgsFields& fields = layer()->pendingFields();
293 
296  mWidgetConfigs.clear();
297 
298  for ( int idx = 0; idx < fields.count(); ++idx )
299  {
300  const QString widgetType = layer()->editorWidgetV2( idx );
301  QgsEditorWidgetFactory* widgetFactory = QgsEditorWidgetRegistry::instance()->factory( widgetType );
302  if ( widgetFactory && widgetType != "Hidden" )
303  {
304  mWidgetFactories.append( widgetFactory );
305  mWidgetConfigs.append( layer()->editorWidgetV2Config( idx ) );
306  mAttributeWidgetCaches.append( widgetFactory->createCache( layer(), idx, mWidgetConfigs.last() ) );
307 
308  attributes << idx;
309  }
310  }
311 
312  if ( mFieldCount < attributes.size() )
313  {
314  ins = true;
315  beginInsertColumns( QModelIndex(), mFieldCount, attributes.size() - 1 );
316  }
317  else if ( attributes.size() < mFieldCount )
318  {
319  rm = true;
320  beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount - 1 );
321  }
322 
323  mFieldCount = attributes.size();
324  mAttributes = attributes;
325 
326  if ( ins )
327  {
329  }
330  else if ( rm )
331  {
333  }
334 }
335 
337 {
338  QgsDebugMsg( "entered." );
339 
340  // make sure attributes are properly updated before caching the data
341  // (emit of progress() signal may enter event loop and thus attribute
342  // table view may be updated with inconsistent model which may assume
343  // wrong number of attributes)
344  loadAttributes();
345 
346  beginResetModel();
347 
348  if ( rowCount() != 0 )
349  {
350  removeRows( 0, rowCount() );
351  }
352 
353  QgsFeatureIterator features = mLayerCache->getFeatures( mFeatureRequest );
354 
355  int i = 0;
356 
357  QTime t;
358  t.start();
359 
360  QgsFeature feat;
361  while ( features.nextFeature( feat ) )
362  {
363  ++i;
364 
365  if ( t.elapsed() > 1000 )
366  {
367  bool cancel = false;
368  emit progress( i, cancel );
369  if ( cancel )
370  break;
371 
372  t.restart();
373  }
374  mFeat = feat;
375  featureAdded( feat.id() );
376  }
377 
378  emit finished();
379 
380  connect( mLayerCache, SIGNAL( invalidated() ), this, SLOT( loadLayer() ), Qt::UniqueConnection );
381 
382  endResetModel();
383 }
384 
386 {
387  if ( a == b )
388  return;
389 
390  int rowA = idToRow( a );
391  int rowB = idToRow( b );
392 
393  //emit layoutAboutToBeChanged();
394 
395  mRowIdMap.remove( rowA );
396  mRowIdMap.remove( rowB );
397  mRowIdMap.insert( rowA, b );
398  mRowIdMap.insert( rowB, a );
399 
400  mIdRowMap.remove( a );
401  mIdRowMap.remove( b );
402  mIdRowMap.insert( a, rowB );
403  mIdRowMap.insert( b, rowA );
404 
405  //emit layoutChanged();
406 }
407 
409 {
410  if ( !mIdRowMap.contains( id ) )
411  {
412  QgsDebugMsg( QString( "idToRow: id %1 not in the map" ).arg( id ) );
413  return -1;
414  }
415 
416  return mIdRowMap[id];
417 }
418 
420 {
421  return index( idToRow( id ), 0 );
422 }
423 
425 {
426  QModelIndexList indexes;
427 
428  int row = idToRow( id );
429  for ( int column = 0; column < columnCount(); ++column )
430  {
431  indexes.append( index( row, column ) );
432  }
433 
434  return indexes;
435 }
436 
438 {
439  if ( !mRowIdMap.contains( row ) )
440  {
441  QgsDebugMsg( QString( "rowToId: row %1 not in the map" ).arg( row ) );
442  // return negative infinite (to avoid collision with newly added features)
444  }
445 
446  return mRowIdMap[row];
447 }
448 
450 {
451  return mAttributes[ col ];
452 }
453 
455 {
456  return mAttributes.indexOf( idx );
457 }
458 
460 {
461  Q_UNUSED( parent );
462  return mRowIdMap.size();
463 }
464 
466 {
467  Q_UNUSED( parent );
468  return qMax( 1, mFieldCount ); // if there are zero columns all model indices will be considered invalid
469 }
470 
471 QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
472 {
473  if ( !layer() )
474  return QVariant();
475 
476  if ( role == Qt::DisplayRole )
477  {
478  if ( orientation == Qt::Vertical ) //row
479  {
480  return QVariant( section );
481  }
482  else if ( section >= 0 && section < mFieldCount )
483  {
484  QString attributeName = layer()->attributeAlias( mAttributes[section] );
485  if ( attributeName.isEmpty() )
486  {
487  QgsField field = layer()->pendingFields()[ mAttributes[section] ];
488  attributeName = field.name();
489  }
490  return QVariant( attributeName );
491  }
492  else
493  {
494  return tr( "feature id" );
495  }
496  }
497  else
498  {
499  return QVariant();
500  }
501 }
502 
504 {
505  if ( !index.isValid() ||
506  ( role != Qt::TextAlignmentRole
507  && role != Qt::DisplayRole
508  && role != Qt::EditRole
509  && role != SortRole
510  && role != FeatureIdRole
511  && role != FieldIndexRole
512  )
513  )
514  return QVariant();
515 
516  QgsFeatureId rowId = rowToId( index.row() );
517 
518  if ( role == FeatureIdRole )
519  return rowId;
520 
521  if ( index.column() >= mFieldCount )
522  return role == Qt::DisplayRole ? rowId : QVariant();
523 
524  int fieldId = mAttributes[ index.column()];
525 
526  if ( role == FieldIndexRole )
527  return fieldId;
528 
529  const QgsField& field = layer()->pendingFields()[ fieldId ];
530 
531  QVariant::Type fldType = field.type();
532  bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
533 
534  if ( role == Qt::TextAlignmentRole )
535  {
536  if ( fldNumeric )
537  return QVariant( Qt::AlignRight );
538  else
539  return QVariant( Qt::AlignLeft );
540  }
541 
542  QVariant val;
543 
544  // if we don't have the row in current cache, load it from layer first
545  if ( mCachedField == fieldId )
546  {
547  val = mFieldCache[ rowId ];
548  }
549  else
550  {
551  if ( mFeat.id() != rowId || !mFeat.isValid() )
552  {
553  if ( !loadFeatureAtId( rowId ) )
554  return QVariant( "ERROR" );
555 
556  if ( mFeat.id() != rowId )
557  return QVariant( "ERROR" );
558  }
559 
560  val = mFeat.attribute( fieldId );
561  }
562 
563  if ( role == Qt::DisplayRole )
564  {
565  return mWidgetFactories[ index.column()]->representValue( layer(), fieldId, mWidgetConfigs[ index.column()], mAttributeWidgetCaches[ index.column()], val );
566  }
567 
568  return val;
569 }
570 
571 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
572 {
573  Q_UNUSED( value )
574 
575  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !layer()->isEditable() )
576  return false;
577 
578  if ( !layer()->isModified() )
579  return false;
580 
581  if ( mChangedCellBounds.isNull() )
582  {
583  mChangedCellBounds = QRect( index.column(), index.row(), 1, 1 );
584  }
585  else
586  {
587  if ( index.column() < mChangedCellBounds.left() )
588  {
589  mChangedCellBounds.setLeft( index.column() );
590  }
591  if ( index.row() < mChangedCellBounds.top() )
592  {
593  mChangedCellBounds.setTop( index.row() );
594  }
595  if ( index.column() > mChangedCellBounds.right() )
596  {
597  mChangedCellBounds.setRight( index.column() );
598  }
599  if ( index.row() > mChangedCellBounds.bottom() )
600  {
601  mChangedCellBounds.setBottom( index.row() );
602  }
603  }
604 
605  return true;
606 }
607 
609 {
610  if ( !index.isValid() )
611  return Qt::ItemIsEnabled;
612 
613  if ( index.column() >= mFieldCount )
614  return Qt::NoItemFlags;
615 
617 
618  if ( layer()->isEditable() &&
619  layer()->fieldEditable( mAttributes[ index.column()] ) )
620  flags |= Qt::ItemIsEditable;
621 
622  return flags;
623 }
624 
625 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
626 {
628  emit dataChanged( index1, index2 );
629 }
630 
631 
632 
633 void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
634 {
635  QgsFeature f = feature( idx );
636  layer()->actions()->doAction( action, f, fieldIdx( idx.column() ) );
637 }
638 
640 {
641  QgsFeature f = feature( idx );
642  action->triggerForFeature( layer(), &f );
643 }
644 
646 {
647  QgsFeature f;
649  f.setFeatureId( rowToId( idx.row() ) );
650  for ( int i = 0; i < mAttributes.size(); i++ )
651  {
652  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
653  }
654 
655  return f;
656 }
657 
659 {
660  mFieldCache.clear();
661 
662  if ( column == -1 )
663  {
664  mCachedField = -1;
665  }
666  else
667  {
668  if ( column >= mAttributes.count() )
669  return;
670  int fieldId = mAttributes[ column ];
671  const QgsFields& fields = layer()->pendingFields();
672  QStringList fldNames;
673  fldNames << fields[ fieldId ].name();
674 
675  QgsFeatureRequest r( mFeatureRequest );
677 
678  QgsFeature f;
679  while ( it.nextFeature( f ) )
680  {
681  mFieldCache.insert( f.id(), f.attribute( fieldId ) );
682  }
683 
684  mCachedField = fieldId;
685  }
686 }
687 
689 {
690  mFeatureRequest = request;
691  if ( layer() && !layer()->hasGeometryType() )
692  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
693 }
694 
696 {
697  return mFeatureRequest;
698 }
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
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
void setBottom(int y)
static unsigned index
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
iterator insert(const Key &key, const T &value)
const Flags & flags() const
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
QModelIndexList idToIndexList(QgsFeatureId id) const
QHash< int, QgsFeatureId > mRowIdMap
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:168
QgsAttributeAction * actions()
void append(const T &value)
int right() const
QgsEditorWidgetFactory * factory(const QString &widgetId)
Get a factory for the given widget type id.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:408
virtual void layerDeleted()
Launched when layer has been deleted.
int size() const
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:162
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...
QString tr(const char *sourceText, const char *disambiguation, int n)
void resetModel()
Resets the model.
virtual QVariant createCache(QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config)
Create a cache for a given field.
QgsVectorLayerCache * mLayerCache
int size() const
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.
int indexOf(const T &value, int from) const
void clear()
bool isValid() const
int elapsed() const
int count(const T &value) const
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
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
int top() const
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns.
QVector< QgsEditorWidgetFactory * > mWidgetFactories
void setTop(int y)
int left() const
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.
bool isEmpty() const
void beginRemoveRows(const QModelIndex &parent, int first, int last)
int row() const
iterator begin()
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)...
void beginRemoveColumns(const QModelIndex &parent, int first, int last)
int restart()
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:283
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
int remove(const Key &key)
virtual void featuresDeleted(QgsFeatureIds fids)
Launched when eatures have been deleted.
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.
QModelIndex createIndex(int row, int column, void *ptr) const
void clear()
QgsFeature feature(const QModelIndex &idx) const
Return the feature attributes at given model index.
This class caches features of a given QgsVectorLayer.
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
Definition: qgslogger.h:93
void progress(int i, bool &cancel)
void beginInsertRows(const QModelIndex &parent, int first, int last)
void modelChanged()
Model has been changed.
bool isNull() const
void setRight(int x)
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
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.
int bottom() const
virtual void loadAttributes()
Gets mFieldCount, mAttributes and mValueMaps.
int column() const
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
void start()
virtual Qt::ItemFlags flags(const QModelIndex &index) const
bool contains(const Key &key) const
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.
double ANALYSIS_EXPORT min(double x, double y)
returns the minimum of two doubles or the first argument if both are equal
iterator end()
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.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void setLeft(int x)
void beginInsertColumns(const QModelIndex &parent, int first, int last)
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
typedef ItemFlags