QGIS API Documentation  2.15.0-Master (972fc9f)
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 "qgsactionmanager.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  , mSortCacheExpression( "" )
43  , mExtraColumns( 0 )
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  return mExtraColumns;
85 }
86 
88 {
89  mExtraColumns = extraColumns;
91 }
92 
94 {
95  QList<int> rows;
96 
97  Q_FOREACH ( QgsFeatureId fid, fids )
98  {
99  QgsDebugMsgLevel( QString( "(%2) fid: %1, size: %3" ).arg( fid ).arg( mFeatureRequest.filterType() ).arg( mIdRowMap.size() ), 4 );
100 
101  int row = idToRow( fid );
102  if ( row != -1 )
103  rows << row;
104  }
105 
106  qSort( rows );
107 
108  int lastRow = -1;
109  int beginRow = -1;
110  int currentRowCount = 0;
111  int removedRows = 0;
112  bool reset = false;
113 
114  Q_FOREACH ( int row, rows )
115  {
116 #if 0
117  qDebug() << "Row: " << row << ", begin " << beginRow << ", last " << lastRow << ", current " << currentRowCount << ", removed " << removedRows;
118 #endif
119  if ( lastRow == -1 )
120  {
121  beginRow = row;
122  }
123 
124  if ( row != lastRow + 1 && lastRow != -1 )
125  {
126  if ( rows.count() > 100 && currentRowCount < 10 )
127  {
128  reset = true;
129  break;
130  }
131  removeRows( beginRow - removedRows, currentRowCount );
132 
133  beginRow = row;
134  removedRows += currentRowCount;
135  currentRowCount = 0;
136  }
137 
138  currentRowCount++;
139 
140  lastRow = row;
141  }
142 
143  if ( !reset )
144  removeRows( beginRow - removedRows, currentRowCount );
145  else
146  resetModel();
147 }
148 
149 bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &parent )
150 {
151  if ( row < 0 || count < 1 )
152  return false;
153 
154  beginRemoveRows( parent, row, row + count - 1 );
155 #ifdef QGISDEBUG
156  if ( 3 <= QgsLogger::debugLevel() )
157  QgsDebugMsgLevel( QString( "remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
158 #endif
159 
160  // clean old references
161  for ( int i = row; i < row + count; i++ )
162  {
163  mSortCache.remove( mRowIdMap[i] );
164  mIdRowMap.remove( mRowIdMap[i] );
165  mRowIdMap.remove( i );
166  }
167 
168  // update maps
169  int n = mRowIdMap.size() + count;
170  for ( int i = row + count; i < n; i++ )
171  {
172  QgsFeatureId id = mRowIdMap[i];
173  mIdRowMap[id] -= count;
174  mRowIdMap[i-count] = id;
175  mRowIdMap.remove( i );
176  }
177 
178 #ifdef QGISDEBUG
179  if ( 4 <= QgsLogger::debugLevel() )
180  {
181  QgsDebugMsgLevel( QString( "after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
182  QgsDebugMsgLevel( "id->row", 4 );
184  QgsDebugMsgLevel( QString( "%1->%2" ).arg( FID_TO_STRING( it.key() ) ).arg( *it ), 4 );
185 
186  QgsDebugMsgLevel( "row->id", 4 );
188  QgsDebugMsgLevel( QString( "%1->%2" ).arg( it.key() ).arg( FID_TO_STRING( *it ) ), 4 );
189  }
190 #endif
191 
192  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
193 
194  endRemoveRows();
195 
196  return true;
197 }
198 
200 {
201  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
202  bool featOk = true;
203 
204  if ( mFeat.id() != fid )
205  featOk = loadFeatureAtId( fid );
206 
207  if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
208  {
210  mSortCache[fid] = mSortCacheExpression.evaluate();
211 
212  int n = mRowIdMap.size();
213  beginInsertRows( QModelIndex(), n, n );
214 
215  mIdRowMap.insert( fid, n );
216  mRowIdMap.insert( n, fid );
217 
218  endInsertRows();
219 
220  reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
221  }
222 }
223 
224 void QgsAttributeTableModel::updatedFields()
225 {
226  loadAttributes();
227  emit modelChanged();
228 }
229 
230 void QgsAttributeTableModel::editCommandEnded()
231 {
232  reload( createIndex( mChangedCellBounds.top(), mChangedCellBounds.left() ),
233  createIndex( mChangedCellBounds.bottom(), mChangedCellBounds.right() ) );
234 
235  mChangedCellBounds = QRect();
236 }
237 
238 void QgsAttributeTableModel::attributeDeleted( int idx )
239 {
240  if ( mSortCacheAttributes.contains( idx ) )
241  prefetchSortData( "" );
242 }
243 
245 {
246  removeRows( 0, rowCount() );
247 
249  mAttributes.clear();
252 }
253 
255 {
256  QgsDebugMsgLevel( QString( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 3 );
257 
258  if ( mSortCacheAttributes.contains( idx ) )
259  {
260  // if the expression used multiple fields, this will not work but this way we don't have
261  // to run the expensive query in the 80% cases where we just have a simple column for sorting
262  // or it's the first used column, this works just fine
263  mSortCache[fid] = value;
264  }
265  // No filter request: skip all possibly heavy checks
266  if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
267  {
268  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
269  }
270  else
271  {
272  if ( loadFeatureAtId( fid ) )
273  {
274  if ( mFeatureRequest.acceptFeature( mFeat ) )
275  {
276  if ( !mIdRowMap.contains( fid ) )
277  {
278  // Feature changed in such a way, it will be shown now
279  featureAdded( fid );
280  }
281  else
282  {
283  // Update representation
284  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
285  }
286  }
287  else
288  {
289  if ( mIdRowMap.contains( fid ) )
290  {
291  // Feature changed such, that it is no longer shown
292  featuresDeleted( QgsFeatureIds() << fid );
293  }
294  // else: we don't care
295  }
296  }
297  }
298 }
299 
301 {
302  if ( !layer() )
303  {
304  return;
305  }
306 
307  bool ins = false, rm = false;
308 
309  QgsAttributeList attributes;
310  const QgsFields& fields = layer()->fields();
311 
315 
316  for ( int idx = 0; idx < fields.count(); ++idx )
317  {
318  const QString widgetType = layer()->editFormConfig()->widgetType( idx );
319  QgsEditorWidgetFactory* widgetFactory = QgsEditorWidgetRegistry::instance()->factory( widgetType );
320  if ( widgetFactory )
321  {
322  mWidgetFactories.append( widgetFactory );
323  mWidgetConfigs.append( layer()->editFormConfig()->widgetConfig( idx ) );
324  mAttributeWidgetCaches.append( widgetFactory->createCache( layer(), idx, mWidgetConfigs.last() ) );
325 
326  attributes << idx;
327  }
328  }
329 
330  if ( mFieldCount + mExtraColumns < attributes.size() + mExtraColumns )
331  {
332  ins = true;
333  beginInsertColumns( QModelIndex(), mFieldCount + mExtraColumns, attributes.size() - 1 );
334  }
335  else if ( attributes.size() + mExtraColumns < mFieldCount + mExtraColumns )
336  {
337  rm = true;
338  beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount + mExtraColumns - 1 );
339  }
340 
341  mFieldCount = attributes.size();
342  mAttributes = attributes;
343 
344  if ( ins )
345  {
347  }
348  else if ( rm )
349  {
351  }
352 }
353 
355 {
356  // make sure attributes are properly updated before caching the data
357  // (emit of progress() signal may enter event loop and thus attribute
358  // table view may be updated with inconsistent model which may assume
359  // wrong number of attributes)
360  loadAttributes();
361 
362  beginResetModel();
363 
364  if ( rowCount() != 0 )
365  {
366  removeRows( 0, rowCount() );
367  }
368 
369  QgsFeatureIterator features = mLayerCache->getFeatures( mFeatureRequest );
370 
371  int i = 0;
372 
373  QTime t;
374  t.start();
375 
376  QgsFeature feat;
377  while ( features.nextFeature( feat ) )
378  {
379  ++i;
380 
381  if ( t.elapsed() > 1000 )
382  {
383  bool cancel = false;
384  emit progress( i, cancel );
385  if ( cancel )
386  break;
387 
388  t.restart();
389  }
390  mFeat = feat;
391  featureAdded( feat.id() );
392  }
393 
394  emit finished();
395 
396  connect( mLayerCache, SIGNAL( invalidated() ), this, SLOT( loadLayer() ), Qt::UniqueConnection );
397 
398  endResetModel();
399 }
400 
402 {
403  if ( fieldName.isNull() )
404  {
406  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
407  return;
408  }
409 
410  int fieldIndex = mLayerCache->layer()->fieldNameIndex( fieldName );
411  if ( fieldIndex == -1 )
412  return;
413 
414  //whole column has changed
415  int col = fieldCol( fieldIndex );
416  emit dataChanged( index( 0, col ), index( rowCount() - 1, col ) );
417 }
418 
420 {
421  if ( a == b )
422  return;
423 
424  int rowA = idToRow( a );
425  int rowB = idToRow( b );
426 
427  //emit layoutAboutToBeChanged();
428 
429  mRowIdMap.remove( rowA );
430  mRowIdMap.remove( rowB );
431  mRowIdMap.insert( rowA, b );
432  mRowIdMap.insert( rowB, a );
433 
434  mIdRowMap.remove( a );
435  mIdRowMap.remove( b );
436  mIdRowMap.insert( a, rowB );
437  mIdRowMap.insert( b, rowA );
438 
439  //emit layoutChanged();
440 }
441 
443 {
444  if ( !mIdRowMap.contains( id ) )
445  {
446  QgsDebugMsg( QString( "idToRow: id %1 not in the map" ).arg( id ) );
447  return -1;
448  }
449 
450  return mIdRowMap[id];
451 }
452 
454 {
455  return index( idToRow( id ), 0 );
456 }
457 
459 {
460  QModelIndexList indexes;
461 
462  int row = idToRow( id );
463  int columns = columnCount();
464  indexes.reserve( columns );
465  for ( int column = 0; column < columns; ++column )
466  {
467  indexes.append( index( row, column ) );
468  }
469 
470  return indexes;
471 }
472 
474 {
475  if ( !mRowIdMap.contains( row ) )
476  {
477  QgsDebugMsg( QString( "rowToId: row %1 not in the map" ).arg( row ) );
478  // return negative infinite (to avoid collision with newly added features)
480  }
481 
482  return mRowIdMap[row];
483 }
484 
486 {
487  return mAttributes[col];
488 }
489 
491 {
492  return mAttributes.indexOf( idx );
493 }
494 
496 {
497  Q_UNUSED( parent );
498  return mRowIdMap.size();
499 }
500 
502 {
503  Q_UNUSED( parent );
504  return qMax( 1, mFieldCount + mExtraColumns ); // if there are zero columns all model indices will be considered invalid
505 }
506 
507 QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
508 {
509  if ( !layer() )
510  return QVariant();
511 
512  if ( role == Qt::DisplayRole )
513  {
514  if ( orientation == Qt::Vertical ) //row
515  {
516  return QVariant( section );
517  }
518  else if ( section >= 0 && section < mFieldCount )
519  {
520  QString attributeName = layer()->attributeAlias( mAttributes.at( section ) );
521  if ( attributeName.isEmpty() )
522  {
523  QgsField field = layer()->fields().at( mAttributes.at( section ) );
524  attributeName = field.name();
525  }
526  return QVariant( attributeName );
527  }
528  else
529  {
530  return tr( "extra column" );
531  }
532  }
533  else if ( role == Qt::ToolTipRole )
534  {
535  if ( orientation == Qt::Vertical )
536  {
537  // TODO show DisplayExpression
538  return tr( "Feature ID: %1" ).arg( rowToId( section ) );
539  }
540  else
541  {
542  QgsField field = layer()->fields().at( mAttributes.at( section ) );
543  return field.name();
544  }
545  }
546  else
547  {
548  return QVariant();
549  }
550 }
551 
553 {
554  if ( !index.isValid() ||
555  ( role != Qt::TextAlignmentRole
556  && role != Qt::DisplayRole
557  && role != Qt::EditRole
558  && role != SortRole
559  && role != FeatureIdRole
560  && role != FieldIndexRole
561  && role != Qt::BackgroundColorRole
562  && role != Qt::TextColorRole
563  && role != Qt::DecorationRole
564  && role != Qt::FontRole
565  )
566  )
567  return QVariant();
568 
569  QgsFeatureId rowId = rowToId( index.row() );
570 
571  if ( role == FeatureIdRole )
572  return rowId;
573 
574  if ( index.column() >= mFieldCount )
575  return QVariant();
576 
577  int fieldId = mAttributes.at( index.column() );
578 
579  if ( role == FieldIndexRole )
580  return fieldId;
581 
582  if ( role == SortRole )
583  {
584  return mSortCache[rowId];
585  }
586 
587  QgsField field = layer()->fields().at( fieldId );
588 
589  if ( role == Qt::TextAlignmentRole )
590  {
591  return mWidgetFactories.at( index.column() )->alignmentFlag( layer(), fieldId, mWidgetConfigs.at( index.column() ) );
592  }
593 
594  if ( mFeat.id() != rowId || !mFeat.isValid() )
595  {
596  if ( !loadFeatureAtId( rowId ) )
597  return QVariant( "ERROR" );
598 
599  if ( mFeat.id() != rowId )
600  return QVariant( "ERROR" );
601  }
602 
603  QVariant val = mFeat.attribute( fieldId );
604 
605  switch ( role )
606  {
607  case Qt::DisplayRole:
608  return mWidgetFactories.at( index.column() )->representValue( layer(), fieldId, mWidgetConfigs.at( index.column() ),
609  mAttributeWidgetCaches.at( index.column() ), val );
610 
611  case Qt::EditRole:
612  return val;
613 
614  case Qt::BackgroundColorRole:
615  case Qt::TextColorRole:
616  case Qt::DecorationRole:
617  case Qt::FontRole:
618  {
621  if ( mRowStylesMap.contains( index.row() ) )
622  {
623  styles = mRowStylesMap[index.row()];
624  }
625  else
626  {
627  styles = QgsConditionalStyle::matchingConditionalStyles( layer()->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
628  mRowStylesMap.insert( index.row(), styles );
629 
630  }
631 
633  styles = layer()->conditionalStyles()->fieldStyles( field.name() );
635  styles.insert( 0, rowstyle );
637 
638  if ( style.isValid() )
639  {
640  if ( role == Qt::BackgroundColorRole && style.validBackgroundColor() )
641  return style.backgroundColor();
642  if ( role == Qt::TextColorRole && style.validTextColor() )
643  return style.textColor();
644  if ( role == Qt::DecorationRole )
645  return style.icon();
646  if ( role == Qt::FontRole )
647  return style.font();
648  }
649 
650  return QVariant();
651  }
652  }
653 
654  return QVariant();
655 }
656 
657 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
658 {
659  Q_UNUSED( value )
660 
661  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !layer()->isEditable() )
662  return false;
663 
664  if ( !layer()->isModified() )
665  return false;
666 
667  if ( mChangedCellBounds.isNull() )
668  {
669  mChangedCellBounds = QRect( index.column(), index.row(), 1, 1 );
670  }
671  else
672  {
673  if ( index.column() < mChangedCellBounds.left() )
674  {
675  mChangedCellBounds.setLeft( index.column() );
676  }
677  if ( index.row() < mChangedCellBounds.top() )
678  {
679  mChangedCellBounds.setTop( index.row() );
680  }
681  if ( index.column() > mChangedCellBounds.right() )
682  {
683  mChangedCellBounds.setRight( index.column() );
684  }
685  if ( index.row() > mChangedCellBounds.bottom() )
686  {
687  mChangedCellBounds.setBottom( index.row() );
688  }
689  }
690 
691  return true;
692 }
693 
695 {
696  if ( !index.isValid() )
697  return Qt::ItemIsEnabled;
698 
699  if ( index.column() >= mFieldCount )
700  return Qt::NoItemFlags;
701 
703 
704  if ( layer()->isEditable() &&
705  !layer()->editFormConfig()->readOnly( mAttributes[index.column()] ) &&
706  (( layer()->dataProvider() && layer()->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) ||
707  FID_IS_NEW( rowToId( index.row() ) ) ) )
708  flags |= Qt::ItemIsEditable;
709 
710  return flags;
711 }
712 
713 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
714 {
716  emit dataChanged( index1, index2 );
717 }
718 
719 
720 void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
721 {
722  QgsFeature f = feature( idx );
723  layer()->actions()->doAction( action, f, fieldIdx( idx.column() ) );
724 }
725 
727 {
728  QgsFeature f = feature( idx );
729  action->triggerForFeature( layer(), &f );
730 }
731 
733 {
734  QgsFeature f;
736  f.setFeatureId( rowToId( idx.row() ) );
737  for ( int i = 0; i < mAttributes.size(); i++ )
738  {
739  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
740  }
741 
742  return f;
743 }
744 
746 {
747  if ( column == -1 || column >= mAttributes.count() )
748  {
749  prefetchSortData( "" );
750  }
751  else
752  {
754  }
755 }
756 
757 void QgsAttributeTableModel::prefetchSortData( const QString& expressionString )
758 {
759  mSortCache.clear();
760  mSortCacheAttributes.clear();
761 
762  mSortCacheExpression = QgsExpression( expressionString );
763 
764  mSortCacheExpression.prepare( &mExpressionContext );
765 
766  Q_FOREACH ( const QString& col, mSortCacheExpression.referencedColumns() )
767  {
768  mSortCacheAttributes.append( mLayerCache->layer()->fieldNameIndex( col ) );
769  }
770 
771  QgsFeatureRequest request = QgsFeatureRequest( mFeatureRequest )
773  .setSubsetOfAttributes( mSortCacheAttributes );
774  QgsFeatureIterator it = mLayerCache->getFeatures( request );
775 
776  QgsFeature f;
777  while ( it.nextFeature( f ) )
778  {
780  mSortCache.insert( f.id(), mSortCacheExpression.evaluate( &mExpressionContext ) );
781  }
782 }
783 
785 {
786  if ( mSortCacheExpression.rootNode() )
787  return mSortCacheExpression.expression();
788  else
789  return QString();
790 }
791 
793 {
794  mFeatureRequest = request;
795  if ( layer() && !layer()->hasGeometryType() )
796  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
797 }
798 
800 {
801  return mFeatureRequest;
802 }
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.
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsActionManager * actions()
Get all layer actions defined on this layer.
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
QStringList referencedColumns() const
Get list of columns referenced by the expression.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
bool validTextColor() const
Check if the text color is valid for render.
QHash< int, QgsFeatureId > mRowIdMap
Get the field index of this column.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:199
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.
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
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:439
QgsFields fields() const
Returns the list of fields of this layer.
int extraColumns() const
Empty extra columns to announce from this model.
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
T & last()
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:193
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.
QString sortCacheExpression() const
The expression which was used to fill the sorting cache.
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)
const Node * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
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
Get the feature id of the feature in this row.
const char * name() const
void clear()
bool isValid() const
int elapsed() const
int count(const T &value) const
void append(const T &value)
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
void setExtraColumns(int extraColumns)
Empty extra columns to announce from this model.
void doAction(int index, const QgsFeature &feat, int defaultValueIndex=0)
Does the given values.
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 a null 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.
bool contains(const T &value) const
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 T & at(int i) const
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.
qint64 QgsFeatureId
Definition: qgsfeature.h:31
QString expression() const
Return the original, unmodified expression string.
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
void prefetchSortData(const QString &expression)
Prefetches the entire data for one expression.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
typedef ItemFlags