45#include "moc_qgsattributetablemodel.cpp"
47using namespace Qt::StringLiterals;
50 : QAbstractTableModel( parent )
58 mFeatureRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
61 mFeat.setId( std::numeric_limits<int>::min() );
63 if ( !mLayer->isSpatial() )
74 mIsCleaningUpAfterRollback =
true;
75 bulkEditCommandEnded();
76 mIsCleaningUpAfterRollback =
false;
86bool QgsAttributeTableModel::loadFeatureAtId(
QgsFeatureId fid )
const
90 if ( fid == std::numeric_limits<int>::min() )
95 return mLayerCache->featureAtId( fid, mFeat );
98bool QgsAttributeTableModel::loadFeatureAtId(
QgsFeatureId fid,
int fieldIdx )
const
102 if ( mLayerCache->cacheSubsetOfAttributes().contains(
fieldIdx ) )
104 return loadFeatureAtId( fid );
107 if ( fid == std::numeric_limits<int>::min() )
111 return mLayerCache->featureAtIdWithAllAttributes( fid, mFeat );
122void QgsAttributeTableModel::featuresDeleted(
const QgsFeatureIds &fids )
126 const auto constFids = fids;
131 const int row =
idToRow( fid );
136 std::sort( rows.begin(), rows.end() );
140 int currentRowCount = 0;
144 const auto constRows = rows;
145 for (
const int row : constRows )
148 qDebug() <<
"Row: " << row <<
", begin " << beginRow <<
", last " << lastRow <<
", current " << currentRowCount <<
", removed " << removedRows;
155 if ( row != lastRow + 1 && lastRow != -1 )
157 if ( rows.count() > 100 && currentRowCount < 10 )
162 removeRows( beginRow - removedRows, currentRowCount );
165 removedRows += currentRowCount;
175 removeRows( beginRow - removedRows, currentRowCount );
182 if ( row < 0 || count < 1 )
185 if ( !mResettingModel )
187 beginRemoveRows( parent, row, row + count - 1 );
190 QgsDebugMsgLevel( u
"remove %2 rows at %1 (rows %3, ids %4)"_s.arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
192 if ( mBulkEditCommandRunning && !mResettingModel )
194 for (
int i = row; i < row + count; i++ )
197 mInsertedRowsChanges.removeOne( fid );
202 for (
int i = row; i < row + count; i++ )
204 for ( SortCache &cache : mSortCaches )
205 cache.sortCache.remove( mRowIdMap[i] );
206 mIdRowMap.remove( mRowIdMap[i] );
207 mRowIdMap.remove( i );
211 const int n = mRowIdMap.size() + count;
212 for (
int i = row + count; i < n; i++ )
215 mIdRowMap[id] -= count;
216 mRowIdMap[i - count] = id;
217 mRowIdMap.remove( i );
223 QgsDebugMsgLevel( u
"after removal rows %1, ids %2"_s.arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
225 for ( QHash<QgsFeatureId, int>::const_iterator it = mIdRowMap.constBegin(); it != mIdRowMap.constEnd(); ++it )
231 for ( QHash<int, QgsFeatureId>::const_iterator it = mRowIdMap.constBegin(); it != mRowIdMap.constEnd(); ++it )
238 Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
240 if ( !mResettingModel )
246void QgsAttributeTableModel::featureAdded(
QgsFeatureId fid )
251 if ( mFeat.
id() != fid )
252 featOk = loadFeatureAtId( fid );
256 for ( SortCache &cache : mSortCaches )
258 if ( cache.sortFieldIndex >= 0 )
260 const WidgetData &widgetData = getWidgetData( cache.sortFieldIndex );
261 const QVariant sortValue = widgetData.fieldFormatter->sortValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, mFeat.
attribute( cache.sortFieldIndex ) );
262 cache.sortCache.insert( mFeat.
id(), sortValue );
264 else if ( cache.sortCacheExpression.isValid() )
266 mExpressionContext.setFeature( mFeat );
267 cache.sortCache[mFeat.id()] = cache.sortCacheExpression.evaluate( &mExpressionContext );
272 if ( !mIdRowMap.contains( fid ) )
274 const int n = mRowIdMap.size();
275 if ( !mResettingModel )
276 beginInsertRows( QModelIndex(), n, n );
277 mIdRowMap.insert( fid, n );
278 mRowIdMap.insert( n, fid );
279 if ( !mResettingModel )
283 const QModelIndex first = index( row, 0 );
285 const QModelIndex last = index( row, lastColumn );
287 if ( mBulkEditCommandRunning && !mResettingModel )
289 mInsertedRowsChanges.append( fid );
295void QgsAttributeTableModel::updatedFields()
301void QgsAttributeTableModel::editCommandEnded()
305 bulkEditCommandEnded();
308void QgsAttributeTableModel::attributeDeleted(
int idx )
311 for (
const SortCache &cache : mSortCaches )
313 if ( cache.sortCacheAttributes.contains( idx ) )
321void QgsAttributeTableModel::layerDeleted()
323 mLayerCache =
nullptr;
328 mWidgetDatas.clear();
331void QgsAttributeTableModel::fieldFormatterRemoved(
QgsFieldFormatter *fieldFormatter )
333 for ( WidgetData &widgetData : mWidgetDatas )
335 if ( widgetData.fieldFormatter == fieldFormatter )
340void QgsAttributeTableModel::attributeValueChanged(
QgsFeatureId fid,
int idx,
const QVariant &value )
343 if ( mBulkEditCommandRunning )
345 mAttributeValueChanges.insert( QPair<QgsFeatureId, int>( fid, idx ), value );
348 QgsDebugMsgLevel( u
"(%4) fid: %1, idx: %2, value: %3"_s.arg( fid ).arg( idx ).arg( value.toString() ).arg(
qgsEnumValueToKey( mFeatureRequest.filterType() ) ), 2 );
350 for ( SortCache &cache : mSortCaches )
352 if ( cache.sortCacheAttributes.contains( idx ) )
354 if ( cache.sortFieldIndex == -1 )
356 if ( loadFeatureAtId( fid ) )
358 mExpressionContext.setFeature( mFeat );
359 cache.sortCache[fid] = cache.sortCacheExpression.evaluate( &mExpressionContext );
364 const WidgetData &widgetData = getWidgetData( cache.sortFieldIndex );
365 const QVariant sortValue = widgetData.fieldFormatter->representValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, value );
366 cache.sortCache.insert( fid, sortValue );
373 if ( loadFeatureAtId( fid ) )
375 const QModelIndex modelIndex = index(
idToRow( fid ),
fieldCol( idx ) );
376 setData( modelIndex, value, Qt::EditRole );
377 emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
382 if ( loadFeatureAtId( fid ) )
384 if ( mFeatureRequest.acceptFeature( mFeat ) )
386 if ( !mIdRowMap.contains( fid ) )
394 const QModelIndex modelIndex = index(
idToRow( fid ),
fieldCol( idx ) );
395 setData( modelIndex, value, Qt::EditRole );
396 emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
401 if ( mIdRowMap.contains( fid ) )
412void QgsAttributeTableModel::loadAttributes()
419 const QgsFields fields = mLayer->fields();
420 if ( mFields == fields )
423 bool ins =
false, rm =
false;
427 for (
int idx = 0; idx < fields.
count(); ++idx )
432 if ( mFieldCount < attributes.size() )
435 beginInsertColumns( QModelIndex(), mFieldCount, attributes.size() - 1 );
437 else if ( attributes.size() < mFieldCount )
440 beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount - 1 );
445 mFieldCount = attributes.size();
446 mAttributes = attributes;
447 mWidgetDatas.clear();
448 mWidgetDatas.resize( mFieldCount );
450 for ( SortCache &cache : mSortCaches )
452 if ( cache.sortFieldIndex >= mAttributes.count() )
453 cache.sortFieldIndex = -1;
475 mResettingModel =
true;
497 if ( t.elapsed() > 1000 )
506 featureAdded( mFeat.id() );
515 mResettingModel =
false;
521 if ( fieldName.isNull() )
523 mRowStylesMap.clear();
524 mConstraintStylesMap.clear();
529 const int fieldIndex = mLayer->fields().lookupField( fieldName );
530 if ( fieldIndex == -1 )
534 const int col =
fieldCol( fieldIndex );
535 emit dataChanged( index( 0, col ), index(
rowCount() - 1, col ) );
548 mRowIdMap.remove( rowA );
549 mRowIdMap.remove( rowB );
550 mRowIdMap.insert( rowA, b );
551 mRowIdMap.insert( rowB, a );
553 mIdRowMap.remove( a );
554 mIdRowMap.remove( b );
555 mIdRowMap.insert( a, rowB );
556 mIdRowMap.insert( b, rowA );
557 Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
565 if ( !mIdRowMap.contains(
id ) )
567 QgsDebugError( u
"idToRow: id %1 not in the map"_s.arg(
id ) );
571 return mIdRowMap[id];
576 return index(
idToRow(
id ), 0 );
581 QModelIndexList indexes;
585 indexes.reserve( columns );
586 for (
int column = 0; column < columns; ++column )
588 indexes.append( index( row, column ) );
596 if ( !mRowIdMap.contains( row ) )
598 QgsDebugError( u
"rowToId: row %1 not in the map"_s.arg( row ) );
600 return std::numeric_limits<int>::min();
603 return mRowIdMap[row];
608 return mAttributes[col];
613 return mAttributes.indexOf( idx );
618 if ( parent.isValid() )
621 return mRowIdMap.size();
626 if ( parent.isValid() )
629 return std::max( 1, mFieldCount + 1 );
637 if ( role == Qt::DisplayRole )
639 if ( orientation == Qt::Vertical )
641 return QVariant( section + 1 );
643 else if ( section >= 0 && section < mFieldCount )
645 const QString attributeName = mLayer->fields().at( mAttributes.at( section ) ).displayName();
646 return QVariant( attributeName );
650 return tr(
"Actions" );
653 else if ( role == Qt::ToolTipRole )
655 if ( orientation == Qt::Vertical )
658 return tr(
"Feature ID: %1" ).arg(
rowToId( section ) );
660 else if ( section >= 0 && section < mFieldCount )
662 const QgsField field = mLayer->fields().at( mAttributes.at( section ) );
672 if ( !index.isValid() || !mLayer )
675 const bool isActionColumn = index.column() == mFieldCount;
682 if ( isActionColumn )
694 return isActionColumn ? QVariant() : mAttributes.at( index.column() );
697 case Qt::TextAlignmentRole:
699 if ( isActionColumn )
701 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft | Qt::AlignVCenter );
705 const int fieldId = mAttributes.at( index.column() );
706 const QgsField field = mFields.at( fieldId );
707 const WidgetData &widgetData = getWidgetData( index.column() );
708 return static_cast<Qt::Alignment::Int
>( widgetData.fieldFormatter->
alignmentFlag( field, widgetData.config ) | Qt::AlignVCenter );
723 const unsigned long cacheIndex = role -
static_cast<int>(
CustomRole::Sort );
724 if ( cacheIndex < mSortCaches.size() )
726 return mSortCaches.at( cacheIndex ).sortCache.value(
rowToId( index.row() ) );
734 if ( isActionColumn )
739 const int fieldId = mAttributes.at( index.column() );
740 if ( mFeat.id() != rowId || !mFeat.isValid() || !mLayerCache->cacheSubsetOfAttributes().contains( fieldId ) )
742 if ( !loadFeatureAtId( rowId, fieldId ) )
743 return QVariant(
"ERROR" );
745 if ( mFeat.id() != rowId )
746 return QVariant(
"ERROR" );
749 const QgsField field = mFields.at( fieldId );
750 const QVariant val = mFeat.attribute( fieldId );
753 case Qt::DisplayRole:
755 const WidgetData &widgetData = getWidgetData( index.column() );
756 QString s = widgetData.fieldFormatter->
representValue( mLayer, fieldId, widgetData.config, widgetData.cache, val );
758 constexpr int MAX_STRING_LENGTH = 10 * 1000;
759 if (
static_cast<size_t>( s.size() ) >
static_cast<size_t>( MAX_STRING_LENGTH ) )
761 s.resize( MAX_STRING_LENGTH );
762 s.append( tr(
"... truncated ..." ) );
766 case Qt::ToolTipRole:
768 const WidgetData &widgetData = getWidgetData( index.column() );
769 QString tooltip = widgetData.fieldFormatter->
representValue( mLayer, fieldId, widgetData.config, widgetData.cache, val );
770 if ( tooltip != val.toString() )
772 tooltip = tr(
"%1 (%2)" ).arg( tooltip, val.toString() );
776 tooltip = tr(
"%1 (Ctrl+click to open)" ).arg( tooltip );
783 case Qt::BackgroundRole:
784 case Qt::ForegroundRole:
785 case Qt::DecorationRole:
788 mExpressionContext.setFeature( mFeat );
789 QList<QgsConditionalStyle> styles;
790 if ( mRowStylesMap.contains( mFeat.id() ) )
792 styles = mRowStylesMap[mFeat.id()];
797 mRowStylesMap.insert( mFeat.id(), styles );
804 if ( mConstraintStylesMap.contains( mFeat.id() ) && mConstraintStylesMap[mFeat.id()].contains( fieldId ) )
806 constraintstyle = mConstraintStylesMap[mFeat.id()][fieldId];
822 mConstraintStylesMap[mFeat.id()].insert( fieldId, constraintstyle );
826 styles = mLayer->conditionalStyles()->fieldStyles( field.
name() );
828 styles.insert( 0, rowstyle );
829 styles.insert( 0, constraintstyle );
838 if ( role == Qt::DecorationRole )
840 if ( role == Qt::FontRole )
845 if ( role == Qt::ForegroundRole )
847 return QColor( Qt::blue );
849 else if ( role == Qt::FontRole )
852 font.setUnderline(
true );
871 if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !mLayer->isEditable() )
874 mRowStylesMap.remove( mFeat.id() );
875 mConstraintStylesMap.remove( mFeat.id() );
877 if ( !mLayer->isModified() )
885 if ( !index.isValid() )
886 return Qt::NoItemFlags;
889 return Qt::NoItemFlags;
891 if ( index.column() >= mFieldCount + 1 )
892 return Qt::NoItemFlags;
893 else if ( index.column() == mFieldCount )
894 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
896 Qt::ItemFlags
flags = QAbstractTableModel::flags( index );
898 const int fieldIndex = mAttributes[index.column()];
902 flags |= Qt::ItemIsEditable;
907void QgsAttributeTableModel::bulkEditCommandStarted()
909 mBulkEditCommandRunning =
true;
910 mAttributeValueChanges.clear();
913void QgsAttributeTableModel::bulkEditCommandEnded()
915 mBulkEditCommandRunning =
false;
919 const long long fullModelUpdateThreshold = std::min<long long>( mLayerCache->cacheSize(), std::ceil(
rowCount() * 0.5 ) );
920 bool fullModelUpdate =
false;
923 if ( mInsertedRowsChanges.size() > fullModelUpdateThreshold )
925 fullModelUpdate =
true;
929 QSet<QgsFeatureId> changedRows;
930 changedRows.reserve( mAttributeValueChanges.size() );
932 for (
auto it = mAttributeValueChanges.constBegin(); it != mAttributeValueChanges.constEnd(); ++it )
934 changedRows.insert( it.key().first );
935 if ( changedRows.size() > fullModelUpdateThreshold )
937 fullModelUpdate =
true;
943 QgsDebugMsgLevel( u
"Bulk edit command ended modified rows over (%3), cache size is %1, starting %2 update."_s.arg( mLayerCache->cacheSize() ).arg( fullModelUpdate ? u
"full"_s : u
"incremental"_s ).arg(
rowCount() ), 3 );
946 if ( mIsCleaningUpAfterRollback )
948 for (
const int fid : std::as_const( mInsertedRowsChanges ) )
950 const int row(
idToRow( fid ) );
960 if ( fullModelUpdate )
963 emit mLayer->dataChanged();
969 else if ( !mAttributeValueChanges.empty() && !mInsertedRowsChanges.empty() )
971 int minRow = std::numeric_limits< int >::max();
972 int minCol = std::numeric_limits< int >::max();
976 for (
auto it = mAttributeValueChanges.constBegin(); it != mAttributeValueChanges.constEnd(); ++it )
978 attributeValueChanged( it.key().first, it.key().second, it.value() );
979 const int row(
idToRow( it.key().first ) );
980 const int col(
fieldCol( it.key().second ) );
981 minRow = std::min<int>( row, minRow );
982 minCol = std::min<int>( col, minCol );
983 maxRow = std::max<int>( row, maxRow );
984 maxCol = std::max<int>( col, maxCol );
987 for (
QgsFeatureId fid : std::as_const( mInsertedRowsChanges ) )
989 const int row(
idToRow( fid ) );
990 minRow = std::min<int>( row, minRow );
991 maxRow = std::max<int>( row, maxRow );
997 Q_ASSERT_X( minRow >= 0 && minRow <
rowCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid minRow, got %1 expected >=0 && < %2"_s.arg( minRow ).arg(
rowCount() ).toLocal8Bit().constData() );
998 Q_ASSERT_X( minCol >= 0 && minCol <
columnCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid minCol, got %1 expected >=0 && < %2"_s.arg( minCol ).arg(
columnCount() ).toLocal8Bit().constData() );
999 Q_ASSERT_X( maxRow >= 0 && maxRow <
rowCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid maxRow, got %1 expected >=0 && < %2"_s.arg( maxRow ).arg(
rowCount() ).toLocal8Bit().constData() );
1000 Q_ASSERT_X( maxCol >= 0 && maxCol <
columnCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid maxCol, got %1 expected >=0 && < %2"_s.arg( maxCol ).arg(
columnCount() ).toLocal8Bit().constData() );
1003 emit dataChanged( createIndex( minRow, minCol ), createIndex( maxRow, maxCol ) );
1005 mAttributeValueChanges.clear();
1010 mFeat.setId( std::numeric_limits<int>::min() );
1013 Q_ASSERT_X( index1.row() >= 0 && index1.row() <
rowCount(),
"QgsAttributeTableModel::reload", u
"Invalid min row, got %1 expected >=0 && < %2"_s.arg( index1.row() ).arg(
rowCount() ).toLocal8Bit().constData() );
1015 index1.column() >= 0 && index1.column() <
columnCount(),
1016 "QgsAttributeTableModel::reload",
1017 u
"Invalid min col, got %1 expected >=0 && < %2"_s.arg( index1.column() ).arg(
columnCount() ).toLocal8Bit().constData()
1019 Q_ASSERT_X( index2.row() >= 0 && index2.row() <
rowCount(),
"QgsAttributeTableModel::reload", u
"Invalid max row, got %1 expected >=0 && < %2"_s.arg( index2.row() ).arg(
rowCount() ).toLocal8Bit().constData() );
1021 index2.column() >= 0 && index2.column() <
columnCount(),
1022 "QgsAttributeTableModel::reload",
1023 u
"Invalid max col, got %1 expected >=0 && < %2"_s.arg( index2.column() ).arg(
columnCount() ).toLocal8Bit().constData()
1025 Q_ASSERT_X( index2.row() >= index1.row(),
"QgsAttributeTableModel::reload", u
"Invalid max row, got %1 expected >= %2"_s.arg( index2.row() ).arg( index1.row() ).toLocal8Bit().constData() );
1026 Q_ASSERT_X( index2.column() >= index1.column(),
"QgsAttributeTableModel::reload", u
"Invalid max column, got %1 expected >= %2"_s.arg( index2.column() ).arg( index1.column() ).toLocal8Bit().constData() );
1029 if ( !mResettingModel )
1031 emit dataChanged( index1, index2 );
1038 mLayer->actions()->doAction( action, f,
fieldIdx( idx.column() ) );
1055 for (
int i = 0; i < mAttributes.size(); i++ )
1057 f.
setAttribute( mAttributes[i],
data( index( idx.row(), i ), Qt::EditRole ) );
1065 if ( column == -1 || column >= mAttributes.count() )
1080 if ( cacheIndex >= mSortCaches.size() )
1082 mSortCaches.resize( cacheIndex + 1 );
1084 SortCache &cache = mSortCaches[cacheIndex];
1085 cache.sortCache.clear();
1086 cache.sortCacheAttributes.clear();
1087 cache.sortFieldIndex = -1;
1088 if ( !expressionString.isEmpty() )
1089 cache.sortCacheExpression =
QgsExpression( expressionString );
1097 WidgetData widgetData;
1099 if ( cache.sortCacheExpression.
isField() )
1102 cache.sortFieldIndex = mLayer->fields().lookupField( fieldName );
1105 if ( cache.sortFieldIndex == -1 )
1107 cache.sortCacheExpression.
prepare( &mExpressionContext );
1109 const QSet<QString> &referencedColumns = cache.sortCacheExpression.
referencedColumns();
1111 for (
const QString &col : referencedColumns )
1113 cache.sortCacheAttributes.append( mLayer->fields().lookupField( col ) );
1118 cache.sortCacheAttributes.append( cache.sortFieldIndex );
1120 widgetData = getWidgetData( cache.sortFieldIndex );
1132 if ( cache.sortFieldIndex == -1 )
1134 mExpressionContext.setFeature( f );
1135 const QVariant cacheValue = cache.sortCacheExpression.
evaluate( &mExpressionContext );
1136 cache.sortCache.insert( f.
id(), cacheValue );
1140 const QVariant sortValue = widgetData.fieldFormatter->
sortValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, f.
attribute( cache.sortFieldIndex ) );
1141 cache.sortCache.insert( f.
id(), sortValue );
1147 const int sortRole =
static_cast< int >(
CustomRole::Sort ) +
static_cast< int >( cacheIndex );
1148 emit dataChanged( index( 0, 0 ), index( rows - 1,
columnCount() - 1 ), { sortRole } );
1154 QString expressionString;
1156 if ( cacheIndex >= mSortCaches.size() )
1157 return expressionString;
1159 const QgsExpression &expression = mSortCaches[cacheIndex].sortCacheExpression;
1164 expressionString = QString();
1166 return expressionString;
1171 if ( !mFeatureRequest.compare(
request ) )
1174 if ( mLayer && !mLayer->isSpatial() )
1177 for (
unsigned long i = 0; i < mSortCaches.size(); ++i )
1186 return mFeatureRequest;
1189const QgsAttributeTableModel::WidgetData &QgsAttributeTableModel::getWidgetData(
int column )
const
1191 Q_ASSERT( column >= 0 && column < mAttributes.size() );
1193 WidgetData &widgetData = mWidgetDatas[column];
1194 if ( !widgetData.loaded )
1196 const int idx =
fieldIdx( column );
1199 widgetData.config = setup.
config();
1200 widgetData.cache = widgetData.fieldFormatter->createCache( mLayer, idx, setup.
config() );
1201 widgetData.loaded =
true;
@ NoFilter
No filter is applied.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
const QgsFeatureRequest & request() const
Gets the the feature request.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Remove rows.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
QgsFeature feature(const QModelIndex &idx) const
Returns the feature attributes at given model index.
void resetModel()
Resets the model.
void fieldConditionalStyleChanged(const QString &fieldName)
Handles updating the model when the conditional style for a field changes.
QString sortCacheExpression(unsigned long cacheIndex=0) const
The expression which was used to fill the sorting cache at index cacheIndex.
int fieldIdx(int col) const
Gets field index from column.
QgsAttributeTableModel(QgsVectorLayerCache *layerCache, QObject *parent=nullptr)
Constructor.
void swapRows(QgsFeatureId a, QgsFeatureId b)
Swaps two rows.
void modelChanged()
Emitted when the model has been changed.
void executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx, const QgsMapLayerActionContext &context=QgsMapLayerActionContext()) const
Execute a QgsMapLayerAction.
void progress(int i, bool &cancel)
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Updates data on given index.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
QModelIndex idToIndex(QgsFeatureId id) const
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
Q_DECL_DEPRECATED int extraColumns() const
Empty extra columns to announce from this model.
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
void finished()
Emitted when the model has completely loaded all features.
@ Field
This column shows a field.
@ ActionButton
This column shows action buttons.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Returns header data.
QModelIndexList idToIndexList(QgsFeatureId id) const
void prefetchSortData(const QString &expression, unsigned long cacheIndex=0)
Prefetches the entire data for an expression.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
int idToRow(QgsFeatureId id) const
Maps feature id to table row.
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
Q_DECL_DEPRECATED void setExtraColumns(int extraColumns)
Empty extra columns to announce from this model.
void prefetchColumnData(int column)
Caches the entire data for one column.
int fieldCol(int idx) const
Gets column from field index.
void reload(const QModelIndex &index1, const QModelIndex &index2)
Reloads the model data between indices.
@ FeatureId
Get the feature id of the feature in this row.
@ ColumnType
The type of a given column. See ColumnType.
@ Sort
Role used for sorting start here.
@ FieldIndex
Get the field index of this column.
void executeAction(QUuid action, const QModelIndex &idx) const
Execute an action.
QVariant data(const QModelIndex &index, int role) const override
Returns data on the given index.
Conditional styling for a rule.
static QgsConditionalStyle compressStyles(const QList< QgsConditionalStyle > &styles)
Compress a list of styles into a single style.
static QList< QgsConditionalStyle > matchingConditionalStyles(const QList< QgsConditionalStyle > &styles, const QVariant &value, QgsExpressionContext &context)
Find and return the matching styles for the value and feature.
QColor backgroundColor() const
The background color for style.
QColor textColor() const
The text color set for style.
QFont font() const
The font for the style.
bool validTextColor() const
Check if the text color is valid for render.
bool isValid() const
isValid Check if this rule is valid.
QPixmap icon() const
The icon set for style generated from the set symbol.
bool validBackgroundColor() const
Check if the background color is valid for render.
static std::vector< std::unique_ptr< QgsExpressionContextScope > > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
An expression node which takes its value from a feature's field.
QString name() const
The name of the column.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QString expression() const
Returns the original, unmodified expression string.
bool isField() const
Checks whether an expression consists only of a single field reference.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
bool isValid() const
Checks if this expression is valid.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
Qgis::FeatureRequestFilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
void setId(QgsFeatureId id)
Sets the feature id for this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
static QString fieldToolTipExtended(const QgsField &field, const QgsVectorLayer *layer, const QString &predefinedComment=QString())
Returns a HTML formatted tooltip string for a field, containing details like the field name,...
Encapsulate a field in an attribute table or data source.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
Encapsulates the context in which a QgsMapLayerAction action is executed.
An action which can run on map layers.
virtual Q_DECL_DEPRECATED void triggerForFeature(QgsMapLayer *layer, const QgsFeature &feature)
Triggers the action with the specified layer and feature.
static bool isUrl(const QString &string)
Returns whether the string is a URL (http,https,ftp,file).
Caches features for a given QgsVectorLayer.
void invalidated()
The cache has been invalidated and cleared.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer and this cache.
void cachedLayerDeleted()
Is emitted when the cached layer is deleted.
void attributeValueChanged(QgsFeatureId fid, int field, const QVariant &value)
Emitted when an attribute is changed.
void featureAboutToBeDeleted(QgsFeatureId fid)
Emitted when a feature is about to be deleted from this cache (as a result of a feature deletion from...
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature, QgsVectorLayerUtils::FieldIsEditableFlags flags=QgsVectorLayerUtils::FieldIsEditableFlags())
Tests whether a field is editable for a particular feature.
static bool attributeHasConstraints(const QgsVectorLayer *layer, int attributeIndex)
Returns true if a feature attribute has active constraints.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
void afterRollBack()
Emitted after changes are rolled back.
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
void beforeRollBack()
Emitted before changes are rolled back.
#define Q_NOWARN_DEPRECATED_POP
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
#define Q_NOWARN_DEPRECATED_PUSH
QSet< QgsFeatureId > QgsFeatureIds
#define FID_TO_STRING(fid)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)