25 : QAbstractItemModel( parent )
27 mReloadTimer.setInterval( 100 );
28 mReloadTimer.setSingleShot(
true );
29 connect( &mReloadTimer, &QTimer::timeout,
this, &QgsFeatureFilterModel::scheduledReload );
30 setExtraIdentifierValueUnguarded( QVariant() );
36 connect( mGatherer, &QgsFieldExpressionValuesGatherer::finished, mGatherer, &QgsFieldExpressionValuesGatherer::deleteLater );
46 if ( mSourceLayer == sourceLayer )
77 if ( mFilterValue == filterValue )
87 return mFilterExpression;
92 if ( mFilterExpression == filterExpression )
108 return createIndex( row, column,
nullptr );
114 return QModelIndex();
121 return mEntries.size();
132 if ( !index.isValid() )
137 case Qt::DisplayRole:
140 return mEntries.value( index.row() ).value;
143 return mEntries.value( index.row() ).identifierValue;
145 case Qt::BackgroundColorRole:
146 case Qt::TextColorRole:
147 case Qt::DecorationRole:
150 if ( mEntries.value( index.row() ).identifierValue.isNull() )
153 if ( role == Qt::TextColorRole )
155 return QBrush( QColor( Qt::gray ) );
157 else if ( role == Qt::FontRole )
159 QFont font = QFont();
160 if ( index.row() == mExtraIdentifierValueIndex )
161 font.setBold(
true );
163 if ( mEntries.value( index.row() ).identifierValue.isNull() )
165 font.setItalic(
true );
181 if ( role == Qt::DecorationRole )
183 if ( role == Qt::FontRole )
194 void QgsFeatureFilterModel::updateCompleter()
197 QVector<Entry> entries = mGatherer->entries();
199 if ( mExtraIdentifierValueIndex == -1 )
200 setExtraIdentifierValueUnguarded( QVariant() );
203 if ( mGatherer->data().toBool() )
205 if ( !entries.isEmpty() )
207 mEntries.replace( mExtraIdentifierValueIndex, entries.at( 0 ) );
208 emit dataChanged(
index( mExtraIdentifierValueIndex, 0, QModelIndex() ),
index( mExtraIdentifierValueIndex, 0, QModelIndex() ) );
209 mShouldReloadCurrentFeature =
false;
210 setExtraValueDoesNotExist(
false );
214 setExtraValueDoesNotExist(
true );
217 mShouldReloadCurrentFeature =
false;
219 if ( mFilterValue.isEmpty() )
225 std::sort( entries.begin(), entries.end(), [](
const Entry & a,
const Entry & b ) {
return a.value.localeAwareCompare( b.value ) < 0; } );
230 const int newEntriesSize = entries.size();
233 int currentEntryInNewList = -1;
234 if ( mExtraIdentifierValueIndex != -1 )
236 for (
int i = 0; i < newEntriesSize; ++i )
238 if ( entries.at( i ).identifierValue == mExtraIdentifierValue )
240 currentEntryInNewList = i;
241 mEntries.replace( mExtraIdentifierValueIndex, entries.at( i ) );
242 emit dataChanged(
index( mExtraIdentifierValueIndex, 0, QModelIndex() ),
index( mExtraIdentifierValueIndex, 0, QModelIndex() ) );
243 setExtraValueDoesNotExist(
false );
250 Q_ASSERT_X(
false,
"QgsFeatureFilterModel::updateCompleter",
"No extra identifier value generated. Should not get here." );
256 if ( mExtraIdentifierValueIndex != -1 )
258 if ( mExtraIdentifierValueIndex != 0 )
260 beginMoveRows( QModelIndex(), mExtraIdentifierValueIndex, mExtraIdentifierValueIndex, QModelIndex(), 0 );
261 mEntries.move( mExtraIdentifierValueIndex, 0 );
268 beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow );
269 mEntries.remove( firstRow, mEntries.size() - firstRow );
272 if ( currentEntryInNewList == -1 )
274 beginInsertRows( QModelIndex(), 1, entries.size() + 1 );
277 setExtraIdentifierValueIndex( 0 );
281 if ( currentEntryInNewList != 0 )
283 beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 );
284 mEntries = entries.mid( 0, currentEntryInNewList ) + mEntries;
289 mEntries.replace( 0, entries.at( 0 ) );
292 emit dataChanged(
index( currentEntryInNewList, 0, QModelIndex() ),
index( currentEntryInNewList, 0, QModelIndex() ) );
294 beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 );
295 mEntries += entries.mid( currentEntryInNewList + 1 );
297 setExtraIdentifierValueIndex( currentEntryInNewList );
305 void QgsFeatureFilterModel::gathererThreadFinished()
312 void QgsFeatureFilterModel::scheduledReload()
317 bool wasLoading =
false;
323 disconnect( mGatherer, &QgsFieldExpressionValuesGatherer::collectedValues,
this, &QgsFeatureFilterModel::updateCompleter );
324 disconnect( mGatherer, &QgsFieldExpressionValuesGatherer::finished,
this, &QgsFeatureFilterModel::gathererThreadFinished );
325 connect( mGatherer, &QgsFieldExpressionValuesGatherer::finished, mGatherer, &QgsFieldExpressionValuesGatherer::deleteLater );
332 if ( mShouldReloadCurrentFeature )
338 QString filterClause;
340 if ( mFilterValue.isEmpty() && !mFilterExpression.isEmpty() )
341 filterClause = mFilterExpression;
342 else if ( mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
343 filterClause = QStringLiteral(
"(%1) ILIKE '%%2%'" ).arg( mDisplayExpression, mFilterValue );
344 else if ( !mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
345 filterClause = QStringLiteral(
"(%1) AND ((%2) ILIKE '%%3%')" ).arg( mFilterExpression, mDisplayExpression, mFilterValue );
347 if ( !filterClause.isEmpty() )
350 QSet<QString> attributes;
353 attributes << mIdentifierField;
360 mGatherer->setData( mShouldReloadCurrentFeature );
362 connect( mGatherer, &QgsFieldExpressionValuesGatherer::collectedValues,
this, &QgsFeatureFilterModel::updateCompleter );
363 connect( mGatherer, &QgsFieldExpressionValuesGatherer::finished,
this, &QgsFeatureFilterModel::gathererThreadFinished );
370 QSet<QString> QgsFeatureFilterModel::requestedAttributes()
const 372 QSet<QString> requestedAttrs;
382 if ( mDisplayExpression.
isField() )
393 return requestedAttrs;
396 void QgsFeatureFilterModel::setExtraIdentifierValueIndex(
int index,
bool force )
398 if ( mExtraIdentifierValueIndex ==
index && !force )
401 mExtraIdentifierValueIndex =
index;
405 void QgsFeatureFilterModel::reloadCurrentFeature()
407 mShouldReloadCurrentFeature =
true;
408 mReloadTimer.start();
411 void QgsFeatureFilterModel::setExtraIdentifierValueUnguarded(
const QVariant &
extraIdentifierValue )
413 const QVector<Entry> entries = mEntries;
416 for (
const Entry &entry : entries )
418 if ( entry.identifierValue == extraIdentifierValue
419 && entry.identifierValue.isNull() == extraIdentifierValue.isNull()
420 && entry.identifierValue.isValid() == extraIdentifierValue.isValid() )
422 setExtraIdentifierValueIndex( index );
430 if ( mExtraIdentifierValueIndex != index )
432 beginInsertRows( QModelIndex(), 0, 0 );
433 if ( extraIdentifierValue.isNull() )
436 mEntries.prepend( Entry( extraIdentifierValue, QStringLiteral(
"(%1)" ).arg( extraIdentifierValue.toString() ),
QgsFeature() ) );
439 setExtraIdentifierValueIndex( 0,
true );
441 reloadCurrentFeature();
463 styles += matchingFieldStyles;
468 mEntryStylesMap.insert( fid, style );
480 if ( mAllowNull == allowNull )
491 return mExtraValueDoesNotExist;
496 if ( mExtraValueDoesNotExist == extraValueDoesNotExist )
505 return mExtraIdentifierValueIndex;
510 return mIdentifierField;
515 if ( mIdentifierField == identifierField )
522 void QgsFeatureFilterModel::reload()
524 mReloadTimer.start();
529 return mExtraIdentifierValue;
534 if (
qgsVariantEqual( extraIdentifierValue, mExtraIdentifierValue ) && mExtraIdentifierValue.isValid() )
537 if ( mIsSettingExtraIdentifierValue )
540 mIsSettingExtraIdentifierValue =
true;
544 setExtraIdentifierValueUnguarded( extraIdentifierValue );
546 mIsSettingExtraIdentifierValue =
false;
Class for parsing and evaluation of expressions (formerly called "search strings").
void filterValueChanged()
This value will be used to filter the features available from this model.
bool allowNull() const
Add a NULL entry to the list.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
void beginUpdate()
Notification that the model is about to be changed because a job was completed.
This class is a composition of two QSettings instances:
int rowCount(const QModelIndex &parent) const override
Used to retrieve the displayExpression of a feature.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setFilterExpression(const QString &filterExpression)
An additional filter expression to apply, next to the filterValue.
QString filterValue() const
This value will be used to filter the features available from this model.
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName)
Returns the conditional styles set for the field UI properties.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QVariant extraIdentifierValue() const
Allows specifying one value that does not need to match the filter criteria but will still be availab...
void filterJobCompleted()
Indicates that a filter job has been completed and new data may be available.
bool validBackgroundColor() const
Check if the background color is valid for render.
QPixmap icon() const
The icon set for style generated from the set symbol.
bool extraValueDoesNotExist() const
Flag indicating that the extraIdentifierValue does not exist in the data.
void extraIdentifierValueIndexChanged(int index)
The index at which the extra identifier value is available within the model.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
friend class QgsFieldExpressionValuesGatherer
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
QgsExpression * filterExpression() const
Returns the filter expression if set.
int extraIdentifierValueIndex() const
The index at which the extra identifier value is available within the model.
QList< QgsConditionalStyle > rowStyles()
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void identifierFieldChanged()
The identifier field should be a unique field that can be used to identify individual features...
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Conditional styling for a rule.
QString displayExpression() const
The display expression will be used for.
bool isValid() const
isValid Check if this rule is valid.
static QList< QgsConditionalStyle > matchingConditionalStyles(const QList< QgsConditionalStyle > &styles, const QVariant &value, QgsExpressionContext &context)
Find and return the matching styles for the value and feature.
void setFilterValue(const QString &filterValue)
This value will be used to filter the features available from this model.
QModelIndex index(int row, int column, const QModelIndex &parent) const override
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QColor backgroundColor() const
The background color for style.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
static QgsConditionalStyle compressStyles(const QList< QgsConditionalStyle > &styles)
Compress a list of styles into a single style.
void isLoadingChanged()
Indicator if the model is currently performing any feature iteration in the background.
QModelIndex parent(const QModelIndex &child) const override
void allowNullChanged()
Add a NULL entry to the list.
QgsFeatureFilterModel(QObject *parent=nullptr)
Create a new QgsFeatureFilterModel, optionally specifying a parent.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool isLoading() const
Indicator if the model is currently performing any feature iteration in the background.
QString filterExpression() const
An additional filter expression to apply, next to the filterValue.
void filterExpressionChanged()
An additional filter expression to apply, next to the filterValue.
void endUpdate()
Notification that the model change is finished.
QString identifierField() const
The identifier field should be a unique field that can be used to identify individual features...
QString expression() const
Returns the original, unmodified expression string.
int columnCount(const QModelIndex &parent) const override
void extraIdentifierValueChanged()
Allows specifying one value that does not need to match the filter criteria but will still be availab...
void setIdentifierField(const QString &identifierField)
The identifier field should be a unique field that can be used to identify individual features...
void setSourceLayer(QgsVectorLayer *sourceLayer)
The source layer from which features will be fetched.
QColor textColor() const
The text color set for style.
void sourceLayerChanged()
The source layer from which features will be fetched.
bool validTextColor() const
Check if the text color is valid for render.
bool isField() const
Checks whether an expression consists only of a single field reference.
void setExtraIdentifierValue(const QVariant &extraIdentifierValue)
Allows specifying one value that does not need to match the filter criteria but will still be availab...
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
QVariant data(const QModelIndex &index, int role) const override
void setAllowNull(bool allowNull)
Add a NULL entry to the list.
QFont font() const
The font for the style.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required...
QgsVectorLayer * sourceLayer() const
The source layer from which features will be fetched.
bool qgsVariantEqual(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether they are equal, NULL values are treated as equal...
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Used to retrieve the identifierValue (primary key) of a feature.
void setDisplayExpression(const QString &displayExpression)
The display expression will be used for.
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
void extraValueDoesNotExistChanged()
Flag indicating that the extraIdentifierValue does not exist in the data.
~QgsFeatureFilterModel() override
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
void displayExpressionChanged()
The display expression will be used for.