QGIS API Documentation  2.11.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 "qgsconditionalstyle.h"
24 #include "qgsfield.h"
25 #include "qgslogger.h"
26 #include "qgsmapcanvas.h"
28 #include "qgsmaplayerregistry.h"
29 #include "qgsrendererv2.h"
30 #include "qgsvectorlayer.h"
31 #include "qgssymbollayerv2utils.h"
32 
33 #include <QVariant>
34 
35 #include <limits>
36 
38  : QAbstractTableModel( parent )
39  , mLayerCache( layerCache )
40  , mFieldCount( 0 )
41  , mCachedField( -1 )
42 {
43  QgsDebugMsg( "entered." );
44 
47  << QgsExpressionContextUtils::layerScope( layerCache->layer() );
48 
49  if ( layerCache->layer()->geometryType() == QGis::NoGeometry )
50  {
51  mFeatureRequest.setFlags( QgsFeatureRequest::NoGeometry );
52  }
53 
55 
56  if ( !layer()->hasGeometryType() )
57  mFeatureRequest.setFlags( QgsFeatureRequest::NoGeometry );
58 
60 
61  connect( mLayerCache, SIGNAL( attributeValueChanged( QgsFeatureId, int, const QVariant& ) ), this, SLOT( attributeValueChanged( QgsFeatureId, int, const QVariant& ) ) );
62  connect( layer(), SIGNAL( featuresDeleted( QgsFeatureIds ) ), this, SLOT( featuresDeleted( QgsFeatureIds ) ) );
63  connect( layer(), SIGNAL( attributeDeleted( int ) ), this, SLOT( attributeDeleted( int ) ) );
64  connect( layer(), SIGNAL( updatedFields() ), this, SLOT( updatedFields() ) );
65  connect( layer(), SIGNAL( editCommandEnded() ), this, SLOT( editCommandEnded() ) );
66  connect( mLayerCache, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( featureAdded( QgsFeatureId ) ) );
67  connect( mLayerCache, SIGNAL( cachedLayerDeleted() ), this, SLOT( layerDeleted() ) );
68 }
69 
70 bool QgsAttributeTableModel::loadFeatureAtId( QgsFeatureId fid ) const
71 {
72  QgsDebugMsgLevel( QString( "loading feature %1" ).arg( fid ), 3 );
73 
74  if ( fid == std::numeric_limits<int>::min() )
75  {
76  return false;
77  }
78 
79  return mLayerCache->featureAtId( fid, mFeat );
80 }
81 
83 {
84  QList<int> rows;
85 
86  Q_FOREACH ( const QgsFeatureId& fid, fids )
87  {
88  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
89 
90  int row = idToRow( fid );
91  if ( row != -1 )
92  rows << row;
93  }
94 
95  qSort( rows );
96 
97  int lastRow = -1;
98  int beginRow = -1;
99  int currentRowCount = 0;
100  int removedRows = 0;
101  bool reset = false;
102 
103  Q_FOREACH ( int row, rows )
104  {
105 #if 0
106  qDebug() << "Row: " << row << ", begin " << beginRow << ", last " << lastRow << ", current " << currentRowCount << ", removed " << removedRows;
107 #endif
108  if ( lastRow == -1 )
109  {
110  beginRow = row;
111  }
112 
113  if ( row != lastRow + 1 && lastRow != -1 )
114  {
115  if ( rows.count() > 100 && currentRowCount < 10 )
116  {
117  reset = true;
118  break;
119  }
120  removeRows( beginRow - removedRows, currentRowCount );
121 
122  beginRow = row;
123  removedRows += currentRowCount;
124  currentRowCount = 0;
125  }
126 
127  currentRowCount++;
128 
129  lastRow = row;
130  }
131 
132  if ( !reset )
133  removeRows( beginRow - removedRows, currentRowCount );
134  else
135  resetModel();
136 }
137 
138 bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &parent )
139 {
140  beginRemoveRows( parent, row, row + count - 1 );
141 #ifdef QGISDEBUG
142  if ( 3 > QgsLogger::debugLevel() )
143  QgsDebugMsgLevel( QString( "remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
144 #endif
145 
146  // clean old references
147  for ( int i = row; i < row + count; i++ )
148  {
149  mFieldCache.remove( mRowIdMap[i] );
150  mIdRowMap.remove( mRowIdMap[ i ] );
151  mRowIdMap.remove( i );
152  }
153 
154  // update maps
155  int n = mRowIdMap.size() + count;
156  for ( int i = row + count; i < n; i++ )
157  {
158  QgsFeatureId id = mRowIdMap[i];
159  mIdRowMap[ id ] -= count;
160  mRowIdMap[ i-count ] = id;
161  mRowIdMap.remove( i );
162  }
163 
164 #ifdef QGISDEBUG
165  if ( 4 > QgsLogger::debugLevel() )
166  {
167  QgsDebugMsgLevel( QString( "after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
168  QgsDebugMsgLevel( "id->row", 4 );
169  for ( QHash<QgsFeatureId, int>::iterator it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
170  QgsDebugMsgLevel( QString( "%1->%2" ).arg( FID_TO_STRING( it.key() ) ).arg( *it ), 4 );
171 
173 
174  QgsDebugMsgLevel( "row->id", 4 );
175  for ( QHash<int, QgsFeatureId>::iterator it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
176  QgsDebugMsgLevel( QString( "%1->%2" ).arg( it.key() ).arg( FID_TO_STRING( *it ) ), 4 );
177  }
178 #endif
179 
180  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
181 
182  endRemoveRows();
183 
184  return true;
185 }
186 
188 {
189  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
190  bool featOk = true;
191 
192  if ( mFeat.id() != fid )
193  featOk = loadFeatureAtId( fid );
194 
195  if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
196  {
197  mFieldCache[ fid ] = mFeat.attribute( mCachedField );
198 
199  int n = mRowIdMap.size();
200  beginInsertRows( QModelIndex(), n, n );
201 
202  mIdRowMap.insert( fid, n );
203  mRowIdMap.insert( n, fid );
204 
205  endInsertRows();
206 
207  reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
208  }
209 }
210 
211 void QgsAttributeTableModel::updatedFields()
212 {
213  QgsDebugMsg( "entered." );
214  loadAttributes();
215  emit modelChanged();
216 }
217 
218 void QgsAttributeTableModel::editCommandEnded()
219 {
220  reload( createIndex( mChangedCellBounds.top(), mChangedCellBounds.left() ),
221  createIndex( mChangedCellBounds.bottom(), mChangedCellBounds.right() ) );
222 
223  mChangedCellBounds = QRect();
224 }
225 
226 void QgsAttributeTableModel::attributeDeleted( int idx )
227 {
228  if ( idx == mCachedField )
229  {
230  prefetchColumnData( -1 );
231  }
232 }
233 
235 {
236  QgsDebugMsg( "entered." );
237 
238  removeRows( 0, rowCount() );
239 
241  mAttributes.clear();
243  mWidgetConfigs.clear();
244 }
245 
247 {
248  QgsDebugMsgLevel( QString( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 3 );
249 
250  if ( idx == mCachedField )
251  mFieldCache[ fid ] = value;
252 
253  // No filter request: skip all possibly heavy checks
254  if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
255  {
256  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
257  }
258  else
259  {
260  if ( loadFeatureAtId( fid ) )
261  {
262  if ( mFeatureRequest.acceptFeature( mFeat ) )
263  {
264  if ( !mIdRowMap.contains( fid ) )
265  {
266  // Feature changed in such a way, it will be shown now
267  featureAdded( fid );
268  }
269  else
270  {
271  // Update representation
272  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
273  }
274  }
275  else
276  {
277  if ( mIdRowMap.contains( fid ) )
278  {
279  // Feature changed such, that it is no longer shown
280  featuresDeleted( QgsFeatureIds() << fid );
281  }
282  // else: we don't care
283  }
284  }
285  }
286 }
287 
289 {
290  if ( !layer() )
291  {
292  return;
293  }
294 
295  bool ins = false, rm = false;
296 
297  QgsAttributeList attributes;
298  const QgsFields& fields = layer()->fields();
299 
302  mWidgetConfigs.clear();
303 
304  for ( int idx = 0; idx < fields.count(); ++idx )
305  {
306  const QString widgetType = layer()->editorWidgetV2( idx );
307  QgsEditorWidgetFactory* widgetFactory = QgsEditorWidgetRegistry::instance()->factory( widgetType );
308  if ( widgetFactory && widgetType != "Hidden" )
309  {
310  mWidgetFactories.append( widgetFactory );
311  mWidgetConfigs.append( layer()->editorWidgetV2Config( idx ) );
312  mAttributeWidgetCaches.append( widgetFactory->createCache( layer(), idx, mWidgetConfigs.last() ) );
313 
314  attributes << idx;
315  }
316  }
317 
318  if ( mFieldCount < attributes.size() )
319  {
320  ins = true;
321  beginInsertColumns( QModelIndex(), mFieldCount, attributes.size() - 1 );
322  }
323  else if ( attributes.size() < mFieldCount )
324  {
325  rm = true;
326  beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount - 1 );
327  }
328 
329  mFieldCount = attributes.size();
330  mAttributes = attributes;
331 
332  if ( ins )
333  {
335  }
336  else if ( rm )
337  {
339  }
340 }
341 
343 {
344  QgsDebugMsg( "entered." );
345 
346  // make sure attributes are properly updated before caching the data
347  // (emit of progress() signal may enter event loop and thus attribute
348  // table view may be updated with inconsistent model which may assume
349  // wrong number of attributes)
350  loadAttributes();
351 
352  beginResetModel();
353 
354  if ( rowCount() != 0 )
355  {
356  removeRows( 0, rowCount() );
357  }
358 
359  QgsFeatureIterator features = mLayerCache->getFeatures( mFeatureRequest );
360 
361  int i = 0;
362 
363  QTime t;
364  t.start();
365 
366  QgsFeature feat;
367  while ( features.nextFeature( feat ) )
368  {
369  ++i;
370 
371  if ( t.elapsed() > 1000 )
372  {
373  bool cancel = false;
374  emit progress( i, cancel );
375  if ( cancel )
376  break;
377 
378  t.restart();
379  }
380  mFeat = feat;
381  featureAdded( feat.id() );
382  }
383 
384  emit finished();
385 
386  connect( mLayerCache, SIGNAL( invalidated() ), this, SLOT( loadLayer() ), Qt::UniqueConnection );
387 
388  endResetModel();
389 }
390 
392 {
393  if ( fieldName.isNull() )
394  {
396  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
397  return;
398  }
399 
400  int fieldIndex = mLayerCache->layer()->fieldNameIndex( fieldName );
401  if ( fieldIndex == -1 )
402  return;
403 
404  //whole column has changed
405  int col = fieldCol( fieldIndex );
406  emit dataChanged( index( 0, col ), index( rowCount() - 1, col ) );
407 }
408 
410 {
411  if ( a == b )
412  return;
413 
414  int rowA = idToRow( a );
415  int rowB = idToRow( b );
416 
417  //emit layoutAboutToBeChanged();
418 
419  mRowIdMap.remove( rowA );
420  mRowIdMap.remove( rowB );
421  mRowIdMap.insert( rowA, b );
422  mRowIdMap.insert( rowB, a );
423 
424  mIdRowMap.remove( a );
425  mIdRowMap.remove( b );
426  mIdRowMap.insert( a, rowB );
427  mIdRowMap.insert( b, rowA );
428 
429  //emit layoutChanged();
430 }
431 
433 {
434  if ( !mIdRowMap.contains( id ) )
435  {
436  QgsDebugMsg( QString( "idToRow: id %1 not in the map" ).arg( id ) );
437  return -1;
438  }
439 
440  return mIdRowMap[id];
441 }
442 
444 {
445  return index( idToRow( id ), 0 );
446 }
447 
449 {
450  QModelIndexList indexes;
451 
452  int row = idToRow( id );
453  for ( int column = 0; column < columnCount(); ++column )
454  {
455  indexes.append( index( row, column ) );
456  }
457 
458  return indexes;
459 }
460 
462 {
463  if ( !mRowIdMap.contains( row ) )
464  {
465  QgsDebugMsg( QString( "rowToId: row %1 not in the map" ).arg( row ) );
466  // return negative infinite (to avoid collision with newly added features)
468  }
469 
470  return mRowIdMap[row];
471 }
472 
474 {
475  return mAttributes[ col ];
476 }
477 
479 {
480  return mAttributes.indexOf( idx );
481 }
482 
484 {
485  Q_UNUSED( parent );
486  return mRowIdMap.size();
487 }
488 
490 {
491  Q_UNUSED( parent );
492  return qMax( 1, mFieldCount ); // if there are zero columns all model indices will be considered invalid
493 }
494 
495 QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
496 {
497  if ( !layer() )
498  return QVariant();
499 
500  if ( role == Qt::DisplayRole )
501  {
502  if ( orientation == Qt::Vertical ) //row
503  {
504  return QVariant( section );
505  }
506  else if ( section >= 0 && section < mFieldCount )
507  {
508  QString attributeName = layer()->attributeAlias( mAttributes[section] );
509  if ( attributeName.isEmpty() )
510  {
511  QgsField field = layer()->fields()[ mAttributes[section] ];
512  attributeName = field.name();
513  }
514  return QVariant( attributeName );
515  }
516  else
517  {
518  return tr( "feature id" );
519  }
520  }
521  else
522  {
523  return QVariant();
524  }
525 }
526 
528 {
529  if ( !index.isValid() ||
530  ( role != Qt::TextAlignmentRole
531  && role != Qt::DisplayRole
532  && role != Qt::EditRole
533  && role != SortRole
534  && role != FeatureIdRole
535  && role != FieldIndexRole
536  && role != Qt::BackgroundColorRole
537  && role != Qt::TextColorRole
538  && role != Qt::DecorationRole
539  && role != Qt::FontRole
540  )
541  )
542  return QVariant();
543 
544  QgsFeatureId rowId = rowToId( index.row() );
545 
546  if ( role == FeatureIdRole )
547  return rowId;
548 
549  if ( index.column() >= mFieldCount )
550  return role == Qt::DisplayRole ? rowId : QVariant();
551 
552  int fieldId = mAttributes[ index.column()];
553 
554  if ( role == FieldIndexRole )
555  return fieldId;
556 
557  QgsField field = layer()->fields().at( fieldId );
558 
559  QVariant::Type fldType = field.type();
560  bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
561 
562  if ( role == Qt::TextAlignmentRole )
563  {
564  if ( fldNumeric )
565  return QVariant( Qt::AlignRight );
566  else
567  return QVariant( Qt::AlignLeft );
568  }
569 
570  QVariant val;
571 
572  // if we don't have the row in current cache, load it from layer first
573  if ( mCachedField == fieldId )
574  {
575  val = mFieldCache[ rowId ];
576  }
577  else
578  {
579  if ( mFeat.id() != rowId || !mFeat.isValid() )
580  {
581  if ( !loadFeatureAtId( rowId ) )
582  return QVariant( "ERROR" );
583 
584  if ( mFeat.id() != rowId )
585  return QVariant( "ERROR" );
586  }
587 
588  val = mFeat.attribute( fieldId );
589  }
590 
591  if ( role == Qt::DisplayRole )
592  {
593  return mWidgetFactories[ index.column()]->representValue( layer(), fieldId, mWidgetConfigs[ index.column()], mAttributeWidgetCaches[ index.column()], val );
594  }
595 
596  if ( role == Qt::BackgroundColorRole || role == Qt::TextColorRole || role == Qt::DecorationRole || role == Qt::FontRole )
597  {
600  if ( mRowStylesMap.contains( index.row() ) )
601  {
602  styles = mRowStylesMap[index.row()];
603  }
604  else
605  {
606  styles = QgsConditionalStyle::matchingConditionalStyles( layer()->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
607  mRowStylesMap.insert( index.row(), styles );
608 
609  }
610 
612  styles = layer()->conditionalStyles()->fieldStyles( field.name() );
614  styles.insert( 0, rowstyle );
616 
617  if ( style.isValid() )
618  {
619  if ( role == Qt::BackgroundColorRole && style.validBackgroundColor() )
620  return style.backgroundColor();
621  if ( role == Qt::TextColorRole && style.validTextColor() )
622  return style.textColor();
623  if ( role == Qt::DecorationRole )
624  return style.icon();
625  if ( role == Qt::FontRole )
626  return style.font();
627  }
628 
629  }
630  return val;
631 }
632 
633 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
634 {
635  Q_UNUSED( value )
636 
637  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !layer()->isEditable() )
638  return false;
639 
640  if ( !layer()->isModified() )
641  return false;
642 
643  if ( mChangedCellBounds.isNull() )
644  {
645  mChangedCellBounds = QRect( index.column(), index.row(), 1, 1 );
646  }
647  else
648  {
649  if ( index.column() < mChangedCellBounds.left() )
650  {
651  mChangedCellBounds.setLeft( index.column() );
652  }
653  if ( index.row() < mChangedCellBounds.top() )
654  {
655  mChangedCellBounds.setTop( index.row() );
656  }
657  if ( index.column() > mChangedCellBounds.right() )
658  {
659  mChangedCellBounds.setRight( index.column() );
660  }
661  if ( index.row() > mChangedCellBounds.bottom() )
662  {
663  mChangedCellBounds.setBottom( index.row() );
664  }
665  }
666 
667  return true;
668 }
669 
671 {
672  if ( !index.isValid() )
673  return Qt::ItemIsEnabled;
674 
675  if ( index.column() >= mFieldCount )
676  return Qt::NoItemFlags;
677 
679 
680  if ( layer()->isEditable() &&
681  layer()->fieldEditable( mAttributes[ index.column()] ) )
682  flags |= Qt::ItemIsEditable;
683 
684  return flags;
685 }
686 
687 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
688 {
690  emit dataChanged( index1, index2 );
691 }
692 
693 
694 void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
695 {
696  QgsFeature f = feature( idx );
697  layer()->actions()->doAction( action, f, fieldIdx( idx.column() ) );
698 }
699 
701 {
702  QgsFeature f = feature( idx );
703  action->triggerForFeature( layer(), &f );
704 }
705 
707 {
708  QgsFeature f;
710  f.setFeatureId( rowToId( idx.row() ) );
711  for ( int i = 0; i < mAttributes.size(); i++ )
712  {
713  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
714  }
715 
716  return f;
717 }
718 
720 {
721  mFieldCache.clear();
722 
723  if ( column == -1 )
724  {
725  mCachedField = -1;
726  }
727  else
728  {
729  if ( column >= mAttributes.count() )
730  return;
731  int fieldId = mAttributes[ column ];
732  const QgsFields& fields = layer()->fields();
733  QStringList fldNames;
734  fldNames << fields[ fieldId ].name();
735 
736  QgsFeatureRequest r( mFeatureRequest );
738 
739  QgsFeature f;
740  while ( it.nextFeature( f ) )
741  {
742  mFieldCache.insert( f.id(), f.attribute( fieldId ) );
743  }
744 
745  mCachedField = fieldId;
746  }
747 }
748 
750 {
751  mFeatureRequest = request;
752  if ( layer() && !layer()->hasGeometryType() )
753  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
754 }
755 
757 {
758  return mFeatureRequest;
759 }
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:70
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
bool validTextColor() const
Check if the text color is valid for render.
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
QColor textColor() const
The text color set for style.
bool validBackgroundColor() const
Check if the background color is valid for render.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:408
QgsFields fields() const
Returns the list of fields of this layer.
virtual void layerDeleted()
Launched when layer has been deleted.
QFont font() const
The font for the style.
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.
QgsConditionalLayerStyles * conditionalStyles() const
Return the conditional styles that are set for this layer.
QModelIndex idToIndex(QgsFeatureId id) const
Container of fields for a vector layer.
Definition: qgsfield.h:177
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
Definition: qgsfeature.cpp:192
void fieldConditionalStyleChanged(const QString &fieldName)
Handles updating the model when the conditional style for a field changes.
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
bool isNull() 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.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QPixmap icon() const
The icon set for style generated from the set symbol.
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
static QList< QgsConditionalStyle > matchingConditionalStyles(QList< QgsConditionalStyle > styles, QVariant value, QgsExpressionContext &context)
Find and return the matching styles for the value and feature.
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
QgsExpressionContext mExpressionContext
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
QColor backgroundColor() const
The background color for style.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Remove rows.
int count() const
Return number of items.
Definition: qgsfield.cpp:285
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:40
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.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:305
static QgsConditionalStyle compressStyles(QList< QgsConditionalStyle > styles)
Compress a list of styles into a single style.
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.
void insert(int i, const T &value)
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)
Does the given values.
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
bool isValid() const
isValid Check if this rule is valid.
QList< QgsConditionalStyle > fieldStyles(QString fieldName)
Returns the conditional styles set for the field UI properties.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
iterator end()
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
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)
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
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.
QHash< int, QList< QgsConditionalStyle > > mRowStylesMap
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:75
typedef ItemFlags