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() )
75 mIsCleaningUpAfterRollback =
true;
76 bulkEditCommandEnded();
77 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 );
116 return mExtraColumns;
123 beginInsertColumns( QModelIndex(), mFieldCount + mExtraColumns, mFieldCount +
extraColumns - 1 );
129 beginRemoveColumns( QModelIndex(), mFieldCount +
extraColumns, mFieldCount + mExtraColumns - 1 );
135void QgsAttributeTableModel::featuresDeleted(
const QgsFeatureIds &fids )
139 const auto constFids = fids;
144 const int row =
idToRow( fid );
149 std::sort( rows.begin(), rows.end() );
153 int currentRowCount = 0;
157 const auto constRows = rows;
158 for (
const int row : constRows )
161 qDebug() <<
"Row: " << row <<
", begin " << beginRow <<
", last " << lastRow <<
", current " << currentRowCount <<
", removed " << removedRows;
168 if ( row != lastRow + 1 && lastRow != -1 )
170 if ( rows.count() > 100 && currentRowCount < 10 )
175 removeRows( beginRow - removedRows, currentRowCount );
178 removedRows += currentRowCount;
188 removeRows( beginRow - removedRows, currentRowCount );
195 if ( row < 0 || count < 1 )
198 if ( !mResettingModel )
200 beginRemoveRows( parent, row, row + count - 1 );
203 QgsDebugMsgLevel( u
"remove %2 rows at %1 (rows %3, ids %4)"_s.arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
205 if ( mBulkEditCommandRunning && !mResettingModel )
207 for (
int i = row; i < row + count; i++ )
210 mInsertedRowsChanges.removeOne( fid );
215 for (
int i = row; i < row + count; i++ )
217 for ( SortCache &cache : mSortCaches )
218 cache.sortCache.remove( mRowIdMap[i] );
219 mIdRowMap.remove( mRowIdMap[i] );
220 mRowIdMap.remove( i );
224 const int n = mRowIdMap.size() + count;
225 for (
int i = row + count; i < n; i++ )
228 mIdRowMap[id] -= count;
229 mRowIdMap[i - count] = id;
230 mRowIdMap.remove( i );
236 QgsDebugMsgLevel( u
"after removal rows %1, ids %2"_s.arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
238 for ( QHash<QgsFeatureId, int>::const_iterator it = mIdRowMap.constBegin(); it != mIdRowMap.constEnd(); ++it )
244 for ( QHash<int, QgsFeatureId>::const_iterator it = mRowIdMap.constBegin(); it != mRowIdMap.constEnd(); ++it )
251 Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
253 if ( !mResettingModel )
259void QgsAttributeTableModel::featureAdded(
QgsFeatureId fid )
264 if ( mFeat.
id() != fid )
265 featOk = loadFeatureAtId( fid );
269 for ( SortCache &cache : mSortCaches )
271 if ( cache.sortFieldIndex >= 0 )
273 const WidgetData &widgetData = getWidgetData( cache.sortFieldIndex );
274 const QVariant sortValue = widgetData.fieldFormatter->sortValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, mFeat.
attribute( cache.sortFieldIndex ) );
275 cache.sortCache.insert( mFeat.
id(), sortValue );
277 else if ( cache.sortCacheExpression.isValid() )
279 mExpressionContext.setFeature( mFeat );
280 cache.sortCache[mFeat.id()] = cache.sortCacheExpression.evaluate( &mExpressionContext );
285 if ( !mIdRowMap.contains( fid ) )
287 const int n = mRowIdMap.size();
288 if ( !mResettingModel )
289 beginInsertRows( QModelIndex(), n, n );
290 mIdRowMap.insert( fid, n );
291 mRowIdMap.insert( n, fid );
292 if ( !mResettingModel )
296 const QModelIndex first = index( row, 0 );
298 const QModelIndex last = index( row, lastColumn );
300 if ( mBulkEditCommandRunning && !mResettingModel )
302 mInsertedRowsChanges.append( fid );
308void QgsAttributeTableModel::updatedFields()
314void QgsAttributeTableModel::editCommandEnded()
318 bulkEditCommandEnded();
321void QgsAttributeTableModel::attributeDeleted(
int idx )
324 for (
const SortCache &cache : mSortCaches )
326 if ( cache.sortCacheAttributes.contains( idx ) )
334void QgsAttributeTableModel::layerDeleted()
336 mLayerCache =
nullptr;
341 mWidgetDatas.clear();
344void QgsAttributeTableModel::fieldFormatterRemoved(
QgsFieldFormatter *fieldFormatter )
346 for ( WidgetData &widgetData : mWidgetDatas )
348 if ( widgetData.fieldFormatter == fieldFormatter )
353void QgsAttributeTableModel::attributeValueChanged(
QgsFeatureId fid,
int idx,
const QVariant &value )
356 if ( mBulkEditCommandRunning )
358 mAttributeValueChanges.insert( QPair<QgsFeatureId, int>( fid, idx ), value );
361 QgsDebugMsgLevel( u
"(%4) fid: %1, idx: %2, value: %3"_s.arg( fid ).arg( idx ).arg( value.toString() ).arg(
qgsEnumValueToKey( mFeatureRequest.filterType() ) ), 2 );
363 for ( SortCache &cache : mSortCaches )
365 if ( cache.sortCacheAttributes.contains( idx ) )
367 if ( cache.sortFieldIndex == -1 )
369 if ( loadFeatureAtId( fid ) )
371 mExpressionContext.setFeature( mFeat );
372 cache.sortCache[fid] = cache.sortCacheExpression.evaluate( &mExpressionContext );
377 const WidgetData &widgetData = getWidgetData( cache.sortFieldIndex );
378 const QVariant sortValue = widgetData.fieldFormatter->representValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, value );
379 cache.sortCache.insert( fid, sortValue );
386 if ( loadFeatureAtId( fid ) )
388 const QModelIndex modelIndex = index(
idToRow( fid ),
fieldCol( idx ) );
389 setData( modelIndex, value, Qt::EditRole );
390 emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
395 if ( loadFeatureAtId( fid ) )
397 if ( mFeatureRequest.acceptFeature( mFeat ) )
399 if ( !mIdRowMap.contains( fid ) )
407 const QModelIndex modelIndex = index(
idToRow( fid ),
fieldCol( idx ) );
408 setData( modelIndex, value, Qt::EditRole );
409 emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
414 if ( mIdRowMap.contains( fid ) )
425void QgsAttributeTableModel::loadAttributes()
432 const QgsFields fields = mLayer->fields();
433 if ( mFields == fields )
436 bool ins =
false, rm =
false;
440 for (
int idx = 0; idx < fields.
count(); ++idx )
445 if ( mFieldCount + mExtraColumns < attributes.size() + mExtraColumns )
448 beginInsertColumns( QModelIndex(), mFieldCount + mExtraColumns, attributes.size() - 1 );
450 else if ( attributes.size() + mExtraColumns < mFieldCount + mExtraColumns )
453 beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount + mExtraColumns - 1 );
458 mFieldCount = attributes.size();
459 mAttributes = attributes;
460 mWidgetDatas.clear();
461 mWidgetDatas.resize( mFieldCount );
463 for ( SortCache &cache : mSortCaches )
465 if ( cache.sortFieldIndex >= mAttributes.count() )
466 cache.sortFieldIndex = -1;
488 mResettingModel =
true;
510 if ( t.elapsed() > 1000 )
519 featureAdded( mFeat.id() );
528 mResettingModel =
false;
534 if ( fieldName.isNull() )
536 mRowStylesMap.clear();
537 mConstraintStylesMap.clear();
542 const int fieldIndex = mLayer->fields().lookupField( fieldName );
543 if ( fieldIndex == -1 )
547 const int col =
fieldCol( fieldIndex );
548 emit dataChanged( index( 0, col ), index(
rowCount() - 1, col ) );
561 mRowIdMap.remove( rowA );
562 mRowIdMap.remove( rowB );
563 mRowIdMap.insert( rowA, b );
564 mRowIdMap.insert( rowB, a );
566 mIdRowMap.remove( a );
567 mIdRowMap.remove( b );
568 mIdRowMap.insert( a, rowB );
569 mIdRowMap.insert( b, rowA );
570 Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
578 if ( !mIdRowMap.contains(
id ) )
580 QgsDebugError( u
"idToRow: id %1 not in the map"_s.arg(
id ) );
584 return mIdRowMap[id];
589 return index(
idToRow(
id ), 0 );
594 QModelIndexList indexes;
598 indexes.reserve( columns );
599 for (
int column = 0; column < columns; ++column )
601 indexes.append( index( row, column ) );
609 if ( !mRowIdMap.contains( row ) )
611 QgsDebugError( u
"rowToId: row %1 not in the map"_s.arg( row ) );
613 return std::numeric_limits<int>::min();
616 return mRowIdMap[row];
621 return mAttributes[col];
626 return mAttributes.indexOf( idx );
631 if ( parent.isValid() )
634 return mRowIdMap.size();
639 if ( parent.isValid() )
642 return std::max( 1, mFieldCount + mExtraColumns );
650 if ( role == Qt::DisplayRole )
652 if ( orientation == Qt::Vertical )
654 return QVariant( section );
656 else if ( section >= 0 && section < mFieldCount )
658 const QString attributeName = mLayer->fields().at( mAttributes.at( section ) ).displayName();
659 return QVariant( attributeName );
663 return tr(
"extra column" );
666 else if ( role == Qt::ToolTipRole )
668 if ( orientation == Qt::Vertical )
671 return tr(
"Feature ID: %1" ).arg(
rowToId( section ) );
675 const QgsField field = mLayer->fields().at( mAttributes.at( section ) );
687 if ( !index.isValid()
689 || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::ToolTipRole && role != Qt::EditRole && role !=
static_cast<int>(
CustomRole::FeatureId ) && role !=
static_cast<int>(
CustomRole::FieldIndex ) && role != Qt::BackgroundRole && role != Qt::ForegroundRole && role != Qt::DecorationRole && role != Qt::FontRole && role <
static_cast<int>(
CustomRole::Sort ) ) )
697 if ( index.column() >= mFieldCount )
700 const int fieldId = mAttributes.at( index.column() );
707 const unsigned long cacheIndex = role -
static_cast<int>(
CustomRole::Sort );
708 if ( cacheIndex < mSortCaches.size() )
710 return mSortCaches.at( cacheIndex ).sortCache.value( rowId );
718 const QgsField field = mFields.at( fieldId );
720 if ( role == Qt::TextAlignmentRole )
722 const WidgetData &widgetData = getWidgetData( index.column() );
723 return static_cast<Qt::Alignment::Int
>( widgetData.fieldFormatter->
alignmentFlag( field, widgetData.config ) | Qt::AlignVCenter );
726 if ( mFeat.id() != rowId || !mFeat.isValid() || !mLayerCache->cacheSubsetOfAttributes().contains( fieldId ) )
728 if ( !loadFeatureAtId( rowId, fieldId ) )
729 return QVariant(
"ERROR" );
731 if ( mFeat.id() != rowId )
732 return QVariant(
"ERROR" );
735 QVariant val = mFeat.attribute( fieldId );
739 case Qt::DisplayRole:
741 const WidgetData &widgetData = getWidgetData( index.column() );
742 QString s = widgetData.fieldFormatter->
representValue( mLayer, fieldId, widgetData.config, widgetData.cache, val );
744 constexpr int MAX_STRING_LENGTH = 10 * 1000;
745 if (
static_cast<size_t>( s.size() ) >
static_cast<size_t>( MAX_STRING_LENGTH ) )
747 s.resize( MAX_STRING_LENGTH );
748 s.append( tr(
"... truncated ..." ) );
752 case Qt::ToolTipRole:
754 const WidgetData &widgetData = getWidgetData( index.column() );
755 QString tooltip = widgetData.fieldFormatter->
representValue( mLayer, fieldId, widgetData.config, widgetData.cache, val );
756 if ( tooltip != val.toString() )
758 tooltip = tr(
"%1 (%2)" ).arg( tooltip, val.toString() );
762 tooltip = tr(
"%1 (Ctrl+click to open)" ).arg( tooltip );
769 case Qt::BackgroundRole:
770 case Qt::ForegroundRole:
771 case Qt::DecorationRole:
774 mExpressionContext.setFeature( mFeat );
775 QList<QgsConditionalStyle> styles;
776 if ( mRowStylesMap.contains( mFeat.id() ) )
778 styles = mRowStylesMap[mFeat.id()];
783 mRowStylesMap.insert( mFeat.id(), styles );
790 if ( mConstraintStylesMap.contains( mFeat.id() ) && mConstraintStylesMap[mFeat.id()].contains( fieldId ) )
792 constraintstyle = mConstraintStylesMap[mFeat.id()][fieldId];
808 mConstraintStylesMap[mFeat.id()].insert( fieldId, constraintstyle );
812 styles = mLayer->conditionalStyles()->fieldStyles( field.
name() );
814 styles.insert( 0, rowstyle );
815 styles.insert( 0, constraintstyle );
824 if ( role == Qt::DecorationRole )
826 if ( role == Qt::FontRole )
831 if ( role == Qt::ForegroundRole )
833 return QColor( Qt::blue );
835 else if ( role == Qt::FontRole )
838 font.setUnderline(
true );
854 if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !mLayer->isEditable() )
857 mRowStylesMap.remove( mFeat.id() );
858 mConstraintStylesMap.remove( mFeat.id() );
860 if ( !mLayer->isModified() )
868 if ( !index.isValid() )
869 return Qt::NoItemFlags;
871 if ( index.column() >= mFieldCount || !mLayer )
872 return Qt::NoItemFlags;
874 Qt::ItemFlags
flags = QAbstractTableModel::flags( index );
876 const int fieldIndex = mAttributes[index.column()];
880 flags |= Qt::ItemIsEditable;
885void QgsAttributeTableModel::bulkEditCommandStarted()
887 mBulkEditCommandRunning =
true;
888 mAttributeValueChanges.clear();
891void QgsAttributeTableModel::bulkEditCommandEnded()
893 mBulkEditCommandRunning =
false;
897 const long long fullModelUpdateThreshold = std::min<long long>( mLayerCache->cacheSize(), std::ceil(
rowCount() * 0.5 ) );
898 bool fullModelUpdate =
false;
901 if ( mInsertedRowsChanges.size() > fullModelUpdateThreshold )
903 fullModelUpdate =
true;
907 QSet<QgsFeatureId> changedRows;
908 changedRows.reserve( mAttributeValueChanges.size() );
910 for (
auto it = mAttributeValueChanges.constBegin(); it != mAttributeValueChanges.constEnd(); ++it )
912 changedRows.insert( it.key().first );
913 if ( changedRows.size() > fullModelUpdateThreshold )
915 fullModelUpdate =
true;
921 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 );
924 if ( mIsCleaningUpAfterRollback )
926 for (
const int fid : std::as_const( mInsertedRowsChanges ) )
928 const int row(
idToRow( fid ) );
938 if ( fullModelUpdate )
941 emit mLayer->dataChanged();
947 else if ( !mAttributeValueChanges.empty() && !mInsertedRowsChanges.empty() )
949 int minRow = std::numeric_limits< int >::max();
950 int minCol = std::numeric_limits< int >::max();
954 for (
auto it = mAttributeValueChanges.constBegin(); it != mAttributeValueChanges.constEnd(); ++it )
956 attributeValueChanged( it.key().first, it.key().second, it.value() );
957 const int row(
idToRow( it.key().first ) );
958 const int col(
fieldCol( it.key().second ) );
959 minRow = std::min<int>( row, minRow );
960 minCol = std::min<int>( col, minCol );
961 maxRow = std::max<int>( row, maxRow );
962 maxCol = std::max<int>( col, maxCol );
965 for (
QgsFeatureId fid : std::as_const( mInsertedRowsChanges ) )
967 const int row(
idToRow( fid ) );
968 minRow = std::min<int>( row, minRow );
969 maxRow = std::max<int>( row, maxRow );
975 Q_ASSERT_X( minRow >= 0 && minRow <
rowCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid minRow, got %1 expected >=0 && < %2"_s.arg( minRow ).arg(
rowCount() ).toLocal8Bit().constData() );
976 Q_ASSERT_X( minCol >= 0 && minCol <
columnCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid minCol, got %1 expected >=0 && < %2"_s.arg( minCol ).arg(
columnCount() ).toLocal8Bit().constData() );
977 Q_ASSERT_X( maxRow >= 0 && maxRow <
rowCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid maxRow, got %1 expected >=0 && < %2"_s.arg( maxRow ).arg(
rowCount() ).toLocal8Bit().constData() );
978 Q_ASSERT_X( maxCol >= 0 && maxCol <
columnCount(),
"QgsAttributeTableModel::bulkEditCommandEnded", u
"Invalid maxCol, got %1 expected >=0 && < %2"_s.arg( maxCol ).arg(
columnCount() ).toLocal8Bit().constData() );
981 emit dataChanged( createIndex( minRow, minCol ), createIndex( maxRow, maxCol ) );
983 mAttributeValueChanges.clear();
988 mFeat.setId( std::numeric_limits<int>::min() );
991 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() );
993 index1.column() >= 0 && index1.column() <
columnCount(),
994 "QgsAttributeTableModel::reload",
995 u
"Invalid min col, got %1 expected >=0 && < %2"_s.arg( index1.column() ).arg(
columnCount() ).toLocal8Bit().constData()
997 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() );
999 index2.column() >= 0 && index2.column() <
columnCount(),
1000 "QgsAttributeTableModel::reload",
1001 u
"Invalid max col, got %1 expected >=0 && < %2"_s.arg( index2.column() ).arg(
columnCount() ).toLocal8Bit().constData()
1003 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() );
1004 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() );
1007 if ( !mResettingModel )
1009 emit dataChanged( index1, index2 );
1016 mLayer->actions()->doAction( action, f,
fieldIdx( idx.column() ) );
1033 for (
int i = 0; i < mAttributes.size(); i++ )
1035 f.
setAttribute( mAttributes[i],
data( index( idx.row(), i ), Qt::EditRole ) );
1043 if ( column == -1 || column >= mAttributes.count() )
1058 if ( cacheIndex >= mSortCaches.size() )
1060 mSortCaches.resize( cacheIndex + 1 );
1062 SortCache &cache = mSortCaches[cacheIndex];
1063 cache.sortCache.clear();
1064 cache.sortCacheAttributes.clear();
1065 cache.sortFieldIndex = -1;
1066 if ( !expressionString.isEmpty() )
1067 cache.sortCacheExpression =
QgsExpression( expressionString );
1075 WidgetData widgetData;
1077 if ( cache.sortCacheExpression.
isField() )
1080 cache.sortFieldIndex = mLayer->fields().lookupField( fieldName );
1083 if ( cache.sortFieldIndex == -1 )
1085 cache.sortCacheExpression.
prepare( &mExpressionContext );
1087 const QSet<QString> &referencedColumns = cache.sortCacheExpression.
referencedColumns();
1089 for (
const QString &col : referencedColumns )
1091 cache.sortCacheAttributes.append( mLayer->fields().lookupField( col ) );
1096 cache.sortCacheAttributes.append( cache.sortFieldIndex );
1098 widgetData = getWidgetData( cache.sortFieldIndex );
1110 if ( cache.sortFieldIndex == -1 )
1112 mExpressionContext.setFeature( f );
1113 const QVariant cacheValue = cache.sortCacheExpression.
evaluate( &mExpressionContext );
1114 cache.sortCache.insert( f.
id(), cacheValue );
1118 const QVariant sortValue = widgetData.fieldFormatter->
sortValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, f.
attribute( cache.sortFieldIndex ) );
1119 cache.sortCache.insert( f.
id(), sortValue );
1126 QString expressionString;
1128 if ( cacheIndex >= mSortCaches.size() )
1129 return expressionString;
1131 const QgsExpression &expression = mSortCaches[cacheIndex].sortCacheExpression;
1136 expressionString = QString();
1138 return expressionString;
1143 if ( !mFeatureRequest.compare(
request ) )
1146 if ( mLayer && !mLayer->isSpatial() )
1149 for (
unsigned long i = 0; i < mSortCaches.size(); ++i )
1158 return mFeatureRequest;
1161const QgsAttributeTableModel::WidgetData &QgsAttributeTableModel::getWidgetData(
int column )
const
1163 Q_ASSERT( column >= 0 && column < mAttributes.size() );
1165 WidgetData &widgetData = mWidgetDatas[column];
1166 if ( !widgetData.loaded )
1168 const int idx =
fieldIdx( column );
1171 widgetData.config = setup.
config();
1172 widgetData.cache = widgetData.fieldFormatter->createCache( mLayer, idx, setup.
config() );
1173 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.
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.
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...
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.
@ 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 QList< 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.
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 featuresDeleted(const QgsFeatureIds &fids)
Emitted when features have been deleted.
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)