QGIS API Documentation  2.14.11-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.at( 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 == SortRole )
597  {
598  return val;
599  }
600 
601  switch ( role )
602  {
603  case Qt::DisplayRole:
604  return mWidgetFactories.at( index.column() )->representValue( layer(), fieldId, mWidgetConfigs.at( index.column() ),
605  mAttributeWidgetCaches.at( index.column() ), val );
606 
607  case Qt::EditRole:
608  return val;
609 
610  case Qt::BackgroundColorRole:
611  case Qt::TextColorRole:
612  case Qt::DecorationRole:
613  case Qt::FontRole:
614  {
617  if ( mRowStylesMap.contains( index.row() ) )
618  {
619  styles = mRowStylesMap[index.row()];
620  }
621  else
622  {
623  styles = QgsConditionalStyle::matchingConditionalStyles( layer()->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
624  mRowStylesMap.insert( index.row(), styles );
625 
626  }
627 
629  styles = layer()->conditionalStyles()->fieldStyles( field.name() );
631  styles.insert( 0, rowstyle );
633 
634  if ( style.isValid() )
635  {
636  if ( role == Qt::BackgroundColorRole && style.validBackgroundColor() )
637  return style.backgroundColor();
638  if ( role == Qt::TextColorRole && style.validTextColor() )
639  return style.textColor();
640  if ( role == Qt::DecorationRole )
641  return style.icon();
642  if ( role == Qt::FontRole )
643  return style.font();
644  }
645 
646  return QVariant();
647  }
648  }
649 
650  return QVariant();
651 }
652 
653 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
654 {
655  Q_UNUSED( value )
656 
657  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !layer()->isEditable() )
658  return false;
659 
660  if ( !layer()->isModified() )
661  return false;
662 
663  if ( mChangedCellBounds.isNull() )
664  {
665  mChangedCellBounds = QRect( index.column(), index.row(), 1, 1 );
666  }
667  else
668  {
669  if ( index.column() < mChangedCellBounds.left() )
670  {
671  mChangedCellBounds.setLeft( index.column() );
672  }
673  if ( index.row() < mChangedCellBounds.top() )
674  {
675  mChangedCellBounds.setTop( index.row() );
676  }
677  if ( index.column() > mChangedCellBounds.right() )
678  {
679  mChangedCellBounds.setRight( index.column() );
680  }
681  if ( index.row() > mChangedCellBounds.bottom() )
682  {
683  mChangedCellBounds.setBottom( index.row() );
684  }
685  }
686 
687  return true;
688 }
689 
691 {
692  if ( !index.isValid() )
693  return Qt::ItemIsEnabled;
694 
695  if ( index.column() >= mFieldCount )
696  return Qt::NoItemFlags;
697 
699 
700  if ( layer()->isEditable() &&
701  !layer()->editFormConfig()->readOnly( mAttributes[index.column()] ) &&
702  (( layer()->dataProvider() && layer()->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) ||
703  FID_IS_NEW( rowToId( index.row() ) ) ) )
704  flags |= Qt::ItemIsEditable;
705 
706  return flags;
707 }
708 
709 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
710 {
712  emit dataChanged( index1, index2 );
713 }
714 
715 
716 void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
717 {
718  QgsFeature f = feature( idx );
719  layer()->actions()->doAction( action, f, fieldIdx( idx.column() ) );
720 }
721 
723 {
724  QgsFeature f = feature( idx );
725  action->triggerForFeature( layer(), &f );
726 }
727 
729 {
730  QgsFeature f;
732  f.setFeatureId( rowToId( idx.row() ) );
733  for ( int i = 0; i < mAttributes.size(); i++ )
734  {
735  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
736  }
737 
738  return f;
739 }
740 
742 {
743  mFieldCache.clear();
744 
745  if ( column == -1 )
746  {
747  mCachedField = -1;
748  }
749  else
750  {
751  if ( column >= mAttributes.count() )
752  return;
753  int fieldId = mAttributes.at( column );
754  const QgsFields& fields = layer()->fields();
755  QStringList fldNames;
756  fldNames << fields[fieldId].name();
757 
758  QgsFeatureRequest r( mFeatureRequest );
760 
761  QgsFeature f;
762  while ( it.nextFeature( f ) )
763  {
764  mFieldCache.insert( f.id(), f.attribute( fieldId ) );
765  }
766 
767  mCachedField = fieldId;
768  }
769 }
770 
772 {
773  mFeatureRequest = request;
774  if ( layer() && !layer()->hasGeometryType() )
775  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
776 }
777 
779 {
780  return mFeatureRequest;
781 }
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:199
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)
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
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)
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
const Flags & flags() const
QHash< int, QgsFeatureId > mRowIdMap
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
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
virtual void layerDeleted()
Launched when layer has been deleted.
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.
FilterType filterType() const
Return the filter type which is currently set on this request.
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
bool validBackgroundColor() const
Check if the background color is valid for render.
QPixmap icon() const
The icon set for style generated from the set symbol.
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.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
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...
int count() const
Return number of items.
Definition: qgsfield.cpp:365
QString tr(const char *sourceText, const char *disambiguation, int n)
void resetModel()
Resets the model.
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:84
virtual QVariant createCache(QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config)
Create a cache for a given field.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:385
QgsVectorLayerCache * mLayerCache
int size() const
bool isNull() const
QModelIndex idToIndex(QgsFeatureId id) const
QgsEditFormConfig * editFormConfig() const
Get the configuration of the form used to represent this vector layer.
QgsFields fields() const
Returns the list of fields of this layer.
QgsConditionalLayerStyles * conditionalStyles() const
Return the conditional styles that are set for this layer.
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
QgsFeature feature(const QModelIndex &idx) const
Return the feature attributes at given model index.
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...
Conditional styling for a rule.
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
bool isValid() const
isValid Check if this rule is valid.
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)
QColor backgroundColor() const
The background color for style.
int restart()
QVector< QgsEditorWidgetConfig > mWidgetConfigs
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Remove rows.
QHash< QgsFeatureId, int > mIdRowMap
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.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
const QgsFeatureRequest & request() const
Get the the feature request.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
int remove(const Key &key)
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()
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
QModelIndexList idToIndexList(QgsFeatureId id) const
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 T & at(int i) const
const_iterator constBegin() const
QColor textColor() const
The text color set for style.
QgsAttributeTableModel(QgsVectorLayerCache *layerCache, QObject *parent=nullptr)
Constructor.
int fieldCol(int idx) const
get column from field index
No filter is applied.
int fieldIdx(int col) const
get field index from column
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
void insert(int i, const T &value)
bool featureAtId(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id.
bool validTextColor() const
Check if the text color is valid for render.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
void executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx) const
Execute a QgsMapLayerAction.
int bottom() const
virtual void loadAttributes()
Gets mFieldCount, mAttributes and mValueMaps.
int column() const
void doAction(int index, const QgsFeature &feat, int defaultValueIndex=0)
Does the given values.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
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
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
QFont font() const
The font for the style.
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)
QString widgetType(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
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
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:89
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
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)
int idToRow(QgsFeatureId id) const
Maps feature id to table row.
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
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QString attributeAlias(int attributeIndex) const
Returns the alias of an attribute name or an empty string if there is no alias.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
typedef ItemFlags