44#include "moc_qgsattributetablemodel.cpp"
47 : QAbstractTableModel( parent )
55 mFeatureRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
58 mFeat.setId( std::numeric_limits<int>::min() );
60 if ( !mLayer->isSpatial() )
72 mIsCleaningUpAfterRollback =
true;
73 bulkEditCommandEnded();
74 mIsCleaningUpAfterRollback =
false;
83bool QgsAttributeTableModel::loadFeatureAtId(
QgsFeatureId fid )
const
87 if ( fid == std::numeric_limits<int>::min() )
92 return mLayerCache->featureAtId( fid, mFeat );
95bool QgsAttributeTableModel::loadFeatureAtId(
QgsFeatureId fid,
int fieldIdx )
const
99 if ( mLayerCache->cacheSubsetOfAttributes().contains(
fieldIdx ) )
101 return loadFeatureAtId( fid );
104 if ( fid == std::numeric_limits<int>::min() )
108 return mLayerCache->featureAtIdWithAllAttributes( fid, mFeat );
113 return mExtraColumns;
120 beginInsertColumns( QModelIndex(), mFieldCount + mExtraColumns, mFieldCount +
extraColumns - 1 );
126 beginRemoveColumns( QModelIndex(), mFieldCount +
extraColumns, mFieldCount + mExtraColumns - 1 );
132void QgsAttributeTableModel::featuresDeleted(
const QgsFeatureIds &fids )
136 const auto constFids = fids;
141 const int row =
idToRow( fid );
146 std::sort( rows.begin(), rows.end() );
150 int currentRowCount = 0;
154 const auto constRows = rows;
155 for (
const int row : constRows )
158 qDebug() <<
"Row: " << row <<
", begin " << beginRow <<
", last " << lastRow <<
", current " << currentRowCount <<
", removed " << removedRows;
165 if ( row != lastRow + 1 && lastRow != -1 )
167 if ( rows.count() > 100 && currentRowCount < 10 )
172 removeRows( beginRow - removedRows, currentRowCount );
175 removedRows += currentRowCount;
185 removeRows( beginRow - removedRows, currentRowCount );
192 if ( row < 0 || count < 1 )
195 if ( !mResettingModel )
197 beginRemoveRows( parent, row, row + count - 1 );
200 QgsDebugMsgLevel( QStringLiteral(
"remove %2 rows at %1 (rows %3, ids %4)" ).arg( row ).arg( count ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
202 if ( mBulkEditCommandRunning && !mResettingModel )
204 for (
int i = row; i < row + count; i++ )
207 mInsertedRowsChanges.removeOne( fid );
212 for (
int i = row; i < row + count; i++ )
214 for ( SortCache &cache : mSortCaches )
215 cache.sortCache.remove( mRowIdMap[i] );
216 mIdRowMap.remove( mRowIdMap[i] );
217 mRowIdMap.remove( i );
221 const int n = mRowIdMap.size() + count;
222 for (
int i = row + count; i < n; i++ )
225 mIdRowMap[id] -= count;
226 mRowIdMap[i - count] = id;
227 mRowIdMap.remove( i );
233 QgsDebugMsgLevel( QStringLiteral(
"after removal rows %1, ids %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );
235 for ( QHash<QgsFeatureId, int>::const_iterator it = mIdRowMap.constBegin(); it != mIdRowMap.constEnd(); ++it )
241 for ( QHash<int, QgsFeatureId>::const_iterator it = mRowIdMap.constBegin(); it != mRowIdMap.constEnd(); ++it )
248 Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
250 if ( !mResettingModel )
256void QgsAttributeTableModel::featureAdded(
QgsFeatureId fid )
261 if ( mFeat.
id() != fid )
262 featOk = loadFeatureAtId( fid );
266 for ( SortCache &cache : mSortCaches )
268 if ( cache.sortFieldIndex >= 0 )
270 const WidgetData &widgetData = getWidgetData( cache.sortFieldIndex );
271 const QVariant sortValue = widgetData.fieldFormatter->sortValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, mFeat.
attribute( cache.sortFieldIndex ) );
272 cache.sortCache.insert( mFeat.
id(), sortValue );
274 else if ( cache.sortCacheExpression.isValid() )
276 mExpressionContext.setFeature( mFeat );
277 cache.sortCache[mFeat.id()] = cache.sortCacheExpression.evaluate( &mExpressionContext );
282 if ( !mIdRowMap.contains( fid ) )
284 const int n = mRowIdMap.size();
285 if ( !mResettingModel )
286 beginInsertRows( QModelIndex(), n, n );
287 mIdRowMap.insert( fid, n );
288 mRowIdMap.insert( n, fid );
289 if ( !mResettingModel )
292 if ( mBulkEditCommandRunning && !mResettingModel )
294 mInsertedRowsChanges.append( fid );
300void QgsAttributeTableModel::updatedFields()
306void QgsAttributeTableModel::editCommandEnded()
310 bulkEditCommandEnded();
313void QgsAttributeTableModel::attributeDeleted(
int idx )
316 for (
const SortCache &cache : mSortCaches )
318 if ( cache.sortCacheAttributes.contains( idx ) )
326void QgsAttributeTableModel::layerDeleted()
328 mLayerCache =
nullptr;
333 mWidgetDatas.clear();
336void QgsAttributeTableModel::fieldFormatterRemoved(
QgsFieldFormatter *fieldFormatter )
338 for ( WidgetData &widgetData : mWidgetDatas )
340 if ( widgetData.fieldFormatter == fieldFormatter )
345void QgsAttributeTableModel::attributeValueChanged(
QgsFeatureId fid,
int idx,
const QVariant &value )
348 if ( mBulkEditCommandRunning )
350 mAttributeValueChanges.insert( QPair<QgsFeatureId, int>( fid, idx ), value );
353 QgsDebugMsgLevel( QStringLiteral(
"(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg(
qgsEnumValueToKey( mFeatureRequest.filterType() ) ), 2 );
355 for ( SortCache &cache : mSortCaches )
357 if ( cache.sortCacheAttributes.contains( idx ) )
359 if ( cache.sortFieldIndex == -1 )
361 if ( loadFeatureAtId( fid ) )
363 mExpressionContext.setFeature( mFeat );
364 cache.sortCache[fid] = cache.sortCacheExpression.evaluate( &mExpressionContext );
369 const WidgetData &widgetData = getWidgetData( cache.sortFieldIndex );
370 const QVariant sortValue = widgetData.fieldFormatter->representValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, value );
371 cache.sortCache.insert( fid, sortValue );
378 if ( loadFeatureAtId( fid ) )
380 const QModelIndex modelIndex = index(
idToRow( fid ),
fieldCol( idx ) );
381 setData( modelIndex, value, Qt::EditRole );
382 emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
387 if ( loadFeatureAtId( fid ) )
389 if ( mFeatureRequest.acceptFeature( mFeat ) )
391 if ( !mIdRowMap.contains( fid ) )
399 const QModelIndex modelIndex = index(
idToRow( fid ),
fieldCol( idx ) );
400 setData( modelIndex, value, Qt::EditRole );
401 emit dataChanged( modelIndex, modelIndex, QVector<int>() << Qt::DisplayRole );
406 if ( mIdRowMap.contains( fid ) )
417void QgsAttributeTableModel::loadAttributes()
424 const QgsFields fields = mLayer->fields();
425 if ( mFields == fields )
430 bool ins =
false, rm =
false;
434 mWidgetDatas.
clear();
436 for (
int idx = 0; idx < fields.
count(); ++idx )
441 if ( mFieldCount + mExtraColumns < attributes.size() + mExtraColumns )
444 beginInsertColumns( QModelIndex(), mFieldCount + mExtraColumns, attributes.size() - 1 );
446 else if ( attributes.size() + mExtraColumns < mFieldCount + mExtraColumns )
449 beginRemoveColumns( QModelIndex(), attributes.size(), mFieldCount + mExtraColumns - 1 );
452 mFieldCount = attributes.size();
453 mAttributes = attributes;
454 mWidgetDatas.resize( mFieldCount );
456 for ( SortCache &cache : mSortCaches )
458 if ( cache.sortFieldIndex >= mAttributes.count() )
459 cache.sortFieldIndex = -1;
481 mResettingModel =
true;
503 if ( t.elapsed() > 1000 )
512 featureAdded( mFeat.id() );
521 mResettingModel =
false;
527 if ( fieldName.isNull() )
529 mRowStylesMap.clear();
530 mConstraintStylesMap.clear();
535 const int fieldIndex = mLayer->fields().lookupField( fieldName );
536 if ( fieldIndex == -1 )
540 const int col =
fieldCol( fieldIndex );
541 emit dataChanged( index( 0, col ), index(
rowCount() - 1, col ) );
554 mRowIdMap.remove( rowA );
555 mRowIdMap.remove( rowB );
556 mRowIdMap.insert( rowA, b );
557 mRowIdMap.insert( rowB, a );
559 mIdRowMap.remove( a );
560 mIdRowMap.remove( b );
561 mIdRowMap.insert( a, rowB );
562 mIdRowMap.insert( b, rowA );
563 Q_ASSERT( mRowIdMap.size() == mIdRowMap.size() );
571 if ( !mIdRowMap.contains(
id ) )
573 QgsDebugError( QStringLiteral(
"idToRow: id %1 not in the map" ).arg(
id ) );
577 return mIdRowMap[id];
582 return index(
idToRow(
id ), 0 );
587 QModelIndexList indexes;
591 indexes.reserve( columns );
592 for (
int column = 0; column < columns; ++column )
594 indexes.append( index( row, column ) );
602 if ( !mRowIdMap.contains( row ) )
604 QgsDebugError( QStringLiteral(
"rowToId: row %1 not in the map" ).arg( row ) );
606 return std::numeric_limits<int>::min();
609 return mRowIdMap[row];
614 return mAttributes[col];
619 return mAttributes.indexOf( idx );
625 return mRowIdMap.size();
631 return std::max( 1, mFieldCount + mExtraColumns );
639 if ( role == Qt::DisplayRole )
641 if ( orientation == Qt::Vertical )
643 return QVariant( section );
645 else if ( section >= 0 && section < mFieldCount )
647 const QString attributeName = mLayer->fields().at( mAttributes.at( section ) ).displayName();
648 return QVariant( attributeName );
652 return tr(
"extra column" );
655 else if ( role == Qt::ToolTipRole )
657 if ( orientation == Qt::Vertical )
660 return tr(
"Feature ID: %1" ).arg(
rowToId( section ) );
664 const QgsField field = mLayer->fields().at( mAttributes.at( section ) );
676 if ( !index.isValid() || !mLayer || ( 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 ) ) )
684 if ( index.column() >= mFieldCount )
687 const int fieldId = mAttributes.at( index.column() );
694 const unsigned long cacheIndex = role -
static_cast<int>(
CustomRole::Sort );
695 if ( cacheIndex < mSortCaches.size() )
697 return mSortCaches.at( cacheIndex ).sortCache.value( rowId );
705 const QgsField field = mLayer->fields().at( fieldId );
707 if ( role == Qt::TextAlignmentRole )
709 const WidgetData &widgetData = getWidgetData( index.column() );
710 return static_cast<Qt::Alignment::Int
>( widgetData.fieldFormatter->
alignmentFlag( mLayer, fieldId, widgetData.config ) | Qt::AlignVCenter );
713 if ( mFeat.id() != rowId || !mFeat.isValid() || !mLayerCache->cacheSubsetOfAttributes().contains( fieldId ) )
715 if ( !loadFeatureAtId( rowId, fieldId ) )
716 return QVariant(
"ERROR" );
718 if ( mFeat.id() != rowId )
719 return QVariant(
"ERROR" );
722 QVariant val = mFeat.attribute( fieldId );
726 case Qt::DisplayRole:
728 const WidgetData &widgetData = getWidgetData( index.column() );
729 QString s = widgetData.fieldFormatter->
representValue( mLayer, fieldId, widgetData.config, widgetData.cache, val );
731 constexpr int MAX_STRING_LENGTH = 10 * 1000;
732 if (
static_cast<size_t>( s.size() ) >
static_cast<size_t>( MAX_STRING_LENGTH ) )
734 s.resize( MAX_STRING_LENGTH );
735 s.append( tr(
"... truncated ..." ) );
739 case Qt::ToolTipRole:
741 const WidgetData &widgetData = getWidgetData( index.column() );
742 QString tooltip = widgetData.fieldFormatter->
representValue( mLayer, fieldId, widgetData.config, widgetData.cache, val );
743 if ( tooltip != val.toString() )
745 tooltip = tr(
"%1 (%2)" ).arg( tooltip, val.toString() );
749 tooltip = tr(
"%1 (Ctrl+click to open)" ).arg( tooltip );
756 case Qt::BackgroundRole:
757 case Qt::ForegroundRole:
758 case Qt::DecorationRole:
761 mExpressionContext.setFeature( mFeat );
762 QList<QgsConditionalStyle> styles;
763 if ( mRowStylesMap.contains( mFeat.id() ) )
765 styles = mRowStylesMap[mFeat.id()];
770 mRowStylesMap.insert( mFeat.id(), styles );
777 if ( mConstraintStylesMap.contains( mFeat.id() ) && mConstraintStylesMap[mFeat.id()].contains( fieldId ) )
779 constraintstyle = mConstraintStylesMap[mFeat.id()][fieldId];
795 mConstraintStylesMap[mFeat.id()].insert( fieldId, constraintstyle );
799 styles = mLayer->conditionalStyles()->fieldStyles( field.
name() );
801 styles.insert( 0, rowstyle );
802 styles.insert( 0, constraintstyle );
809 if ( role == Qt::ForegroundRole )
811 if ( role == Qt::DecorationRole )
813 if ( role == Qt::FontRole )
818 if ( role == Qt::ForegroundRole )
820 return QColor( Qt::blue );
822 else if ( role == Qt::FontRole )
825 font.setUnderline(
true );
841 if ( !index.isValid() || index.column() >= mFieldCount || role != Qt::EditRole || !mLayer->isEditable() )
844 mRowStylesMap.remove( mFeat.id() );
845 mConstraintStylesMap.remove( mFeat.id() );
847 if ( !mLayer->isModified() )
855 if ( !index.isValid() )
856 return Qt::ItemIsEnabled;
858 if ( index.column() >= mFieldCount || !mLayer )
859 return Qt::NoItemFlags;
861 Qt::ItemFlags
flags = QAbstractTableModel::flags( index );
863 const int fieldIndex = mAttributes[index.column()];
867 flags |= Qt::ItemIsEditable;
872void QgsAttributeTableModel::bulkEditCommandStarted()
874 mBulkEditCommandRunning =
true;
875 mAttributeValueChanges.clear();
878void QgsAttributeTableModel::bulkEditCommandEnded()
880 mBulkEditCommandRunning =
false;
884 const long long fullModelUpdateThreshold = std::min<long long>( mLayerCache->cacheSize(), std::ceil(
rowCount() * 0.5 ) );
885 bool fullModelUpdate =
false;
888 if ( mInsertedRowsChanges.size() > fullModelUpdateThreshold )
890 fullModelUpdate =
true;
894 QSet<QgsFeatureId> changedRows;
895 changedRows.reserve( mAttributeValueChanges.size() );
897 for (
auto it = mAttributeValueChanges.constBegin(); it != mAttributeValueChanges.constEnd(); ++it )
899 changedRows.insert( it.key().first );
900 if ( changedRows.size() > fullModelUpdateThreshold )
902 fullModelUpdate =
true;
908 QgsDebugMsgLevel( QStringLiteral(
"Bulk edit command ended modified rows over (%3), cache size is %1, starting %2 update." ).arg( mLayerCache->cacheSize() ).arg( fullModelUpdate ? QStringLiteral(
"full" ) : QStringLiteral(
"incremental" ) ).arg(
rowCount() ), 3 );
911 if ( mIsCleaningUpAfterRollback )
913 for (
const int fid : std::as_const( mInsertedRowsChanges ) )
915 const int row(
idToRow( fid ) );
925 if ( fullModelUpdate )
928 emit mLayer->dataChanged();
937 const auto keys = mAttributeValueChanges.keys();
938 for (
const auto &key : keys )
940 attributeValueChanged( key.first, key.second, mAttributeValueChanges.value( key ) );
941 const int row(
idToRow( key.first ) );
942 const int col(
fieldCol( key.second ) );
943 minRow = std::min<int>( row, minRow );
944 minCol = std::min<int>( col, minCol );
945 maxRow = std::max<int>( row, maxRow );
946 maxCol = std::max<int>( col, maxCol );
949 emit dataChanged( createIndex( minRow, minCol ), createIndex( maxRow, maxCol ) );
951 mAttributeValueChanges.clear();
956 mFeat.setId( std::numeric_limits<int>::min() );
957 emit dataChanged( index1, index2 );
964 mLayer->actions()->doAction( action, f,
fieldIdx( idx.column() ) );
981 for (
int i = 0; i < mAttributes.size(); i++ )
983 f.
setAttribute( mAttributes[i],
data( index( idx.row(), i ), Qt::EditRole ) );
991 if ( column == -1 || column >= mAttributes.count() )
1006 if ( cacheIndex >= mSortCaches.size() )
1008 mSortCaches.resize( cacheIndex + 1 );
1010 SortCache &cache = mSortCaches[cacheIndex];
1011 cache.sortCache.clear();
1012 cache.sortCacheAttributes.clear();
1013 cache.sortFieldIndex = -1;
1014 if ( !expressionString.isEmpty() )
1015 cache.sortCacheExpression =
QgsExpression( expressionString );
1023 WidgetData widgetData;
1025 if ( cache.sortCacheExpression.
isField() )
1028 cache.sortFieldIndex = mLayer->fields().lookupField( fieldName );
1031 if ( cache.sortFieldIndex == -1 )
1033 cache.sortCacheExpression.
prepare( &mExpressionContext );
1035 const QSet<QString> &referencedColumns = cache.sortCacheExpression.
referencedColumns();
1037 for (
const QString &col : referencedColumns )
1039 cache.sortCacheAttributes.append( mLayer->fields().lookupField( col ) );
1044 cache.sortCacheAttributes.append( cache.sortFieldIndex );
1046 widgetData = getWidgetData( cache.sortFieldIndex );
1056 if ( cache.sortFieldIndex == -1 )
1058 mExpressionContext.setFeature( f );
1059 const QVariant cacheValue = cache.sortCacheExpression.
evaluate( &mExpressionContext );
1060 cache.sortCache.insert( f.
id(), cacheValue );
1064 const QVariant sortValue = widgetData.fieldFormatter->
sortValue( mLayer, cache.sortFieldIndex, widgetData.config, widgetData.cache, f.
attribute( cache.sortFieldIndex ) );
1065 cache.sortCache.insert( f.
id(), sortValue );
1072 QString expressionString;
1074 if ( cacheIndex >= mSortCaches.size() )
1075 return expressionString;
1077 const QgsExpression &expression = mSortCaches[cacheIndex].sortCacheExpression;
1082 expressionString = QString();
1084 return expressionString;
1089 if ( !mFeatureRequest.compare(
request ) )
1092 if ( mLayer && !mLayer->isSpatial() )
1095 for (
unsigned long i = 0; i < mSortCaches.size(); ++i )
1104 return mFeatureRequest;
1107const QgsAttributeTableModel::WidgetData &QgsAttributeTableModel::getWidgetData(
int column )
const
1109 Q_ASSERT( column >= 0 && column < mAttributes.size() );
1111 WidgetData &widgetData = mWidgetDatas[column];
1112 if ( !widgetData.loaded )
1114 const int idx =
fieldIdx( column );
1117 widgetData.config = setup.
config();
1118 widgetData.cache = widgetData.fieldFormatter->createCache( mLayer, idx, setup.
config() );
1119 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 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)
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.
void clear()
Removes all fields.
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)
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)