QGIS API Documentation  2.12.0-Lyon
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 ( const QgsFeatureId& fid, fids )
88  {
89  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 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  beginRemoveRows( parent, row, row + count - 1 );
142 #ifdef QGISDEBUG
143  if ( 3 > QgsLogger::debugLevel() )
144  QgsDebugMsgLevel( QString( "remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
145 #endif
146 
147  // clean old references
148  for ( int i = row; i < row + count; i++ )
149  {
150  mFieldCache.remove( mRowIdMap[i] );
151  mIdRowMap.remove( mRowIdMap[ i ] );
152  mRowIdMap.remove( i );
153  }
154 
155  // update maps
156  int n = mRowIdMap.size() + count;
157  for ( int i = row + count; i < n; i++ )
158  {
159  QgsFeatureId id = mRowIdMap[i];
160  mIdRowMap[ id ] -= count;
161  mRowIdMap[ i-count ] = id;
162  mRowIdMap.remove( i );
163  }
164 
165 #ifdef QGISDEBUG
166  if ( 4 > QgsLogger::debugLevel() )
167  {
168  QgsDebugMsgLevel( QString( "after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
169  QgsDebugMsgLevel( "id->row", 4 );
170  for ( QHash<QgsFeatureId, int>::iterator it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
171  QgsDebugMsgLevel( QString( "%1->%2" ).arg( FID_TO_STRING( it.key() ) ).arg( *it ), 4 );
172 
174 
175  QgsDebugMsgLevel( "row->id", 4 );
176  for ( QHash<int, QgsFeatureId>::iterator it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
177  QgsDebugMsgLevel( QString( "%1->%2" ).arg( it.key() ).arg( FID_TO_STRING( *it ) ), 4 );
178  }
179 #endif
180 
181  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
182 
183  endRemoveRows();
184 
185  return true;
186 }
187 
189 {
190  QgsDebugMsgLevel( QString( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
191  bool featOk = true;
192 
193  if ( mFeat.id() != fid )
194  featOk = loadFeatureAtId( fid );
195 
196  if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
197  {
198  mFieldCache[ fid ] = mFeat.attribute( mCachedField );
199 
200  int n = mRowIdMap.size();
201  beginInsertRows( QModelIndex(), n, n );
202 
203  mIdRowMap.insert( fid, n );
204  mRowIdMap.insert( n, fid );
205 
206  endInsertRows();
207 
208  reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
209  }
210 }
211 
212 void QgsAttributeTableModel::updatedFields()
213 {
214  QgsDebugMsg( "entered." );
215  loadAttributes();
216  emit modelChanged();
217 }
218 
219 void QgsAttributeTableModel::editCommandEnded()
220 {
221  reload( createIndex( mChangedCellBounds.top(), mChangedCellBounds.left() ),
222  createIndex( mChangedCellBounds.bottom(), mChangedCellBounds.right() ) );
223 
224  mChangedCellBounds = QRect();
225 }
226 
227 void QgsAttributeTableModel::attributeDeleted( int idx )
228 {
229  if ( idx == mCachedField )
230  {
231  prefetchColumnData( -1 );
232  }
233 }
234 
236 {
237  QgsDebugMsg( "entered." );
238 
239  removeRows( 0, rowCount() );
240 
242  mAttributes.clear();
244  mWidgetConfigs.clear();
245 }
246 
248 {
249  QgsDebugMsgLevel( QString( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 3 );
250 
251  if ( idx == mCachedField )
252  mFieldCache[ fid ] = value;
253 
254  // No filter request: skip all possibly heavy checks
255  if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
256  {
257  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
258  }
259  else
260  {
261  if ( loadFeatureAtId( fid ) )
262  {
263  if ( mFeatureRequest.acceptFeature( mFeat ) )
264  {
265  if ( !mIdRowMap.contains( fid ) )
266  {
267  // Feature changed in such a way, it will be shown now
268  featureAdded( fid );
269  }
270  else
271  {
272  // Update representation
273  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
274  }
275  }
276  else
277  {
278  if ( mIdRowMap.contains( fid ) )
279  {
280  // Feature changed such, that it is no longer shown
281  featuresDeleted( QgsFeatureIds() << fid );
282  }
283  // else: we don't care
284  }
285  }
286  }
287 }
288 
290 {
291  if ( !layer() )
292  {
293  return;
294  }
295 
296  bool ins = false, rm = false;
297 
298  QgsAttributeList attributes;
299  const QgsFields& fields = layer()->fields();
300 
303  mWidgetConfigs.clear();
304 
305  for ( int idx = 0; idx < fields.count(); ++idx )
306  {
307  const QString widgetType = layer()->editorWidgetV2( idx );
308  QgsEditorWidgetFactory* widgetFactory = QgsEditorWidgetRegistry::instance()->factory( widgetType );
309  if ( widgetFactory && widgetType != "Hidden" )
310  {
311  mWidgetFactories.append( widgetFactory );
312  mWidgetConfigs.append( layer()->editorWidgetV2Config( idx ) );
313  mAttributeWidgetCaches.append( widgetFactory->createCache( layer(), idx, mWidgetConfigs.last() ) );
314 
315  attributes << idx;
316  }
317  }
318 
319  if ( mFieldCount < attributes.size() )
320  {
321  ins = true;
322  beginInsertColumns( QModelIndex(), mFieldCount, attributes.size() - 1 );
323  }
324  else if ( attributes.size() < mFieldCount )
325  {
326  rm = true;
327  beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount - 1 );
328  }
329 
330  mFieldCount = attributes.size();
331  mAttributes = attributes;
332 
333  if ( ins )
334  {
336  }
337  else if ( rm )
338  {
340  }
341 }
342 
344 {
345  QgsDebugMsg( "entered." );
346 
347  // make sure attributes are properly updated before caching the data
348  // (emit of progress() signal may enter event loop and thus attribute
349  // table view may be updated with inconsistent model which may assume
350  // wrong number of attributes)
351  loadAttributes();
352 
353  beginResetModel();
354 
355  if ( rowCount() != 0 )
356  {
357  removeRows( 0, rowCount() );
358  }
359 
360  QgsFeatureIterator features = mLayerCache->getFeatures( mFeatureRequest );
361 
362  int i = 0;
363 
364  QTime t;
365  t.start();
366 
367  QgsFeature feat;
368  while ( features.nextFeature( feat ) )
369  {
370  ++i;
371 
372  if ( t.elapsed() > 1000 )
373  {
374  bool cancel = false;
375  emit progress( i, cancel );
376  if ( cancel )
377  break;
378 
379  t.restart();
380  }
381  mFeat = feat;
382  featureAdded( feat.id() );
383  }
384 
385  emit finished();
386 
387  connect( mLayerCache, SIGNAL( invalidated() ), this, SLOT( loadLayer() ), Qt::UniqueConnection );
388 
389  endResetModel();
390 }
391 
393 {
394  if ( fieldName.isNull() )
395  {
397  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
398  return;
399  }
400 
401  int fieldIndex = mLayerCache->layer()->fieldNameIndex( fieldName );
402  if ( fieldIndex == -1 )
403  return;
404 
405  //whole column has changed
406  int col = fieldCol( fieldIndex );
407  emit dataChanged( index( 0, col ), index( rowCount() - 1, col ) );
408 }
409 
411 {
412  if ( a == b )
413  return;
414 
415  int rowA = idToRow( a );
416  int rowB = idToRow( b );
417 
418  //emit layoutAboutToBeChanged();
419 
420  mRowIdMap.remove( rowA );
421  mRowIdMap.remove( rowB );
422  mRowIdMap.insert( rowA, b );
423  mRowIdMap.insert( rowB, a );
424 
425  mIdRowMap.remove( a );
426  mIdRowMap.remove( b );
427  mIdRowMap.insert( a, rowB );
428  mIdRowMap.insert( b, rowA );
429 
430  //emit layoutChanged();
431 }
432 
434 {
435  if ( !mIdRowMap.contains( id ) )
436  {
437  QgsDebugMsg( QString( "idToRow: id %1 not in the map" ).arg( id ) );
438  return -1;
439  }
440 
441  return mIdRowMap[id];
442 }
443 
445 {
446  return index( idToRow( id ), 0 );
447 }
448 
450 {
451  QModelIndexList indexes;
452 
453  int row = idToRow( id );
454  int columns = columnCount();
455  indexes.reserve( columns );
456  for ( int column = 0; column < columns; ++column )
457  {
458  indexes.append( index( row, column ) );
459  }
460 
461  return indexes;
462 }
463 
465 {
466  if ( !mRowIdMap.contains( row ) )
467  {
468  QgsDebugMsg( QString( "rowToId: row %1 not in the map" ).arg( row ) );
469  // return negative infinite (to avoid collision with newly added features)
471  }
472 
473  return mRowIdMap[row];
474 }
475 
477 {
478  return mAttributes[ col ];
479 }
480 
482 {
483  return mAttributes.indexOf( idx );
484 }
485 
487 {
488  Q_UNUSED( parent );
489  return mRowIdMap.size();
490 }
491 
493 {
494  Q_UNUSED( parent );
495  return qMax( 1, mFieldCount ); // if there are zero columns all model indices will be considered invalid
496 }
497 
498 QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
499 {
500  if ( !layer() )
501  return QVariant();
502 
503  if ( role == Qt::DisplayRole )
504  {
505  if ( orientation == Qt::Vertical ) //row
506  {
507  return QVariant( section );
508  }
509  else if ( section >= 0 && section < mFieldCount )
510  {
511  QString attributeName = layer()->attributeAlias( mAttributes[section] );
512  if ( attributeName.isEmpty() )
513  {
514  QgsField field = layer()->fields().at( mAttributes[section] );
515  attributeName = field.name();
516  }
517  return QVariant( attributeName );
518  }
519  else
520  {
521  return tr( "feature id" );
522  }
523  }
524  else
525  {
526  return QVariant();
527  }
528 }
529 
531 {
532  if ( !index.isValid() ||
533  ( role != Qt::TextAlignmentRole
534  && role != Qt::DisplayRole
535  && role != Qt::EditRole
536  && role != SortRole
537  && role != FeatureIdRole
538  && role != FieldIndexRole
539  && role != Qt::BackgroundColorRole
540  && role != Qt::TextColorRole
541  && role != Qt::DecorationRole
542  && role != Qt::FontRole
543  )
544  )
545  return QVariant();
546 
547  QgsFeatureId rowId = rowToId( index.row() );
548 
549  if ( role == FeatureIdRole )
550  return rowId;
551 
552  if ( index.column() >= mFieldCount )
553  return role == Qt::DisplayRole ? rowId : QVariant();
554 
555  int fieldId = mAttributes[ index.column()];
556 
557  if ( role == FieldIndexRole )
558  return fieldId;
559 
560  QgsField field = layer()->fields().at( fieldId );
561 
562  QVariant::Type fldType = field.type();
563  bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
564 
565  if ( role == Qt::TextAlignmentRole )
566  {
567  if ( fldNumeric )
568  return QVariant( Qt::AlignRight );
569  else
570  return QVariant( Qt::AlignLeft );
571  }
572 
573  QVariant val;
574 
575  // if we don't have the row in current cache, load it from layer first
576  if ( mCachedField == fieldId )
577  {
578  val = mFieldCache[ rowId ];
579  }
580  else
581  {
582  if ( mFeat.id() != rowId || !mFeat.isValid() )
583  {
584  if ( !loadFeatureAtId( rowId ) )
585  return QVariant( "ERROR" );
586 
587  if ( mFeat.id() != rowId )
588  return QVariant( "ERROR" );
589  }
590 
591  val = mFeat.attribute( fieldId );
592  }
593 
594  if ( role == Qt::DisplayRole )
595  {
596  return mWidgetFactories[ index.column()]->representValue( layer(), fieldId, mWidgetConfigs[ index.column()], mAttributeWidgetCaches[ index.column()], val );
597  }
598 
599  if ( role == Qt::BackgroundColorRole || role == Qt::TextColorRole || role == Qt::DecorationRole || role == Qt::FontRole )
600  {
603  if ( mRowStylesMap.contains( index.row() ) )
604  {
605  styles = mRowStylesMap[index.row()];
606  }
607  else
608  {
609  styles = QgsConditionalStyle::matchingConditionalStyles( layer()->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
610  mRowStylesMap.insert( index.row(), styles );
611 
612  }
613 
615  styles = layer()->conditionalStyles()->fieldStyles( field.name() );
617  styles.insert( 0, rowstyle );
619 
620  if ( style.isValid() )
621  {
622  if ( role == Qt::BackgroundColorRole && style.validBackgroundColor() )
623  return style.backgroundColor();
624  if ( role == Qt::TextColorRole && style.validTextColor() )
625  return style.textColor();
626  if ( role == Qt::DecorationRole )
627  return style.icon();
628  if ( role == Qt::FontRole )
629  return style.font();
630  }
631 
632  }
633  return val;
634 }
635 
636 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
637 {
638  Q_UNUSED( value )
639 
640  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !layer()->isEditable() )
641  return false;
642 
643  if ( !layer()->isModified() )
644  return false;
645 
646  if ( mChangedCellBounds.isNull() )
647  {
648  mChangedCellBounds = QRect( index.column(), index.row(), 1, 1 );
649  }
650  else
651  {
652  if ( index.column() < mChangedCellBounds.left() )
653  {
654  mChangedCellBounds.setLeft( index.column() );
655  }
656  if ( index.row() < mChangedCellBounds.top() )
657  {
658  mChangedCellBounds.setTop( index.row() );
659  }
660  if ( index.column() > mChangedCellBounds.right() )
661  {
662  mChangedCellBounds.setRight( index.column() );
663  }
664  if ( index.row() > mChangedCellBounds.bottom() )
665  {
666  mChangedCellBounds.setBottom( index.row() );
667  }
668  }
669 
670  return true;
671 }
672 
674 {
675  if ( !index.isValid() )
676  return Qt::ItemIsEnabled;
677 
678  if ( index.column() >= mFieldCount )
679  return Qt::NoItemFlags;
680 
682 
683  if ( layer()->isEditable() &&
684  layer()->fieldEditable( mAttributes[ index.column()] ) &&
685  (( layer()->dataProvider() && layer()->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) ||
686  FID_IS_NEW( rowToId( index.row() ) ) ) )
687  flags |= Qt::ItemIsEditable;
688 
689  return flags;
690 }
691 
692 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
693 {
695  emit dataChanged( index1, index2 );
696 }
697 
698 
699 void QgsAttributeTableModel::executeAction( int action, const QModelIndex &idx ) const
700 {
701  QgsFeature f = feature( idx );
702  layer()->actions()->doAction( action, f, fieldIdx( idx.column() ) );
703 }
704 
706 {
707  QgsFeature f = feature( idx );
708  action->triggerForFeature( layer(), &f );
709 }
710 
712 {
713  QgsFeature f;
715  f.setFeatureId( rowToId( idx.row() ) );
716  for ( int i = 0; i < mAttributes.size(); i++ )
717  {
718  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
719  }
720 
721  return f;
722 }
723 
725 {
726  mFieldCache.clear();
727 
728  if ( column == -1 )
729  {
730  mCachedField = -1;
731  }
732  else
733  {
734  if ( column >= mAttributes.count() )
735  return;
736  int fieldId = mAttributes[ column ];
737  const QgsFields& fields = layer()->fields();
738  QStringList fldNames;
739  fldNames << fields[ fieldId ].name();
740 
741  QgsFeatureRequest r( mFeatureRequest );
743 
744  QgsFeature f;
745  while ( it.nextFeature( f ) )
746  {
747  mFieldCache.insert( f.id(), f.attribute( fieldId ) );
748  }
749 
750  mCachedField = fieldId;
751  }
752 }
753 
755 {
756  mFeatureRequest = request;
757  if ( layer() && !layer()->hasGeometryType() )
758  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
759 }
760 
762 {
763  return mFeatureRequest;
764 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:53
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:72
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
void setBottom(int y)
Allows modification of attribute values.
static unsigned index
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:170
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:422
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.
void reload(const QModelIndex &index1, const QModelIndex &index2)
Reloads the model data between indices.
#define FID_TO_STRING(fid)
Definition: qgsfeature.h:89
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsConditionalLayerStyles * conditionalStyles() const
Return the conditional styles that are set for this layer.
QModelIndex idToIndex(QgsFeatureId id) const
Container of fields for a vector layer.
Definition: qgsfield.h:177
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
Definition: qgsfeature.cpp:194
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:176
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.
void setFeatureId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:83
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:184
const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
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
iterator begin()
Every attribute editor widget needs a factory, which inherits this class.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void beginRemoveColumns(const QModelIndex &parent, int first, int last)
int restart()
QVector< QgsEditorWidgetConfig > mWidgetConfigs
QColor backgroundColor() const
The background color for style.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Remove rows.
int count() const
Return number of items.
Definition: qgsfield.cpp:311
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:40
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:331
virtual void featureAdded(QgsFeatureId fid)
Launched when a feature has been added.
QModelIndex createIndex(int row, int column, void *ptr) const
void clear()
QgsFeature feature(const QModelIndex &idx) const
Return the feature attributes at given model index.
This class caches features of a given QgsVectorLayer.
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
Definition: qgslogger.h:93
void progress(int i, bool &cancel)
void beginInsertRows(const QModelIndex &parent, int first, int last)
void modelChanged()
Model has been changed.
bool isNull() const
void setRight(int x)
QVector< QVariant > mAttributeWidgetCaches
No filter is applied.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:238
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.
iterator end()
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void swapRows(QgsFeatureId a, QgsFeatureId b)
Swaps two rows.
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void setLeft(int x)
void beginInsertColumns(const QModelIndex &parent, int first, int last)
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Updates data on given index.
void triggerForFeature(QgsMapLayer *layer, const QgsFeature *feature)
Triggers the action with the specified layer and feature.
QgsAttributeTableModel(QgsVectorLayerCache *layerCache, QObject *parent=0)
Constructor.
An action which can run on map layers.
void prefetchColumnData(int column)
Caches the entire data for one column.
QHash< int, QList< QgsConditionalStyle > > mRowStylesMap
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:77
typedef ItemFlags