QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 "qgseditorwidgetfactory.h"
23 #include "qgsexpression.h"
24 #include "qgsfeatureiterator.h"
25 #include "qgsconditionalstyle.h"
26 #include "qgsfields.h"
27 #include "qgsfieldformatter.h"
28 #include "qgslogger.h"
29 #include "qgsmapcanvas.h"
31 #include "qgsrenderer.h"
32 #include "qgsvectorlayer.h"
33 #include "qgsvectordataprovider.h"
34 #include "qgssymbollayerutils.h"
36 #include "qgsgui.h"
37 #include "qgsexpressionnodeimpl.h"
38 #include "qgsvectorlayerjoininfo.h"
40 #include "qgsfieldmodel.h"
43 #include "qgsstringutils.h"
44 #include "qgsvectorlayerutils.h"
45 #include "qgsvectorlayercache.h"
46 
47 #include <QVariant>
48 #include <QUuid>
49 
50 #include <limits>
51 
53  : QAbstractTableModel( parent )
54  , mLayer( layerCache->layer() )
55  , mLayerCache( layerCache )
56 {
58 
59  if ( mLayer->geometryType() == QgsWkbTypes::NullGeometry )
60  {
61  mFeatureRequest.setFlags( QgsFeatureRequest::NoGeometry );
62  }
63 
64  mFeat.setId( std::numeric_limits<int>::min() );
65 
66  if ( !mLayer->isSpatial() )
67  mFeatureRequest.setFlags( QgsFeatureRequest::NoGeometry );
68 
69  loadAttributes();
70 
71  connect( mLayer, &QgsVectorLayer::featuresDeleted, this, &QgsAttributeTableModel::featuresDeleted );
72  connect( mLayer, &QgsVectorLayer::attributeDeleted, this, &QgsAttributeTableModel::attributeDeleted );
73  connect( mLayer, &QgsVectorLayer::updatedFields, this, &QgsAttributeTableModel::updatedFields );
74 
75  connect( mLayer, &QgsVectorLayer::editCommandStarted, this, &QgsAttributeTableModel::bulkEditCommandStarted );
76  connect( mLayer, &QgsVectorLayer::beforeRollBack, this, &QgsAttributeTableModel::bulkEditCommandStarted );
77  connect( mLayer, &QgsVectorLayer::afterRollBack, this, [ = ]
78  {
79  mIsCleaningUpAfterRollback = true;
80  bulkEditCommandEnded();
81  mIsCleaningUpAfterRollback = false;
82  } );
83 
84  connect( mLayer, &QgsVectorLayer::editCommandEnded, this, &QgsAttributeTableModel::editCommandEnded );
85  connect( mLayerCache, &QgsVectorLayerCache::attributeValueChanged, this, &QgsAttributeTableModel::attributeValueChanged );
86  connect( mLayerCache, &QgsVectorLayerCache::featureAdded, this, [ = ]( QgsFeatureId id ) { featureAdded( id ); } );
87  connect( mLayerCache, &QgsVectorLayerCache::cachedLayerDeleted, this, &QgsAttributeTableModel::layerDeleted );
88 }
89 
90 bool QgsAttributeTableModel::loadFeatureAtId( QgsFeatureId fid ) const
91 {
92  QgsDebugMsgLevel( QStringLiteral( "loading feature %1" ).arg( fid ), 3 );
93 
94  if ( fid == std::numeric_limits<int>::min() )
95  {
96  return false;
97  }
98 
99  return mLayerCache->featureAtId( fid, mFeat );
100 }
101 
103 {
104  return mExtraColumns;
105 }
106 
108 {
109  mExtraColumns = extraColumns;
110  loadAttributes();
111 }
112 
113 void QgsAttributeTableModel::featuresDeleted( const QgsFeatureIds &fids )
114 {
115  QList<int> rows;
116 
117  const auto constFids = fids;
118  for ( const QgsFeatureId fid : constFids )
119  {
120  QgsDebugMsgLevel( QStringLiteral( "(%2) fid: %1, size: %3" ).arg( fid ).arg( mFeatureRequest.filterType() ).arg( mIdRowMap.size() ), 4 );
121 
122  const int row = idToRow( fid );
123  if ( row != -1 )
124  rows << row;
125  }
126 
127  std::sort( rows.begin(), rows.end() );
128 
129  int lastRow = -1;
130  int beginRow = -1;
131  int currentRowCount = 0;
132  int removedRows = 0;
133  bool reset = false;
134 
135  const auto constRows = rows;
136  for ( const int row : constRows )
137  {
138 #if 0
139  qDebug() << "Row: " << row << ", begin " << beginRow << ", last " << lastRow << ", current " << currentRowCount << ", removed " << removedRows;
140 #endif
141  if ( lastRow == -1 )
142  {
143  beginRow = row;
144  }
145 
146  if ( row != lastRow + 1 && lastRow != -1 )
147  {
148  if ( rows.count() > 100 && currentRowCount < 10 )
149  {
150  reset = true;
151  break;
152  }
153  removeRows( beginRow - removedRows, currentRowCount );
154 
155  beginRow = row;
156  removedRows += currentRowCount;
157  currentRowCount = 0;
158  }
159 
160  currentRowCount++;
161 
162  lastRow = row;
163  }
164 
165  if ( !reset )
166  removeRows( beginRow - removedRows, currentRowCount );
167  else
168  resetModel();
169 }
170 
171 bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &parent )
172 {
173 
174  if ( row < 0 || count < 1 )
175  return false;
176 
177  if ( !mResettingModel )
178  {
179  beginRemoveRows( parent, row, row + count - 1 );
180  }
181 
182 #ifdef QGISDEBUG
183  if ( 3 <= QgsLogger::debugLevel() )
184  QgsDebugMsgLevel( QStringLiteral( "remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
185 #endif
186 
187  if ( mBulkEditCommandRunning && !mResettingModel )
188  {
189  for ( int i = row; i < row + count; i++ )
190  {
191  const QgsFeatureId fid { rowToId( row ) };
192  mInsertedRowsChanges.removeOne( fid );
193  }
194  }
195 
196  // clean old references
197  for ( int i = row; i < row + count; i++ )
198  {
199  for ( SortCache &cache : mSortCaches )
200  cache.sortCache.remove( mRowIdMap[i] );
201  mIdRowMap.remove( mRowIdMap[i] );
202  mRowIdMap.remove( i );
203  }
204 
205  // update maps
206  const int n = mRowIdMap.size() + count;
207  for ( int i = row + count; i < n; i++ )
208  {
209  const QgsFeatureId id = mRowIdMap[i];
210  mIdRowMap[id] -= count;
211  mRowIdMap[i - count] = id;
212  mRowIdMap.remove( i );
213  }
214 
215 #ifdef QGISDEBUG
216  if ( 4 <= QgsLogger::debugLevel() )
217  {
218  QgsDebugMsgLevel( QStringLiteral( "after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
219  QgsDebugMsgLevel( QStringLiteral( "id->row" ), 4 );
220  for ( QHash<QgsFeatureId, int>::const_iterator it = mIdRowMap.constBegin(); it != mIdRowMap.constEnd(); ++it )
221  QgsDebugMsgLevel( QStringLiteral( "%1->%2" ).arg( FID_TO_STRING( it.key() ) ).arg( *it ), 4 );
222 
223  QgsDebugMsgLevel( QStringLiteral( "row->id" ), 4 );
224  for ( QHash<int, QgsFeatureId>::const_iterator it = mRowIdMap.constBegin(); it != mRowIdMap.constEnd(); ++it )
225  QgsDebugMsgLevel( QStringLiteral( "%1->%2" ).arg( it.key() ).arg( FID_TO_STRING( *it ) ), 4 );
226  }
227 #endif
228 
229  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
230 
231  if ( !mResettingModel )
232  endRemoveRows();
233 
234  return true;
235 }
236 
237 void QgsAttributeTableModel::featureAdded( QgsFeatureId fid )
238 {
239  QgsDebugMsgLevel( QStringLiteral( "(%2) fid: %1" ).arg( fid ).arg( mFeatureRequest.filterType() ), 4 );
240  bool featOk = true;
241 
242  if ( mFeat.id() != fid )
243  featOk = loadFeatureAtId( fid );
244 
245  if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
246  {
247  for ( SortCache &cache : mSortCaches )
248  {
249  if ( cache.sortFieldIndex >= 0 )
250  {
251  QgsFieldFormatter *fieldFormatter = mFieldFormatters.at( cache.sortFieldIndex );
252  const QVariant &widgetCache = mAttributeWidgetCaches.at( cache.sortFieldIndex );
253  const QVariantMap &widgetConfig = mWidgetConfigs.at( cache.sortFieldIndex );
254  const QVariant sortValue = fieldFormatter->sortValue( mLayer, cache.sortFieldIndex, widgetConfig, widgetCache, mFeat.attribute( cache.sortFieldIndex ) );
255  cache.sortCache.insert( mFeat.id(), sortValue );
256  }
257  else if ( cache.sortCacheExpression.isValid() )
258  {
259  mExpressionContext.setFeature( mFeat );
260  cache.sortCache[mFeat.id()] = cache.sortCacheExpression.evaluate( &mExpressionContext );
261  }
262  }
263 
264  // Skip if the fid is already in the map (do not add twice)!
265  if ( ! mIdRowMap.contains( fid ) )
266  {
267  const int n = mRowIdMap.size();
268  if ( !mResettingModel )
269  beginInsertRows( QModelIndex(), n, n );
270  mIdRowMap.insert( fid, n );
271  mRowIdMap.insert( n, fid );
272  if ( !mResettingModel )
273  endInsertRows();
274  reload( index( rowCount() - 1, 0 ), index( rowCount() - 1, columnCount() ) );
275  if ( mBulkEditCommandRunning && !mResettingModel )
276  {
277  mInsertedRowsChanges.append( fid );
278  }
279  }
280  }
281 }
282 
283 void QgsAttributeTableModel::updatedFields()
284 {
285  loadAttributes();
286  emit modelChanged();
287 }
288 
289 void QgsAttributeTableModel::editCommandEnded()
290 {
291  // do not do reload(...) due would trigger (dataChanged) row sort
292  // giving issue: https://github.com/qgis/QGIS/issues/23892
293  bulkEditCommandEnded( );
294 }
295 
296 void QgsAttributeTableModel::attributeDeleted( int idx )
297 {
298  int cacheIndex = 0;
299  for ( const SortCache &cache : mSortCaches )
300  {
301  if ( cache.sortCacheAttributes.contains( idx ) )
302  {
303  prefetchSortData( QString(), cacheIndex );
304  }
305  cacheIndex++;
306  }
307 }
308 
309 void QgsAttributeTableModel::layerDeleted()
310 {
311  mLayerCache = nullptr;
312  mLayer = nullptr;
313  removeRows( 0, rowCount() );
314 
315  mAttributeWidgetCaches.clear();
316  mAttributes.clear();
317  mWidgetFactories.clear();
318  mWidgetConfigs.clear();
319  mFieldFormatters.clear();
320 }
321 
322 void QgsAttributeTableModel::fieldFormatterRemoved( QgsFieldFormatter *fieldFormatter )
323 {
324  for ( int i = 0; i < mFieldFormatters.size(); ++i )
325  {
326  if ( mFieldFormatters.at( i ) == fieldFormatter )
328  }
329 }
330 
331 void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
332 {
333  // Defer all updates if a bulk edit/rollback command is running
334  if ( mBulkEditCommandRunning )
335  {
336  mAttributeValueChanges.insert( QPair<QgsFeatureId, int>( fid, idx ), value );
337  return;
338  }
339  QgsDebugMsgLevel( QStringLiteral( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 2 );
340 
341  for ( SortCache &cache : mSortCaches )
342  {
343  if ( cache.sortCacheAttributes.contains( idx ) )
344  {
345  if ( cache.sortFieldIndex == -1 )
346  {
347  if ( loadFeatureAtId( fid ) )
348  {
349  mExpressionContext.setFeature( mFeat );
350  cache.sortCache[fid] = cache.sortCacheExpression.evaluate( &mExpressionContext );
351  }
352  }
353  else
354  {
355  QgsFieldFormatter *fieldFormatter = mFieldFormatters.at( cache.sortFieldIndex );
356  const QVariant &widgetCache = mAttributeWidgetCaches.at( cache.sortFieldIndex );
357  const QVariantMap &widgetConfig = mWidgetConfigs.at( cache.sortFieldIndex );
358  const QVariant sortValue = fieldFormatter->representValue( mLayer, cache.sortFieldIndex, widgetConfig, widgetCache, value );
359  cache.sortCache.insert( fid, sortValue );
360  }
361  }
362  }
363  // No filter request: skip all possibly heavy checks
364  if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
365  {
366  if ( loadFeatureAtId( fid ) )
367  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
368  }
369  else
370  {
371  if ( loadFeatureAtId( fid ) )
372  {
373  if ( mFeatureRequest.acceptFeature( mFeat ) )
374  {
375  if ( !mIdRowMap.contains( fid ) )
376  {
377  // Feature changed in such a way, it will be shown now
378  featureAdded( fid );
379  }
380  else
381  {
382  // Update representation
383  setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
384  }
385  }
386  else
387  {
388  if ( mIdRowMap.contains( fid ) )
389  {
390  // Feature changed such, that it is no longer shown
391  featuresDeleted( QgsFeatureIds() << fid );
392  }
393  // else: we don't care
394  }
395  }
396  }
397 }
398 
399 void QgsAttributeTableModel::loadAttributes()
400 {
401  if ( !mLayer )
402  {
403  return;
404  }
405 
406  bool ins = false, rm = false;
407 
408  QgsAttributeList attributes;
409  const QgsFields &fields = mLayer->fields();
410 
411  mWidgetFactories.clear();
412  mAttributeWidgetCaches.clear();
413  mWidgetConfigs.clear();
414  mFieldFormatters.clear();
415 
416  for ( int idx = 0; idx < fields.count(); ++idx )
417  {
418  const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( mLayer, fields[idx].name() );
419  QgsEditorWidgetFactory *widgetFactory = QgsGui::editorWidgetRegistry()->factory( setup.type() );
421 
422  mWidgetFactories.append( widgetFactory );
423  mWidgetConfigs.append( setup.config() );
424  mAttributeWidgetCaches.append( fieldFormatter->createCache( mLayer, idx, setup.config() ) );
425  mFieldFormatters.append( fieldFormatter );
426 
427  attributes << idx;
428  }
429 
430  if ( mFieldCount + mExtraColumns < attributes.size() + mExtraColumns )
431  {
432  ins = true;
433  beginInsertColumns( QModelIndex(), mFieldCount + mExtraColumns, attributes.size() - 1 );
434  }
435  else if ( attributes.size() + mExtraColumns < mFieldCount + mExtraColumns )
436  {
437  rm = true;
438  beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount + mExtraColumns - 1 );
439  }
440 
441  mFieldCount = attributes.size();
442  mAttributes = attributes;
443 
444  for ( SortCache &cache : mSortCaches )
445  {
446  if ( cache.sortFieldIndex >= mAttributes.count() )
447  cache.sortFieldIndex = -1;
448  }
449 
450  if ( ins )
451  {
452  endInsertColumns();
453  }
454  else if ( rm )
455  {
456  endRemoveColumns();
457  }
458 }
459 
461 {
462  // make sure attributes are properly updated before caching the data
463  // (emit of progress() signal may enter event loop and thus attribute
464  // table view may be updated with inconsistent model which may assume
465  // wrong number of attributes)
466 
467  loadAttributes();
468 
469  mResettingModel = true;
470  beginResetModel();
471 
472  if ( rowCount() != 0 )
473  {
474  removeRows( 0, rowCount() );
475  }
476 
477  // Layer might have been deleted and cache set to nullptr!
478  if ( mLayerCache )
479  {
480  QgsFeatureIterator features = mLayerCache->getFeatures( mFeatureRequest );
481 
482  int i = 0;
483 
484  QElapsedTimer t;
485  t.start();
486 
487  while ( features.nextFeature( mFeat ) )
488  {
489  ++i;
490 
491  if ( t.elapsed() > 1000 )
492  {
493  bool cancel = false;
494  emit progress( i, cancel );
495  if ( cancel )
496  break;
497 
498  t.restart();
499  }
500  featureAdded( mFeat.id() );
501  }
502 
503  emit finished();
504  connect( mLayerCache, &QgsVectorLayerCache::invalidated, this, &QgsAttributeTableModel::loadLayer, Qt::UniqueConnection );
505  }
506 
507  endResetModel();
508 
509  mResettingModel = false;
510 }
511 
512 
514 {
515  if ( fieldName.isNull() )
516  {
517  mRowStylesMap.clear();
518  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
519  return;
520  }
521 
522  const int fieldIndex = mLayer->fields().lookupField( fieldName );
523  if ( fieldIndex == -1 )
524  return;
525 
526  //whole column has changed
527  const int col = fieldCol( fieldIndex );
528  emit dataChanged( index( 0, col ), index( rowCount() - 1, col ) );
529 }
530 
532 {
533  if ( a == b )
534  return;
535 
536  const int rowA = idToRow( a );
537  const int rowB = idToRow( b );
538 
539  //emit layoutAboutToBeChanged();
540 
541  mRowIdMap.remove( rowA );
542  mRowIdMap.remove( rowB );
543  mRowIdMap.insert( rowA, b );
544  mRowIdMap.insert( rowB, a );
545 
546  mIdRowMap.remove( a );
547  mIdRowMap.remove( b );
548  mIdRowMap.insert( a, rowB );
549  mIdRowMap.insert( b, rowA );
550  Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
551 
552 
553  //emit layoutChanged();
554 }
555 
557 {
558  if ( !mIdRowMap.contains( id ) )
559  {
560  QgsDebugMsg( QStringLiteral( "idToRow: id %1 not in the map" ).arg( id ) );
561  return -1;
562  }
563 
564  return mIdRowMap[id];
565 }
566 
568 {
569  return index( idToRow( id ), 0 );
570 }
571 
573 {
574  QModelIndexList indexes;
575 
576  const int row = idToRow( id );
577  const int columns = columnCount();
578  indexes.reserve( columns );
579  for ( int column = 0; column < columns; ++column )
580  {
581  indexes.append( index( row, column ) );
582  }
583 
584  return indexes;
585 }
586 
588 {
589  if ( !mRowIdMap.contains( row ) )
590  {
591  QgsDebugMsg( QStringLiteral( "rowToId: row %1 not in the map" ).arg( row ) );
592  // return negative infinite (to avoid collision with newly added features)
593  return std::numeric_limits<int>::min();
594  }
595 
596  return mRowIdMap[row];
597 }
598 
600 {
601  return mAttributes[col];
602 }
603 
605 {
606  return mAttributes.indexOf( idx );
607 }
608 
609 int QgsAttributeTableModel::rowCount( const QModelIndex &parent ) const
610 {
611  Q_UNUSED( parent )
612  return mRowIdMap.size();
613 }
614 
615 int QgsAttributeTableModel::columnCount( const QModelIndex &parent ) const
616 {
617  Q_UNUSED( parent )
618  return std::max( 1, mFieldCount + mExtraColumns ); // if there are zero columns all model indices will be considered invalid
619 }
620 
621 QVariant QgsAttributeTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
622 {
623  if ( !mLayer )
624  return QVariant();
625 
626  if ( role == Qt::DisplayRole )
627  {
628  if ( orientation == Qt::Vertical ) //row
629  {
630  return QVariant( section );
631  }
632  else if ( section >= 0 && section < mFieldCount )
633  {
634  const QString attributeName = mLayer->fields().at( mAttributes.at( section ) ).displayName();
635  return QVariant( attributeName );
636  }
637  else
638  {
639  return tr( "extra column" );
640  }
641  }
642  else if ( role == Qt::ToolTipRole )
643  {
644  if ( orientation == Qt::Vertical )
645  {
646  // TODO show DisplayExpression
647  return tr( "Feature ID: %1" ).arg( rowToId( section ) );
648  }
649  else
650  {
651  const QgsField field = mLayer->fields().at( mAttributes.at( section ) );
652  return QgsFieldModel::fieldToolTipExtended( field, mLayer );
653  }
654  }
655  else
656  {
657  return QVariant();
658  }
659 }
660 
661 QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) const
662 {
663  if ( !index.isValid() || !mLayer ||
664  ( role != Qt::TextAlignmentRole
665  && role != Qt::DisplayRole
666  && role != Qt::ToolTipRole
667  && role != Qt::EditRole
668  && role != FeatureIdRole
669  && role != FieldIndexRole
670 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
671  && role != Qt::BackgroundColorRole
672  && role != Qt::TextColorRole
673 #else
674  && role != Qt::BackgroundRole
675  && role != Qt::ForegroundRole
676 #endif
677  && role != Qt::DecorationRole
678  && role != Qt::FontRole
679  && role < SortRole
680  )
681  )
682  return QVariant();
683 
684  const QgsFeatureId rowId = rowToId( index.row() );
685 
686  if ( role == FeatureIdRole )
687  return rowId;
688 
689  if ( index.column() >= mFieldCount )
690  return QVariant();
691 
692  const int fieldId = mAttributes.at( index.column() );
693 
694  if ( role == FieldIndexRole )
695  return fieldId;
696 
697  if ( role >= SortRole )
698  {
699  const unsigned long cacheIndex = role - SortRole;
700  if ( cacheIndex < mSortCaches.size() )
701  return mSortCaches.at( cacheIndex ).sortCache.value( rowId );
702  else
703  return QVariant();
704  }
705 
706  const QgsField field = mLayer->fields().at( fieldId );
707 
708  if ( role == Qt::TextAlignmentRole )
709  {
710  return static_cast<Qt::Alignment::Int>( mFieldFormatters.at( index.column() )->alignmentFlag( mLayer, fieldId, mWidgetConfigs.at( index.column() ) ) | Qt::AlignVCenter );
711  }
712 
713  if ( mFeat.id() != rowId || !mFeat.isValid() )
714  {
715  if ( !loadFeatureAtId( rowId ) )
716  return QVariant( "ERROR" );
717 
718  if ( mFeat.id() != rowId )
719  return QVariant( "ERROR" );
720  }
721 
722  QVariant val = mFeat.attribute( fieldId );
723 
724  switch ( role )
725  {
726  case Qt::DisplayRole:
727  return mFieldFormatters.at( index.column() )->representValue( mLayer,
728  fieldId,
729  mWidgetConfigs.at( index.column() ),
730  mAttributeWidgetCaches.at( index.column() ),
731  val );
732  case Qt::ToolTipRole:
733  {
734  QString tooltip = mFieldFormatters.at( index.column() )->representValue( mLayer,
735  fieldId,
736  mWidgetConfigs.at( index.column() ),
737  mAttributeWidgetCaches.at( index.column() ),
738  val );
739  if ( val.type() == QVariant::String && QgsStringUtils::isUrl( val.toString() ) )
740  {
741  tooltip = tr( "%1 (Ctrl+click to open)" ).arg( tooltip );
742  }
743  return tooltip;
744  }
745  case Qt::EditRole:
746  return val;
747 
748  case Qt::BackgroundRole:
749 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
750  case Qt::TextColorRole:
751 #else
752  case Qt::ForegroundRole:
753 #endif
754  case Qt::DecorationRole:
755  case Qt::FontRole:
756  {
757  mExpressionContext.setFeature( mFeat );
758  QList<QgsConditionalStyle> styles;
759  if ( mRowStylesMap.contains( mFeat.id() ) )
760  {
761  styles = mRowStylesMap[mFeat.id()];
762  }
763  else
764  {
765  styles = QgsConditionalStyle::matchingConditionalStyles( mLayer->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
766  mRowStylesMap.insert( mFeat.id(), styles );
767  }
768 
769  const QgsConditionalStyle rowstyle = QgsConditionalStyle::compressStyles( styles );
770  styles = mLayer->conditionalStyles()->fieldStyles( field.name() );
771  styles = QgsConditionalStyle::matchingConditionalStyles( styles, val, mExpressionContext );
772  styles.insert( 0, rowstyle );
774 
775  if ( style.isValid() )
776  {
777  if ( role == Qt::BackgroundRole && style.validBackgroundColor() )
778  return style.backgroundColor();
779 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
780  if ( role == Qt::TextColorRole && style.validTextColor() )
781 #else
782  if ( role == Qt::ForegroundRole )
783 #endif
784  return style.textColor();
785  if ( role == Qt::DecorationRole )
786  return style.icon();
787  if ( role == Qt::FontRole )
788  return style.font();
789  }
790  else if ( val.type() == QVariant::String && QgsStringUtils::isUrl( val.toString() ) )
791  {
792  if ( role == Qt::ForegroundRole )
793  {
794  return QColor( Qt::blue );
795  }
796  else if ( role == Qt::FontRole )
797  {
798  QFont font;
799  font.setUnderline( true );
800  return font;
801  }
802  }
803 
804  return QVariant();
805  }
806  }
807 
808  return QVariant();
809 }
810 
811 bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
812 {
813  Q_UNUSED( value )
814 
815  if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !mLayer->isEditable() )
816  return false;
817 
818  mRowStylesMap.remove( mFeat.id() );
819 
820  if ( !mLayer->isModified() )
821  return false;
822 
823  return true;
824 }
825 
826 Qt::ItemFlags QgsAttributeTableModel::flags( const QModelIndex &index ) const
827 {
828  if ( !index.isValid() )
829  return Qt::ItemIsEnabled;
830 
831  if ( index.column() >= mFieldCount || !mLayer )
832  return Qt::NoItemFlags;
833 
834  Qt::ItemFlags flags = QAbstractTableModel::flags( index );
835 
836  const int fieldIndex = mAttributes[index.column()];
837  const QgsFeatureId fid = rowToId( index.row() );
838 
839  if ( QgsVectorLayerUtils::fieldIsEditable( mLayer, fieldIndex, fid ) )
840  flags |= Qt::ItemIsEditable;
841 
842  return flags;
843 }
844 
845 void QgsAttributeTableModel::bulkEditCommandStarted()
846 {
847  mBulkEditCommandRunning = true;
848  mAttributeValueChanges.clear();
849 }
850 
851 void QgsAttributeTableModel::bulkEditCommandEnded()
852 {
853  mBulkEditCommandRunning = false;
854  // Full model update if the changed rows are more than half the total rows
855  // or if their count is > layer cache size
856  const int changeCount( std::max( mAttributeValueChanges.count(), mInsertedRowsChanges.count() ) );
857  const bool fullModelUpdate = changeCount > mLayerCache->cacheSize() ||
858  changeCount > rowCount() * 0.5;
859 
860  QgsDebugMsgLevel( QStringLiteral( "Bulk edit command ended with %1 modified rows over (%4), cache size is %2, starting %3 update." )
861  .arg( changeCount )
862  .arg( mLayerCache->cacheSize() )
863  .arg( fullModelUpdate ? QStringLiteral( "full" ) : QStringLiteral( "incremental" ) )
864  .arg( rowCount() ),
865  3 );
866 
867  // Remove added rows on rollback
868  if ( mIsCleaningUpAfterRollback )
869  {
870  for ( const int fid : std::as_const( mInsertedRowsChanges ) )
871  {
872  const int row( idToRow( fid ) );
873  if ( row < 0 )
874  {
875  continue;
876  }
877  removeRow( row );
878  }
879  }
880 
881  // Invalidates the whole model
882  if ( fullModelUpdate )
883  {
884  // Invalidates the cache (there is no API for doing this directly)
885  emit mLayer->dataChanged();
886  emit dataChanged( createIndex( 0, 0 ), createIndex( rowCount() - 1, columnCount() - 1 ) );
887  }
888  else
889  {
890 
891  int minRow = rowCount();
892  int minCol = columnCount();
893  int maxRow = 0;
894  int maxCol = 0;
895  const auto keys = mAttributeValueChanges.keys();
896  for ( const auto &key : keys )
897  {
898  attributeValueChanged( key.first, key.second, mAttributeValueChanges.value( key ) );
899  const int row( idToRow( key.first ) );
900  const int col( fieldCol( key.second ) );
901  minRow = std::min<int>( row, minRow );
902  minCol = std::min<int>( col, minCol );
903  maxRow = std::max<int>( row, maxRow );
904  maxCol = std::max<int>( col, maxCol );
905  }
906 
907  emit dataChanged( createIndex( minRow, minCol ), createIndex( maxRow, maxCol ) );
908  }
909  mAttributeValueChanges.clear();
910 }
911 
912 void QgsAttributeTableModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
913 {
914  mFeat.setId( std::numeric_limits<int>::min() );
915  emit dataChanged( index1, index2 );
916 }
917 
918 
919 void QgsAttributeTableModel::executeAction( QUuid action, const QModelIndex &idx ) const
920 {
921  const QgsFeature f = feature( idx );
922  mLayer->actions()->doAction( action, f, fieldIdx( idx.column() ) );
923 }
924 
925 void QgsAttributeTableModel::executeMapLayerAction( QgsMapLayerAction *action, const QModelIndex &idx ) const
926 {
927  const QgsFeature f = feature( idx );
928  action->triggerForFeature( mLayer, f );
929 }
930 
931 QgsFeature QgsAttributeTableModel::feature( const QModelIndex &idx ) const
932 {
933  QgsFeature f( mLayer->fields() );
934  f.initAttributes( mAttributes.size() );
935  f.setId( rowToId( idx.row() ) );
936  for ( int i = 0; i < mAttributes.size(); i++ )
937  {
938  f.setAttribute( mAttributes[i], data( index( idx.row(), i ), Qt::EditRole ) );
939  }
940 
941  return f;
942 }
943 
945 {
946  if ( column == -1 || column >= mAttributes.count() )
947  {
948  prefetchSortData( QString() );
949  }
950  else
951  {
952  prefetchSortData( QgsExpression::quotedColumnRef( mLayer->fields().at( mAttributes.at( column ) ).name() ) );
953  }
954 }
955 
956 void QgsAttributeTableModel::prefetchSortData( const QString &expressionString, unsigned long cacheIndex )
957 {
958  if ( cacheIndex >= mSortCaches.size() )
959  {
960  mSortCaches.resize( cacheIndex + 1 );
961  }
962  SortCache &cache = mSortCaches[cacheIndex];
963  cache.sortCache.clear();
964  cache.sortCacheAttributes.clear();
965  cache.sortFieldIndex = -1;
966  if ( !expressionString.isEmpty() )
967  cache.sortCacheExpression = QgsExpression( expressionString );
968  else
969  {
970  // no sorting
971  cache.sortCacheExpression = QgsExpression();
972  return;
973  }
974 
975  QgsFieldFormatter *fieldFormatter = nullptr;
976  QVariant widgetCache;
977  QVariantMap widgetConfig;
978 
979  if ( cache.sortCacheExpression.isField() )
980  {
981  const QString fieldName = static_cast<const QgsExpressionNodeColumnRef *>( cache.sortCacheExpression.rootNode() )->name();
982  cache.sortFieldIndex = mLayer->fields().lookupField( fieldName );
983  }
984 
985  if ( cache.sortFieldIndex == -1 )
986  {
987  cache.sortCacheExpression.prepare( &mExpressionContext );
988 
989  const QSet<QString> &referencedColumns = cache.sortCacheExpression.referencedColumns();
990 
991  for ( const QString &col : referencedColumns )
992  {
993  cache.sortCacheAttributes.append( mLayer->fields().lookupField( col ) );
994  }
995  }
996  else
997  {
998  cache.sortCacheAttributes.append( cache.sortFieldIndex );
999 
1000  widgetCache = mAttributeWidgetCaches.at( cache.sortFieldIndex );
1001  widgetConfig = mWidgetConfigs.at( cache.sortFieldIndex );
1002  fieldFormatter = mFieldFormatters.at( cache.sortFieldIndex );
1003  }
1004 
1005  const QgsFeatureRequest request = QgsFeatureRequest( mFeatureRequest )
1007  .setSubsetOfAttributes( cache.sortCacheAttributes );
1008  QgsFeatureIterator it = mLayerCache->getFeatures( request );
1009 
1010  QgsFeature f;
1011  while ( it.nextFeature( f ) )
1012  {
1013  if ( cache.sortFieldIndex == -1 )
1014  {
1015  mExpressionContext.setFeature( f );
1016  const QVariant cacheValue = cache.sortCacheExpression.evaluate( &mExpressionContext );
1017  cache.sortCache.insert( f.id(), cacheValue );
1018  }
1019  else
1020  {
1021  const QVariant sortValue = fieldFormatter->sortValue( mLayer, cache.sortFieldIndex, widgetConfig, widgetCache, f.attribute( cache.sortFieldIndex ) );
1022  cache.sortCache.insert( f.id(), sortValue );
1023  }
1024  }
1025 }
1026 
1027 QString QgsAttributeTableModel::sortCacheExpression( unsigned long cacheIndex ) const
1028 {
1029  QString expressionString;
1030 
1031  if ( cacheIndex >= mSortCaches.size() )
1032  return expressionString;
1033 
1034  const QgsExpression &expression = mSortCaches[cacheIndex].sortCacheExpression;
1035 
1036  if ( expression.isValid() )
1037  expressionString = expression.expression();
1038  else
1039  expressionString = QString();
1040 
1041  return expressionString;
1042 }
1043 
1045 {
1046  mFeatureRequest = request;
1047  if ( mLayer && !mLayer->isSpatial() )
1048  mFeatureRequest.setFlags( mFeatureRequest.flags() | QgsFeatureRequest::NoGeometry );
1049 }
1050 
1052 {
1053  return mFeatureRequest;
1054 }
QgsMapLayerAction::triggerForFeature
virtual void triggerForFeature(QgsMapLayer *layer, const QgsFeature &feature)
Triggers the action with the specified layer and feature.
Definition: qgsmaplayeractionregistry.cpp:95
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:115
qgsfields.h
qgsexpressioncontextutils.h
QgsExpressionContext::appendScopes
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Definition: qgsexpressioncontext.cpp:499
QgsGui::editorWidgetRegistry
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
Definition: qgsgui.cpp:85
qgsconditionalstyle.h
QgsAttributeTableModel::headerData
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Returns header data.
Definition: qgsattributetablemodel.cpp:621
QgsConditionalStyle::isValid
bool isValid() const
isValid Check if this rule is valid.
Definition: qgsconditionalstyle.h:252
QgsEditorWidgetFactory
Every attribute editor widget needs a factory, which inherits this class.
Definition: qgseditorwidgetfactory.h:42
QgsAttributeTableModel::idToIndexList
QModelIndexList idToIndexList(QgsFeatureId id) const
Definition: qgsattributetablemodel.cpp:572
QgsMapLayerAction
An action which can run on map layers The class can be used in two manners:
Definition: qgsmaplayeractionregistry.h:38
QgsActionManager::doAction
void doAction(QUuid actionId, const QgsFeature &feature, int defaultValueIndex=0, const QgsExpressionContextScope &scope=QgsExpressionContextScope())
Does the given action.
Definition: qgsactionmanager.cpp:125
qgsvectorlayercache.h
QgsFieldFormatter::createCache
virtual QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const
Create a cache for a given field.
Definition: qgsfieldformatter.cpp:71
QgsVectorLayerCache
This class caches features of a given QgsVectorLayer.
Definition: qgsvectorlayercache.h:46
QgsAttributeTableModel::progress
void progress(int i, bool &cancel)
QgsFeatureRequest::acceptFeature
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
Definition: qgsfeaturerequest.cpp:314
qgsmapcanvas.h
QgsEditorWidgetSetup
Holder for the widget type and its configuration for a field.
Definition: qgseditorwidgetsetup.h:28
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:146
QgsVectorLayer::featuresDeleted
void featuresDeleted(const QgsFeatureIds &fids)
Emitted when features have been deleted.
QgsFeature::setId
void setId(QgsFeatureId id)
Sets the feature id for this feature.
Definition: qgsfeature.cpp:122
QgsFeature::initAttributes
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:235
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
qgsexpression.h
qgsstringutils.h
qgsgui.h
QgsVectorLayer::beforeRollBack
void beforeRollBack()
Emitted before changes are rolled back.
QgsFeatureRequest::filterType
FilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
Definition: qgsfeaturerequest.h:355
QgsExpressionNodeColumnRef
An expression node which takes it value from a feature's field.
Definition: qgsexpressionnodeimpl.h:512
qgssymbollayerutils.h
qgsfeatureiterator.h
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsEditorWidgetSetup::config
QVariantMap config() const
Definition: qgseditorwidgetsetup.h:64
QgsExpression::isValid
bool isValid() const
Checks if this expression is valid.
Definition: qgsexpression.cpp:201
QgsVectorLayer::attributeDeleted
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
qgsfieldformatterregistry.h
QgsAttributeTableModel::modelChanged
void modelChanged()
Model has been changed.
QgsVectorLayer::isSpatial
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Definition: qgsvectorlayer.cpp:3733
QgsFieldModel::fieldToolTipExtended
static QString fieldToolTipExtended(const QgsField &field, const QgsVectorLayer *layer)
Returns a HTML formatted tooltip string for a field, containing details like the field name,...
Definition: qgsfieldmodel.cpp:500
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:377
QgsAttributeTableModel::QgsAttributeTableModel
QgsAttributeTableModel(QgsVectorLayerCache *layerCache, QObject *parent=nullptr)
Constructor.
Definition: qgsattributetablemodel.cpp:52
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
QgsAttributeTableModel::fieldIdx
int fieldIdx(int col) const
Gets field index from column.
Definition: qgsattributetablemodel.cpp:599
QgsVectorLayerCache::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
Definition: qgsvectorlayercache.cpp:400
field
const QgsField & field
Definition: qgsfield.h:463
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsVectorLayerCache::invalidated
void invalidated()
The cache has been invalidated and cleared.
QgsFieldFormatter::sortValue
virtual QVariant sortValue(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value) const
If the default sort order should be overwritten for this widget, you can transform the value in here.
Definition: qgsfieldformatter.cpp:50
QgsAttributeTableModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
Definition: qgsattributetablemodel.cpp:609
FID_TO_STRING
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:33
QgsAttributeTableModel::idToRow
int idToRow(QgsFeatureId id) const
Maps feature id to table row.
Definition: qgsattributetablemodel.cpp:556
QgsAttributeList
QList< int > QgsAttributeList
Definition: qgsfield.h:26
QgsAttributeTableModel::executeAction
void executeAction(QUuid action, const QModelIndex &idx) const
Execute an action.
Definition: qgsattributetablemodel.cpp:919
QgsField::name
QString name
Definition: qgsfield.h:60
QgsConditionalStyle
Conditional styling for a rule.
Definition: qgsconditionalstyle.h:120
QgsVectorLayer::isEditable
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
Definition: qgsvectorlayer.cpp:3728
QgsConditionalStyle::compressStyles
static QgsConditionalStyle compressStyles(const QList< QgsConditionalStyle > &styles)
Compress a list of styles into a single style.
Definition: qgsconditionalstyle.cpp:276
qgsvectorlayerjoininfo.h
QgsFeatureRequest::flags
Flags flags() const
Returns the flags which affect how features are fetched.
Definition: qgsfeaturerequest.h:673
QgsAttributeTableModel::executeMapLayerAction
void executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx) const
Execute a QgsMapLayerAction.
Definition: qgsattributetablemodel.cpp:925
qgsapplication.h
QgsVectorLayerCache::attributeValueChanged
void attributeValueChanged(QgsFeatureId fid, int field, const QVariant &value)
Emitted when an attribute is changed.
QgsAttributeTableModel::fieldCol
int fieldCol(int idx) const
Gets column from field index.
Definition: qgsattributetablemodel.cpp:604
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsEditorWidgetSetup::type
QString type() const
Definition: qgseditorwidgetsetup.h:59
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsConditionalStyle::icon
QPixmap icon() const
The icon set for style generated from the set symbol.
Definition: qgsconditionalstyle.h:200
QgsAttributeTableModel::FieldIndexRole
@ FieldIndexRole
Get the field index of this column.
Definition: qgsattributetablemodel.h:57
QgsLogger::debugLevel
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
Definition: qgslogger.h:108
QgsAttributeTableModel::swapRows
void swapRows(QgsFeatureId a, QgsFeatureId b)
Swaps two rows.
Definition: qgsattributetablemodel.cpp:531
QgsAttributeTableModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
Definition: qgsattributetablemodel.cpp:826
qgsvectorlayerjoinbuffer.h
qgsactionmanager.h
QgsFeature::isValid
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:216
QgsAttributeTableModel::rowToId
QgsFeatureId rowToId(int row) const
Maps row to feature id.
Definition: qgsattributetablemodel.cpp:587
QgsAttributeTableModel::setRequest
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
Definition: qgsattributetablemodel.cpp:1044
QgsConditionalStyle::validBackgroundColor
bool validBackgroundColor() const
Check if the background color is valid for render.
Definition: qgsconditionalstyle.cpp:243
QgsConditionalStyle::backgroundColor
QColor backgroundColor() const
The background color for style.
Definition: qgsconditionalstyle.h:225
qgsattributetablefiltermodel.h
QgsVectorLayerCache::featureAdded
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer and this cache.
QgsVectorLayer::afterRollBack
void afterRollBack()
Emitted after changes are rolled back.
qgsvectordataprovider.h
QgsEditorWidgetRegistry::findBest
QgsEditorWidgetSetup findBest(const QgsVectorLayer *vl, const QString &fieldName) const
Find the best editor widget and its configuration for a given field.
Definition: qgseditorwidgetregistry.cpp:78
qgsvectorlayerutils.h
QgsAttributeTableModel::prefetchSortData
void prefetchSortData(const QString &expression, unsigned long cacheIndex=0)
Prefetches the entire data for an expression.
Definition: qgsattributetablemodel.cpp:956
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:327
QgsAttributeTableModel::finished
void finished()
QgsVectorLayer::actions
QgsActionManager * actions()
Returns all layer actions defined on this layer.
Definition: qgsvectorlayer.h:741
QgsAttributeTableModel::setData
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Updates data on given index.
Definition: qgsattributetablemodel.cpp:811
qgsattributetablemodel.h
QgsVectorLayerCache::layer
QgsVectorLayer * layer()
Returns the layer to which this cache belongs.
Definition: qgsvectorlayercache.cpp:192
QgsAttributeTableModel::extraColumns
int extraColumns() const
Empty extra columns to announce from this model.
Definition: qgsattributetablemodel.cpp:102
qgsrenderer.h
qgsmaplayeractionregistry.h
QgsAttributeTableModel::prefetchColumnData
void prefetchColumnData(int column)
Caches the entire data for one column.
Definition: qgsattributetablemodel.cpp:944
QgsAttributeTableModel::loadLayer
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
Definition: qgsattributetablemodel.cpp:460
QgsConditionalStyle::matchingConditionalStyles
static QList< QgsConditionalStyle > matchingConditionalStyles(const QList< QgsConditionalStyle > &styles, const QVariant &value, QgsExpressionContext &context)
Find and return the matching styles for the value and feature.
Definition: qgsconditionalstyle.cpp:253
QgsVectorLayerCache::featureAtId
bool featureAtId(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id.
Definition: qgsvectorlayercache.cpp:147
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsEditorWidgetRegistry::factory
QgsEditorWidgetFactory * factory(const QString &widgetId)
Gets a factory for the given widget type id.
Definition: qgseditorwidgetregistry.cpp:174
QgsVectorLayerCache::cachedLayerDeleted
void cachedLayerDeleted()
Is emitted when the cached layer is deleted.
QgsAttributeTableModel::sortCacheExpression
QString sortCacheExpression(unsigned long cacheIndex=0) const
The expression which was used to fill the sorting cache at index cacheIndex.
Definition: qgsattributetablemodel.cpp:1027
QgsApplication::fieldFormatterRegistry
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Definition: qgsapplication.cpp:2480
QgsConditionalStyle::font
QFont font() const
The font for the style.
Definition: qgsconditionalstyle.h:238
qgsvectorlayer.h
QgsAttributeTableModel::FeatureIdRole
@ FeatureIdRole
Get the feature id of the feature in this row.
Definition: qgsattributetablemodel.h:56
QgsMapLayer::dataChanged
void dataChanged()
Data of layer changed.
QgsFieldFormatter::representValue
virtual QString representValue(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value) const
Create a pretty String representation of the value.
Definition: qgsfieldformatter.cpp:24
QgsConditionalLayerStyles::rowStyles
QgsConditionalStyles rowStyles() const
Returns a list of row styles associated with the layer.
Definition: qgsconditionalstyle.cpp:28
QgsFeature::setAttribute
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:262
qgseditorwidgetregistry.h
QgsAttributeTableModel::data
QVariant data(const QModelIndex &index, int role) const override
Returns data on the given index.
Definition: qgsattributetablemodel.cpp:661
QgsAttributeTableModel::feature
QgsFeature feature(const QModelIndex &idx) const
Returns the feature attributes at given model index.
Definition: qgsattributetablemodel.cpp:931
QgsVectorLayerCache::cacheSize
int cacheSize()
Returns the maximum number of features this cache will hold.
Definition: qgsvectorlayercache.cpp:60
QgsAttributeTableModel::fieldConditionalStyleChanged
void fieldConditionalStyleChanged(const QString &fieldName)
Handles updating the model when the conditional style for a field changes.
Definition: qgsattributetablemodel.cpp:513
qgsexpressionnodeimpl.h
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsConditionalStyle::textColor
QColor textColor() const
The text color set for style.
Definition: qgsconditionalstyle.h:212
qgseditorwidgetfactory.h
QgsAttributeTableModel::reload
void reload(const QModelIndex &index1, const QModelIndex &index2)
Reloads the model data between indices.
Definition: qgsattributetablemodel.cpp:912
QgsVectorLayer::editCommandStarted
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
QgsFieldFormatterRegistry::fallbackFieldFormatter
QgsFieldFormatter * fallbackFieldFormatter() const
Returns a basic fallback field formatter which can be used to represent any field in an unspectacular...
Definition: qgsfieldformatterregistry.cpp:82
QgsVectorLayerUtils::fieldIsEditable
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
Tests whether a field is editable for a particular feature.
Definition: qgsvectorlayerutils.cpp:919
QgsFieldFormatterRegistry::fieldFormatter
QgsFieldFormatter * fieldFormatter(const QString &id) const
Gets a field formatter by its id.
Definition: qgsfieldformatterregistry.cpp:76
qgsfieldmodel.h
QgsVectorLayer::conditionalStyles
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
Definition: qgsvectorlayer.cpp:1047
QgsExpression::quotedColumnRef
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Definition: qgsexpression.cpp:68
QgsAttributeTableModel::setExtraColumns
void setExtraColumns(int extraColumns)
Empty extra columns to announce from this model.
Definition: qgsattributetablemodel.cpp:107
QgsStringUtils::isUrl
static bool isUrl(const QString &string)
Returns whether the string is a URL (http,https,ftp,file)
Definition: qgsstringutils.cpp:568
QgsFeatureRequest::FilterNone
@ FilterNone
No filter is applied.
Definition: qgsfeaturerequest.h:115
QgsConditionalLayerStyles::fieldStyles
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName) const
Returns the conditional styles set for the field with matching fieldName.
Definition: qgsconditionalstyle.cpp:51
qgstexteditwidgetfactory.h
QgsField::displayName
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:89
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsVectorLayer::isModified
bool isModified() const override
Returns true if the provider has been modified since the last commit.
Definition: qgsvectorlayer.cpp:3763
QgsVectorLayer::updatedFields
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
QgsAttributeTableModel::SortRole
@ SortRole
Role used for sorting start here.
Definition: qgsattributetablemodel.h:60
QgsAttributeTableModel::removeRows
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Remove rows.
Definition: qgsattributetablemodel.cpp:171
qgslogger.h
QgsAttributeTableModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns.
Definition: qgsattributetablemodel.cpp:615
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
QgsAttributeTableModel::request
const QgsFeatureRequest & request() const
Gets the the feature request.
Definition: qgsattributetablemodel.cpp:1051
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsAttributeTableModel::idToIndex
QModelIndex idToIndex(QgsFeatureId id) const
Definition: qgsattributetablemodel.cpp:567
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:720
QgsConditionalStyle::validTextColor
bool validTextColor() const
Check if the text color is valid for render.
Definition: qgsconditionalstyle.cpp:248
QgsFieldFormatter
A field formatter helps to handle and display values for a field.
Definition: qgsfieldformatter.h:72
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:222
QgsExpression::expression
QString expression() const
Returns the original, unmodified expression string.
Definition: qgsexpression.cpp:60
QgsAttributeTableModel::resetModel
void resetModel()
Resets the model.
Definition: qgsattributetablemodel.h:130
QgsAttributeTableModel::layerCache
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
Definition: qgsattributetablemodel.h:173
qgsfieldformatter.h
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsVectorLayer::editCommandEnded
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50