mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-02 00:02:12 -05:00
get rid of model types and cache
This commit is contained in:
parent
7c005d7c07
commit
265740fd5a
@ -48,22 +48,21 @@ Item {
|
||||
property var currentEditorValue: value
|
||||
|
||||
comboStyle: customStyle.fields
|
||||
textRole: 'display'
|
||||
textRole: 'FeatureTitle'
|
||||
height: parent.height
|
||||
|
||||
model: QgsQuick.FeaturesListModel {
|
||||
id: vrModel
|
||||
modelType: QgsQuick.FeaturesListModel.ValueRelation
|
||||
|
||||
// recalculate index when model changes
|
||||
onModelReset: {
|
||||
combobox.currentIndex = vrModel.rowModelIndexFromKey( value )
|
||||
combobox.currentIndex = vrModel.rowFromAttribute( QgsQuick.FeaturesListModel.KeyColumn, value )
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
vrModel.populate(config)
|
||||
currentIndex = vrModel.rowModelIndexFromKey( value )
|
||||
vrModel.setupValueRelation( config )
|
||||
currentIndex = vrModel.rowFromAttribute( QgsQuick.FeaturesListModel.KeyColumn, value )
|
||||
}
|
||||
|
||||
onPressedChanged: {
|
||||
@ -76,13 +75,13 @@ Item {
|
||||
|
||||
// Called when user makes selection in the combo box
|
||||
onItemClicked: {
|
||||
currentIndex = vrModel.rowModelIndexFromKey( index )
|
||||
valueChanged( index, false )
|
||||
currentIndex = vrModel.rowFromAttribute( QgsQuick.FeaturesListModel.FeatureId, index )
|
||||
valueChanged( vrModel.keyFromAttribute( QgsQuick.FeaturesListModel.FeatureId, index ), false )
|
||||
}
|
||||
|
||||
// Called when the same form is used for a different feature
|
||||
onCurrentEditorValueChanged: {
|
||||
currentIndex = vrModel.rowModelIndexFromKey( value );
|
||||
currentIndex = vrModel.rowFromAttribute( QgsQuick.FeaturesListModel.KeyColumn, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,21 +19,10 @@
|
||||
|
||||
QgsQuickFeaturesListModel::QgsQuickFeaturesListModel( QObject *parent )
|
||||
: QAbstractListModel( parent ),
|
||||
mCurrentLayer( nullptr ),
|
||||
mModelType( modelTypes::FeatureListing )
|
||||
mCurrentLayer( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
QgsQuickFeatureLayerPair QgsQuickFeaturesListModel::featureLayerPair( const int &featureId )
|
||||
{
|
||||
for ( const QgsQuickFeatureLayerPair &i : mFeatures )
|
||||
{
|
||||
if ( i.feature().id() == featureId )
|
||||
return i;
|
||||
}
|
||||
return QgsQuickFeatureLayerPair();
|
||||
}
|
||||
|
||||
int QgsQuickFeaturesListModel::rowCount( const QModelIndex &parent ) const
|
||||
{
|
||||
// For list models only the root node (an invalid parent) should return the list's size. For all
|
||||
@ -46,15 +35,24 @@ int QgsQuickFeaturesListModel::rowCount( const QModelIndex &parent ) const
|
||||
|
||||
QVariant QgsQuickFeaturesListModel::featureTitle( const QgsQuickFeatureLayerPair &featurePair ) const
|
||||
{
|
||||
QString title;
|
||||
|
||||
if ( !mFeatureTitleField.isEmpty() )
|
||||
{
|
||||
title = featurePair.feature().attribute( mFeatureTitleField ).toString();
|
||||
if ( !title.isEmpty() )
|
||||
return title;
|
||||
}
|
||||
|
||||
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( featurePair.layer() ) );
|
||||
context.setFeature( featurePair.feature() );
|
||||
QgsExpression expr( featurePair.layer()->displayExpression() );
|
||||
const QString title = expr.evaluate( &context ).toString();
|
||||
title = expr.evaluate( &context ).toString();
|
||||
|
||||
if ( title.isEmpty() )
|
||||
return QVariant( featurePair.feature().id() );
|
||||
return featurePair.feature().id();
|
||||
|
||||
return QVariant( title );
|
||||
return title;
|
||||
}
|
||||
|
||||
QVariant QgsQuickFeaturesListModel::data( const QModelIndex &index, int role ) const
|
||||
@ -74,21 +72,9 @@ QVariant QgsQuickFeaturesListModel::data( const QModelIndex &index, int role ) c
|
||||
case FeatureId: return QVariant( pair.feature().id() );
|
||||
case Feature: return QVariant::fromValue<QgsFeature>( pair.feature() );
|
||||
case Description: return QVariant( QString( "Feature ID %1" ).arg( pair.feature().id() ) );
|
||||
case EmitableIndex:
|
||||
{
|
||||
if ( mModelType == modelTypes::ValueRelation )
|
||||
return pair.feature().attribute( mKeyFieldName );
|
||||
return pair.feature().id();
|
||||
}
|
||||
case KeyColumn: return mKeyField.isEmpty() ? QVariant() : pair.feature().attribute( mKeyField );
|
||||
case FoundPair: return foundPair( pair );
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
if ( row >= 0 && row < mCache.count() )
|
||||
{
|
||||
int r = rowIndexFromKey( pair.feature().attribute( mKeyFieldName ) );
|
||||
return mCache[r].value;
|
||||
}
|
||||
}
|
||||
case Qt::DisplayRole: return featureTitle( pair );
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@ -163,19 +149,20 @@ void QgsQuickFeaturesListModel::loadFeaturesFromLayer( QgsVectorLayer *layer )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsQuickFeaturesListModel::populate( const QVariantMap &config )
|
||||
void QgsQuickFeaturesListModel::setupValueRelation( const QVariantMap &config )
|
||||
{
|
||||
beginResetModel();
|
||||
emptyData();
|
||||
|
||||
mCache = QgsValueRelationFieldFormatter::createCache( config );
|
||||
QgsVectorLayer *layer = QgsValueRelationFieldFormatter::resolveLayer( config, QgsProject::instance() );
|
||||
|
||||
if ( layer )
|
||||
{
|
||||
// save key field
|
||||
// save key and value field
|
||||
QgsFields fields = layer->fields();
|
||||
mKeyFieldName = fields.field( config.value( QStringLiteral( "Key" ) ).toString() ).name();
|
||||
|
||||
setKeyField( fields.field( config.value( QStringLiteral( "Key" ) ).toString() ).name() );
|
||||
setFeatureTitleField( fields.field( config.value( QStringLiteral( "Value" ) ).toString() ).name() );
|
||||
|
||||
loadFeaturesFromLayer( layer );
|
||||
}
|
||||
@ -201,8 +188,8 @@ void QgsQuickFeaturesListModel::emptyData()
|
||||
{
|
||||
mFeatures.clear();
|
||||
mCurrentLayer = nullptr;
|
||||
mCache.clear();
|
||||
mKeyFieldName.clear();
|
||||
mKeyField.clear();
|
||||
mFeatureTitleField.clear();
|
||||
mFilterExpression.clear();
|
||||
}
|
||||
|
||||
@ -214,7 +201,7 @@ QHash<int, QByteArray> QgsQuickFeaturesListModel::roleNames() const
|
||||
roleNames[Feature] = QStringLiteral( "Feature" ).toLatin1();
|
||||
roleNames[Description] = QStringLiteral( "Description" ).toLatin1();
|
||||
roleNames[FoundPair] = QStringLiteral( "FoundPair" ).toLatin1();
|
||||
roleNames[EmitableIndex] = QStringLiteral( "EmitableIndex" ).toLatin1();
|
||||
roleNames[KeyColumn] = QStringLiteral( "KeyColumn" ).toLatin1();
|
||||
return roleNames;
|
||||
}
|
||||
|
||||
@ -238,39 +225,54 @@ void QgsQuickFeaturesListModel::setFilterExpression( const QString &filterExpres
|
||||
loadFeaturesFromLayer();
|
||||
}
|
||||
|
||||
void QgsQuickFeaturesListModel::setFeatureTitleField( const QString &attribute )
|
||||
{
|
||||
mFeatureTitleField = attribute;
|
||||
}
|
||||
|
||||
void QgsQuickFeaturesListModel::setKeyField( const QString &attribute )
|
||||
{
|
||||
mKeyField = attribute;
|
||||
}
|
||||
|
||||
int QgsQuickFeaturesListModel::featuresLimit() const
|
||||
{
|
||||
return FEATURES_LIMIT;
|
||||
}
|
||||
|
||||
QgsQuickFeaturesListModel::modelTypes QgsQuickFeaturesListModel::modelType() const
|
||||
{
|
||||
return mModelType;
|
||||
}
|
||||
|
||||
void QgsQuickFeaturesListModel::setModelType( modelTypes modelType )
|
||||
{
|
||||
mModelType = modelType;
|
||||
}
|
||||
|
||||
int QgsQuickFeaturesListModel::rowIndexFromKey( const QVariant &key ) const
|
||||
{
|
||||
for ( int i = 0; i < mCache.count(); ++i )
|
||||
{
|
||||
if ( mCache[i].key == key )
|
||||
return i;
|
||||
}
|
||||
QgsDebugMsg( "rowIndexFromKey: key not found: " + key.toString() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
int QgsQuickFeaturesListModel::rowModelIndexFromKey( const QVariant &key ) const
|
||||
int QgsQuickFeaturesListModel::rowFromAttribute( const int role, const QVariant &value ) const
|
||||
{
|
||||
for ( int i = 0; i < mFeatures.count(); ++i )
|
||||
{
|
||||
if ( mFeatures[i].feature().attribute( mKeyFieldName ) == key )
|
||||
QVariant d = data( index( i, 0 ), role );
|
||||
if ( d == value )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
QgsDebugMsg( "rowModelIndexFromKey: Could not find index in features model, index: " + key.toString() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
int QgsQuickFeaturesListModel::keyFromAttribute( const int role, const QVariant &value ) const
|
||||
{
|
||||
for ( int i = 0; i < mFeatures.count(); ++i )
|
||||
{
|
||||
QVariant d = data( index( i, 0 ), role );
|
||||
if ( d == value )
|
||||
{
|
||||
QVariant key = data( index( i, 0 ), KeyColumn );
|
||||
return key.toInt();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
QgsQuickFeatureLayerPair QgsQuickFeaturesListModel::featureLayerPair( const int &featureId )
|
||||
{
|
||||
for ( const QgsQuickFeatureLayerPair &i : mFeatures )
|
||||
{
|
||||
if ( i.feature().id() == featureId )
|
||||
return i;
|
||||
}
|
||||
return QgsQuickFeatureLayerPair();
|
||||
}
|
||||
|
@ -28,10 +28,6 @@
|
||||
*
|
||||
* Model allows searching by any string or number attribute.
|
||||
*
|
||||
* Note that the model can run in several modes:
|
||||
* (1) as a features list - usable in listing features from specifig layer
|
||||
* (2) as a value relation model - filling value-relation widget with data from config
|
||||
*
|
||||
* \note QML Type: FeaturesListModel
|
||||
*
|
||||
* \since QGIS 3.16
|
||||
@ -58,37 +54,19 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
*/
|
||||
Q_PROPERTY( int featuresLimit READ featuresLimit NOTIFY featuresLimitChanged )
|
||||
|
||||
/**
|
||||
* Property determining type of Feature Model.
|
||||
*
|
||||
* \note ValueRelation type provides different attribute when opting for data with EmitableIndex role, it returns "key" attribute
|
||||
*/
|
||||
Q_PROPERTY( modelTypes modelType READ modelType WRITE setModelType )
|
||||
public:
|
||||
|
||||
enum roleNames
|
||||
//! Roles for FeaturesListModel
|
||||
enum modelRoles
|
||||
{
|
||||
FeatureTitle = Qt::UserRole + 1,
|
||||
FeatureId,
|
||||
Feature,
|
||||
Description, //! secondary text in list view
|
||||
EmitableIndex, //! key in value relation
|
||||
KeyColumn, //! key in value relation
|
||||
FoundPair //! pair of attribute and its value by which the feature was found, empty if mFilterExpression is empty
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief The modelTypes enum
|
||||
* ValueRelation type provides different attribute when opting for data with EmitableIndex role, it returns "key" attribute.
|
||||
*
|
||||
* Default type is FeatureListing
|
||||
*/
|
||||
enum modelTypes
|
||||
{
|
||||
FeatureListing,
|
||||
ValueRelation
|
||||
};
|
||||
Q_ENUM( modelTypes );
|
||||
Q_ENUM( modelRoles );
|
||||
|
||||
//! Create features list model
|
||||
explicit QgsQuickFeaturesListModel( QObject *parent = nullptr );
|
||||
@ -102,10 +80,10 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
/**
|
||||
* \brief populate populates model with value relation data from config
|
||||
* \brief setupValueRelation populates model with value relation data from config
|
||||
* \param config to be used
|
||||
*/
|
||||
Q_INVOKABLE void populate( const QVariantMap &config );
|
||||
Q_INVOKABLE void setupValueRelation( const QVariantMap &config );
|
||||
|
||||
/**
|
||||
* \brief populateFromLayer populates model with features from layer
|
||||
@ -119,25 +97,27 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
Q_INVOKABLE void reloadFeatures();
|
||||
|
||||
/**
|
||||
* \brief rowIndexFromKey translates value relation key into index from cache
|
||||
* \param key value relation key
|
||||
* \return index from cache (loaded from config)
|
||||
* \brief rowFromAttribute finds feature with requested role and value, returns its row
|
||||
* \param role to find from modelRoles
|
||||
* \param value to find
|
||||
* \return Row index for found feature, returns -1 if no feature is found. If more features
|
||||
* match requested role and value, index of first is returned.
|
||||
*/
|
||||
Q_INVOKABLE int rowIndexFromKey( const QVariant &key ) const;
|
||||
Q_INVOKABLE int rowFromAttribute( const int role, const QVariant &value ) const;
|
||||
|
||||
/**
|
||||
* \brief rowModelIndexFromKey translates value relation key into model index
|
||||
* \param key value relation key
|
||||
* \return model index (row) for corresponding feature (from mFeatures)
|
||||
* \brief keyFromAttribute finds feature with requested role and value, returns keycolumn
|
||||
* \param role role to find from modelRoles
|
||||
* \param value value to find
|
||||
* \return KeyColumn role for found feature, returns -1 if no feature is found. If more features
|
||||
* match requested role and value, KeyColumn for first is returned.
|
||||
*/
|
||||
Q_INVOKABLE int rowModelIndexFromKey( const QVariant &key ) const;
|
||||
Q_INVOKABLE int keyFromAttribute( const int role, const QVariant &value ) const;
|
||||
|
||||
//! Returns maximum amount of features that can be queried from layer
|
||||
int featuresLimit() const;
|
||||
//! Returns number of features in layer, not number of loaded features
|
||||
int featuresCount() const;
|
||||
//! Returns type of this model
|
||||
modelTypes modelType() const;
|
||||
//! Returns filter expression, empty string represents no filter
|
||||
QString filterExpression() const;
|
||||
|
||||
@ -147,9 +127,14 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
*/
|
||||
void setFilterExpression( const QString &filterExpression );
|
||||
|
||||
public slots:
|
||||
//! Sets corresponding type of model from modelTypes enum
|
||||
void setModelType( modelTypes modelType );
|
||||
/**
|
||||
* \brief setFeatureTitleField Sets name of attribute that will be used for FeatureTitle and Qt::DisplayRole
|
||||
* \param attribute Name of attribute to use. If empty, displayExpression will be used.
|
||||
*/
|
||||
void setFeatureTitleField( const QString &attribute );
|
||||
|
||||
//! Sets name of attribute used as "key" in value relation
|
||||
void setKeyField( const QString &attribute );
|
||||
|
||||
signals:
|
||||
|
||||
@ -167,10 +152,7 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \brief loadFeaturesFromLayer
|
||||
* \param layer
|
||||
*/
|
||||
//! Reloads features from layer, if layer is not provided, uses current layer, If layer is provided, saves it as current.
|
||||
void loadFeaturesFromLayer( QgsVectorLayer *layer = nullptr );
|
||||
|
||||
//! Empty data when resetting model
|
||||
@ -190,7 +172,7 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
* Hold maximum of FEATURES_LIMIT features
|
||||
* \note mFeatures.size() is not always the same as mFeaturesCount
|
||||
*/
|
||||
QList<QgsQuickFeatureLayerPair> mFeatures;
|
||||
QgsQuickFeatureLayerPairs mFeatures;
|
||||
|
||||
//! Number of maximum features loaded from layer
|
||||
const int FEATURES_LIMIT = 10000;
|
||||
@ -201,18 +183,11 @@ class QUICK_EXPORT QgsQuickFeaturesListModel : public QAbstractListModel
|
||||
//! Pointer to layer that is currently loaded
|
||||
QgsVectorLayer *mCurrentLayer = nullptr;
|
||||
|
||||
/**
|
||||
* Data from config for value relations
|
||||
* mCache is not affected by reloading features when filter expression is changed and
|
||||
* is kept until next call of emptyData.
|
||||
*/
|
||||
QgsValueRelationFieldFormatter::ValueRelationCache mCache;
|
||||
|
||||
//! Type of a model - Listing (browsing) features or use in value relation widget
|
||||
modelTypes mModelType;
|
||||
|
||||
//! Field that is used as a "key" in value relation
|
||||
QString mKeyFieldName;
|
||||
QString mKeyField;
|
||||
|
||||
//! Field that represents field used as a feature title, if not set, display expression is used
|
||||
QString mFeatureTitleField;
|
||||
};
|
||||
|
||||
#endif // QGSQUICKFEATURESMODEL_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user