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