allow QgsFeatureListComboBox to handle multiple keys

This commit is contained in:
Denis Rouzaud 2019-08-22 16:21:46 +02:00
parent 8cdfc2554d
commit a5574eb96b
7 changed files with 376 additions and 78 deletions

View File

@ -26,6 +26,7 @@ Features are fetched asynchronously.
enum Role
{
IdentifierValueRole,
IdentifierValuesRole,
ValueRole
};
@ -103,28 +104,69 @@ Can be used for spatial filtering etc.
Indicator if the model is currently performing any feature iteration in the background.
%End
QString identifierField() const;
QString identifierField() const;
%Docstring
The identifier field should be a unique field that can be used to identify individual features.
It is normally set to the primary key of the layer.
If there are several identifier fields defined, the behavior is not guaranteed
.. deprecated:: since QGIS 3.10 use identifierFields instead
%End
void setIdentifierField( const QString &identifierField );
QStringList identifierFields() const;
%Docstring
The identifier field should be a unique field that can be used to identify individual features.
It is normally set to the primary key of the layer.
.. versionadded:: 3.10
%End
QVariant extraIdentifierValue() const;
void setIdentifierField( const QString &identifierField );
%Docstring
The identifier field should be a unique field that can be used to identify individual features.
It is normally set to the primary key of the layer.
.. deprecated:: since QGIS 3.10
%End
void setIdentifierFields( const QStringList &identifierFields );
%Docstring
The identifier field should be a unique field that can be used to identify individual features.
It is normally set to the primary key of the layer.
.. versionadded:: 3.10
%End
QVariant extraIdentifierValue() const;
%Docstring
Allows specifying one value that does not need to match the filter criteria but will
still be available in the model.
.. deprecated:: since QGIS 3.10
%End
void setExtraIdentifierValue( const QVariant &extraIdentifierValue );
QVariantList extraIdentifierValues() const;
%Docstring
Allows specifying one value that does not need to match the filter criteria but will
still be available in the model.
.. versionadded:: 3.10
%End
void setExtraIdentifierValue( const QVariant &extraIdentifierValue );
%Docstring
Allows specifying one value that does not need to match the filter criteria but will
still be available in the model.
.. deprecated:: since QGIS 3.10
%End
void setExtraIdentifierValues( const QVariantList &extraIdentifierValues );
%Docstring
Allows specifying one value that does not need to match the filter criteria but will
still be available in the model.
.. versionadded:: 3.10
%End
int extraIdentifierValueIndex() const;

View File

@ -9,6 +9,7 @@
class QgsFeatureListComboBox : QComboBox
{
%Docstring
@ -38,6 +39,13 @@ The layer from which features should be listed.
void setSourceLayer( QgsVectorLayer *sourceLayer );
%Docstring
The layer from which features should be listed.
%End
void setCurrentFeature( const QgsFeature &feature );
%Docstring
Sets the current index by using the given feature
.. versionadded:: 3.10
%End
QString displayExpression() const;
@ -74,16 +82,37 @@ This can be used to integrate additional spatial or other constraints.
TODO!
%End
QVariant identifierValue() const;
QVariant identifierValue() const /Deprecated/;
%Docstring
The identifier value of the currently selected feature. A value from the
identifierField.
.. deprecated:: since QGIS 3.10
%End
void setIdentifierValue( const QVariant &identifierValue );
QVariantList identifierValues() const;
%Docstring
The identifier values of the currently selected feature. A value from the
identifierField.
.. versionadded:: 3.10
%End
void setIdentifierValue( const QVariant &identifierValue ) /Deprecated/;
%Docstring
The identifier value of the currently selected feature. A value from the
identifierField.
.. deprecated:: since QGIS 3.10 use setIdentifierValues
%End
void setIdentifierValues( const QVariantList &identifierValues );
%Docstring
The identifier values of the currently selected feature. A value from the
identifierFields.
.. versionadded:: 3.10
%End
QgsFeatureRequest currentFeatureRequest() const;
@ -102,16 +131,36 @@ Determines if a NULL value should be available in the list.
Determines if a NULL value should be available in the list.
%End
QString identifierField() const;
QString identifierField() const /Deprecated/;
%Docstring
Field name that will be used to uniquely identify the current feature.
Normally the primary key of the layer.
.. deprecated:: since QGIS 3.10
%End
void setIdentifierField( const QString &identifierField );
QStringList identifierFields() const;
%Docstring
Field name that will be used to uniquely identify the current feature.
Normally the primary key of the layer.
.. versionadded:: 3.10
%End
void setIdentifierField( const QString &identifierField ) /Deprecated/;
%Docstring
Field name that will be used to uniquely identify the current feature.
Normally the primary key of the layer.
.. deprecated:: since QGIS 3.10
%End
void setIdentifierFields( const QStringList &identifierFields );
%Docstring
Field name that will be used to uniquely identify the current feature.
Normally the primary key of the layer.
.. versionadded:: 3.10
%End
QModelIndex currentModelIndex() const;
@ -170,6 +219,8 @@ Determines if a NULL value should be available in the list.
};
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -1,6 +1,5 @@
/***************************************************************************
qgsfeaturefiltermodel.cpp - QgsFeatureFilterModel
---------------------
begin : 10.3.2017
copyright : (C) 2017 by Matthias Kuhn
@ -27,7 +26,7 @@ QgsFeatureFilterModel::QgsFeatureFilterModel( QObject *parent )
mReloadTimer.setInterval( 100 );
mReloadTimer.setSingleShot( true );
connect( &mReloadTimer, &QTimer::timeout, this, &QgsFeatureFilterModel::scheduledReload );
setExtraIdentifierValueUnguarded( QVariant() );
setExtraIdentifierValuesUnguarded( QVariantList() );
}
QgsFeatureFilterModel::~QgsFeatureFilterModel()
@ -102,6 +101,14 @@ bool QgsFeatureFilterModel::isLoading() const
return mGatherer;
}
QString QgsFeatureFilterModel::identifierField() const
{
if ( mIdentifierFields.isEmpty() )
return QString();
else
return mIdentifierFields.at( 0 );
}
QModelIndex QgsFeatureFilterModel::index( int row, int column, const QModelIndex &parent ) const
{
Q_UNUSED( parent )
@ -140,30 +147,42 @@ QVariant QgsFeatureFilterModel::data( const QModelIndex &index, int role ) const
return mEntries.value( index.row() ).value;
case IdentifierValueRole:
return mEntries.value( index.row() ).identifierValue;
{
QVariantList values = mEntries.value( index.row() ).identifierValues;
return values.isEmpty() ? QVariant() : values.at( 0 );
}
case IdentifierValuesRole:
return mEntries.value( index.row() ).identifierValues;
case Qt::BackgroundColorRole:
case Qt::TextColorRole:
case Qt::DecorationRole:
case Qt::FontRole:
{
if ( mEntries.value( index.row() ).identifierValue.isNull() )
bool isNull = true;
for ( const QVariant &value : mEntries.value( index.row() ).identifierValues )
{
if ( !value.isNull() )
{
isNull = false;
break;
}
}
if ( isNull )
{
// Representation for NULL value
if ( role == Qt::TextColorRole )
{
return QBrush( QColor( Qt::gray ) );
}
else if ( role == Qt::FontRole )
if ( role == Qt::FontRole )
{
QFont font = QFont();
if ( index.row() == mExtraIdentifierValueIndex )
font.setBold( true );
if ( mEntries.value( index.row() ).identifierValue.isNull() )
{
else
font.setItalic( true );
}
return font;
}
}
@ -197,7 +216,7 @@ void QgsFeatureFilterModel::updateCompleter()
QVector<Entry> entries = mGatherer->entries();
if ( mExtraIdentifierValueIndex == -1 )
setExtraIdentifierValueUnguarded( QVariant() );
setExtraIdentifierValuesUnguarded( QVariantList() );
// Only reloading the current entry?
if ( mGatherer->data().toBool() )
@ -225,7 +244,9 @@ void QgsFeatureFilterModel::updateCompleter()
std::sort( entries.begin(), entries.end(), []( const Entry & a, const Entry & b ) { return a.value.localeAwareCompare( b.value ) < 0; } );
if ( mAllowNull )
entries.prepend( Entry( QVariant( QVariant::Int ), QgsApplication::nullRepresentation(), QgsFeature() ) );
{
entries.prepend( nullEntry() );
}
const int newEntriesSize = entries.size();
@ -235,7 +256,7 @@ void QgsFeatureFilterModel::updateCompleter()
{
for ( int i = 0; i < newEntriesSize; ++i )
{
if ( entries.at( i ).identifierValue == mExtraIdentifierValue )
if ( entries.at( i ).identifierValues == mExtraIdentifierValues )
{
currentEntryInNewList = i;
mEntries.replace( mExtraIdentifierValueIndex, entries.at( i ) );
@ -274,7 +295,7 @@ void QgsFeatureFilterModel::updateCompleter()
beginInsertRows( QModelIndex(), 1, entries.size() + 1 );
mEntries += entries;
endInsertRows();
setExtraIdentifierValueIndex( 0 );
setExtraIdentifierValuesIndex( 0 );
}
else
{
@ -294,7 +315,7 @@ void QgsFeatureFilterModel::updateCompleter()
beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 );
mEntries += entries.mid( currentEntryInNewList + 1 );
endInsertRows();
setExtraIdentifierValueIndex( currentEntryInNewList );
setExtraIdentifierValuesIndex( currentEntryInNewList );
}
emit filterJobCompleted();
@ -331,7 +352,19 @@ void QgsFeatureFilterModel::scheduledReload()
if ( mShouldReloadCurrentFeature )
{
request.setFilterExpression( QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( mIdentifierField ), QgsExpression::quotedValue( mExtraIdentifierValue ) ) );
QStringList conditions;
for ( int i = 0; i < mIdentifierFields.count(); i++ )
{
if ( i >= mExtraIdentifierValues.count() )
{
conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), QVariant() );
}
else
{
conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), mExtraIdentifierValues.at( i ) );
}
}
request.setFilterExpression( conditions.join( QStringLiteral( " AND " ) ) );
}
else
{
@ -350,13 +383,14 @@ void QgsFeatureFilterModel::scheduledReload()
QSet<QString> attributes;
if ( request.filterExpression() )
attributes = request.filterExpression()->referencedColumns();
attributes << mIdentifierField;
for ( const QString &fieldName : qgis::as_const( mIdentifierFields ) )
attributes << fieldName;
request.setSubsetOfAttributes( attributes, mSourceLayer->fields() );
request.setFlags( QgsFeatureRequest::NoGeometry );
request.setLimit( QgsSettings().value( QStringLiteral( "maxEntriesRelationWidget" ), 100, QgsSettings::Gui ).toInt() );
mGatherer = new QgsFieldExpressionValuesGatherer( mSourceLayer, mDisplayExpression, mIdentifierField, request );
mGatherer = new QgsFieldExpressionValuesGatherer( mSourceLayer, mDisplayExpression, mIdentifierFields, request );
mGatherer->setData( mShouldReloadCurrentFeature );
connect( mGatherer, &QgsFieldExpressionValuesGatherer::collectedValues, this, &QgsFeatureFilterModel::updateCompleter );
@ -393,7 +427,7 @@ QSet<QString> QgsFeatureFilterModel::requestedAttributes() const
return requestedAttrs;
}
void QgsFeatureFilterModel::setExtraIdentifierValueIndex( int index, bool force )
void QgsFeatureFilterModel::setExtraIdentifierValuesIndex( int index, bool force )
{
if ( mExtraIdentifierValueIndex == index && !force )
return;
@ -408,18 +442,16 @@ void QgsFeatureFilterModel::reloadCurrentFeature()
mReloadTimer.start();
}
void QgsFeatureFilterModel::setExtraIdentifierValueUnguarded( const QVariant &extraIdentifierValue )
void QgsFeatureFilterModel::setExtraIdentifierValuesUnguarded( const QVariantList &extraIdentifierValues )
{
const QVector<Entry> entries = mEntries;
int index = 0;
for ( const Entry &entry : entries )
{
if ( entry.identifierValue == extraIdentifierValue
&& entry.identifierValue.isNull() == extraIdentifierValue.isNull()
&& entry.identifierValue.isValid() == extraIdentifierValue.isValid() )
if ( entry.identifierValues == extraIdentifierValues )
{
setExtraIdentifierValueIndex( index );
setExtraIdentifierValuesIndex( index );
break;
}
@ -430,18 +462,37 @@ void QgsFeatureFilterModel::setExtraIdentifierValueUnguarded( const QVariant &ex
if ( mExtraIdentifierValueIndex != index )
{
beginInsertRows( QModelIndex(), 0, 0 );
if ( extraIdentifierValue.isNull() )
mEntries.prepend( Entry( QVariant( QVariant::Int ), QgsApplication::nullRepresentation( ), QgsFeature() ) );
if ( extraIdentifierValues.isEmpty() )
{
mEntries.prepend( nullEntry() );
}
else
mEntries.prepend( Entry( extraIdentifierValue, QStringLiteral( "(%1)" ).arg( extraIdentifierValue.toString() ), QgsFeature() ) );
{
QStringList values;
for ( const QVariant &v : qgis::as_const( extraIdentifierValues ) )
values << QStringLiteral( "(%1)" ).arg( v.toString() );
mEntries.prepend( Entry( extraIdentifierValues, values.join( QStringLiteral( " " ) ), QgsFeature() ) );
}
endInsertRows();
setExtraIdentifierValueIndex( 0, true );
setExtraIdentifierValuesIndex( 0, true );
reloadCurrentFeature();
}
}
QgsFeatureFilterModel::Entry QgsFeatureFilterModel::nullEntry()
{
QVariantList nullAttributes;
for ( const QString &fieldName : mIdentifierFields )
{
int idx = mSourceLayer->fields().indexOf( fieldName );
nullAttributes << QVariant( mSourceLayer->fields().at( idx ).type() );
}
return Entry( nullAttributes, QgsApplication::nullRepresentation(), QgsFeature() );
}
QgsConditionalStyle QgsFeatureFilterModel::featureStyle( const QgsFeature &feature ) const
{
if ( !mSourceLayer )
@ -505,18 +556,24 @@ int QgsFeatureFilterModel::extraIdentifierValueIndex() const
return mExtraIdentifierValueIndex;
}
QString QgsFeatureFilterModel::identifierField() const
QStringList QgsFeatureFilterModel::identifierFields() const
{
return mIdentifierField;
return mIdentifierFields;
}
void QgsFeatureFilterModel::setIdentifierField( const QString &identifierField )
{
if ( mIdentifierField == identifierField )
setIdentifierFields( QStringList() << identifierField );
}
void QgsFeatureFilterModel::setIdentifierFields( const QStringList &identifierFields )
{
if ( mIdentifierFields == identifierFields )
return;
mIdentifierField = identifierField;
mIdentifierFields = identifierFields;
emit identifierFieldChanged();
setExtraIdentifierValues( QVariantList() );
}
void QgsFeatureFilterModel::reload()
@ -526,12 +583,25 @@ void QgsFeatureFilterModel::reload()
QVariant QgsFeatureFilterModel::extraIdentifierValue() const
{
return mExtraIdentifierValue;
if ( mExtraIdentifierValues.isEmpty() )
return QVariant();
else
return mExtraIdentifierValues.at( 0 );
}
QVariantList QgsFeatureFilterModel::extraIdentifierValues() const
{
return mExtraIdentifierValues;
}
void QgsFeatureFilterModel::setExtraIdentifierValue( const QVariant &extraIdentifierValue )
{
if ( qgsVariantEqual( extraIdentifierValue, mExtraIdentifierValue ) && mExtraIdentifierValue.isValid() )
setExtraIdentifierValues( QVariantList() << extraIdentifierValue );
}
void QgsFeatureFilterModel::setExtraIdentifierValues( const QVariantList &extraIdentifierValues )
{
if ( extraIdentifierValues == mExtraIdentifierValues && !mExtraIdentifierValues.isEmpty() )
return;
if ( mIsSettingExtraIdentifierValue )
@ -539,9 +609,9 @@ void QgsFeatureFilterModel::setExtraIdentifierValue( const QVariant &extraIdenti
mIsSettingExtraIdentifierValue = true;
mExtraIdentifierValue = extraIdentifierValue;
mExtraIdentifierValues = extraIdentifierValues;
setExtraIdentifierValueUnguarded( extraIdentifierValue );
setExtraIdentifierValuesUnguarded( extraIdentifierValues );
mIsSettingExtraIdentifierValue = false;

View File

@ -1,6 +1,5 @@
/***************************************************************************
qgsfeaturefiltermodel.h - QgsFeatureFilterModel
---------------------
begin : 10.3.2017
copyright : (C) 2017 by Matthias Kuhn
@ -61,7 +60,8 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
*/
enum Role
{
IdentifierValueRole = Qt::UserRole, //!< Used to retrieve the identifierValue (primary key) of a feature.
IdentifierValueRole = Qt::UserRole, //!< \deprecated Use IdentifierValuesRole instead
IdentifierValuesRole, //!< Used to retrieve the identifierValues (primary keys) of a feature.
ValueRole //!< Used to retrieve the displayExpression of a feature.
};
@ -137,26 +137,59 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
/**
* The identifier field should be a unique field that can be used to identify individual features.
* It is normally set to the primary key of the layer.
* If there are several identifier fields defined, the behavior is not guaranteed
* \deprecated since QGIS 3.10 use identifierFields instead
*/
QString identifierField() const;
Q_DECL_DEPRECATED QString identifierField() const;
/**
* The identifier field should be a unique field that can be used to identify individual features.
* It is normally set to the primary key of the layer.
* \since QGIS 3.10
*/
void setIdentifierField( const QString &identifierField );
QStringList identifierFields() const;
/**
* The identifier field should be a unique field that can be used to identify individual features.
* It is normally set to the primary key of the layer.
* \deprecated since QGIS 3.10
*/
Q_DECL_DEPRECATED void setIdentifierField( const QString &identifierField );
/**
* The identifier field should be a unique field that can be used to identify individual features.
* It is normally set to the primary key of the layer.
* \since QGIS 3.10
*/
void setIdentifierFields( const QStringList &identifierFields );
/**
* Allows specifying one value that does not need to match the filter criteria but will
* still be available in the model.
* \deprecated since QGIS 3.10
*/
QVariant extraIdentifierValue() const;
Q_DECL_DEPRECATED QVariant extraIdentifierValue() const;
/**
* Allows specifying one value that does not need to match the filter criteria but will
* still be available in the model.
* \since QGIS 3.10
*/
void setExtraIdentifierValue( const QVariant &extraIdentifierValue );
QVariantList extraIdentifierValues() const;
/**
* Allows specifying one value that does not need to match the filter criteria but will
* still be available in the model.
* \deprecated since QGIS 3.10
*/
Q_DECL_DEPRECATED void setExtraIdentifierValue( const QVariant &extraIdentifierValue );
/**
* Allows specifying one value that does not need to match the filter criteria but will
* still be available in the model.
* \since QGIS 3.10
*/
void setExtraIdentifierValues( const QVariantList &extraIdentifierValues );
/**
* The index at which the extra identifier value is available within the model.
@ -260,27 +293,28 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
private:
QSet<QString> requestedAttributes() const;
void setExtraIdentifierValueIndex( int index, bool force = false );
void setExtraIdentifierValuesIndex( int index, bool force = false );
void setExtraValueDoesNotExist( bool extraValueDoesNotExist );
void reload();
void reloadCurrentFeature();
void setExtraIdentifierValueUnguarded( const QVariant &extraIdentifierValue );
void setExtraIdentifierValuesUnguarded( const QVariantList &extraIdentifierValues );
struct Entry
{
Entry() = default;
Entry( const QVariant &_identifierValue, const QString &_value, const QgsFeature &_feature )
: identifierValue( _identifierValue )
Entry( const QVariantList &_identifierValues, const QString &_value, const QgsFeature &_feature )
: identifierValues( _identifierValues )
, value( _value )
, feature( _feature )
{}
QVariant identifierValue;
QVariantList identifierValues;
QString value;
QgsFeature feature;
bool operator()( const Entry &lhs, const Entry &rhs ) const;
};
Entry nullEntry();
QgsConditionalStyle featureStyle( const QgsFeature &feature ) const;
@ -299,9 +333,8 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
bool mAllowNull = false;
bool mIsSettingExtraIdentifierValue = false;
QString mIdentifierField;
QVariant mExtraIdentifierValue;
QStringList mIdentifierFields;
QVariantList mExtraIdentifierValues;
int mExtraIdentifierValueIndex = -1;

View File

@ -1,6 +1,5 @@
/***************************************************************************
qgsfeaturefiltermodel_p - QgsFieldExpressionValuesGatherer
---------------------
begin : 10.3.2017
copyright : (C) 2017 by Matthias Kuhn
@ -37,11 +36,14 @@ class QgsFieldExpressionValuesGatherer: public QThread
Q_OBJECT
public:
QgsFieldExpressionValuesGatherer( QgsVectorLayer *layer, const QString &displayExpression, const QString &identifierField, const QgsFeatureRequest &request = QgsFeatureRequest() )
QgsFieldExpressionValuesGatherer( QgsVectorLayer *layer,
const QString &displayExpression,
const QStringList &identifierFields,
const QgsFeatureRequest &request = QgsFeatureRequest() )
: mSource( new QgsVectorLayerFeatureSource( layer ) )
, mDisplayExpression( displayExpression )
, mRequest( request )
, mIdentifierField( identifierField )
, mIdentifierFields( identifierFields )
{
}
@ -54,12 +56,17 @@ class QgsFieldExpressionValuesGatherer: public QThread
mDisplayExpression.prepare( &mExpressionContext );
QgsFeature feat;
const int attribute = mSource->fields().indexOf( mIdentifierField );
QList<int> attributeIndexes;
for ( const QString &fieldName : qgis::as_const( mIdentifierFields ) )
attributeIndexes << mSource->fields().indexOf( fieldName );
while ( mIterator.nextFeature( feat ) )
{
mExpressionContext.setFeature( feat );
mEntries.append( QgsFeatureFilterModel::Entry( feat.attribute( attribute ), mDisplayExpression.evaluate( &mExpressionContext ).toString(), feat ) );
QVariantList attributes;
for ( const int idx : attributeIndexes )
attributes << feat.attribute( idx );
mEntries.append( QgsFeatureFilterModel::Entry( attributes, mDisplayExpression.evaluate( &mExpressionContext ).toString(), feat ) );
if ( mWasCanceled )
return;
@ -120,7 +127,7 @@ class QgsFieldExpressionValuesGatherer: public QThread
QgsFeatureIterator mIterator;
bool mWasCanceled = false;
QVector<QgsFeatureFilterModel::Entry> mEntries;
QString mIdentifierField;
QStringList mIdentifierFields;
QVariant mData;
};

View File

@ -1,6 +1,5 @@
/***************************************************************************
qgsfieldlistcombobox.cpp - QgsFieldListComboBox
qgsfeaturelistcombobox.cpp - QgsFeatureListComboBox
---------------------
begin : 10.3.2017
copyright : (C) 2017 by Matthias Kuhn
@ -75,6 +74,17 @@ void QgsFeatureListComboBox::setSourceLayer( QgsVectorLayer *sourceLayer )
mModel->setSourceLayer( sourceLayer );
}
void QgsFeatureListComboBox::setCurrentFeature( const QgsFeature &feature )
{
QVariantList values;
const QStringList fields = mModel->identifierFields();
for ( const QString &field : fields )
{
values << feature.attribute( field );
}
setCurrentIndex( findData( values, QgsFeatureFilterModel::Role::IdentifierValueRole ) );
}
QString QgsFeatureListComboBox::displayExpression() const
{
return mModel->displayExpression();
@ -115,7 +125,7 @@ void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
if ( !mHasStoredEditState )
mIsCurrentlyEdited = false;
QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
mModel->setExtraIdentifierValue( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValueRole ) );
mModel->setExtraIdentifierValues( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValuesRole ).toList() );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
QPalette palette = mLineEdit->palette();
@ -125,7 +135,7 @@ void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
void QgsFeatureListComboBox::onActivated( QModelIndex modelIndex )
{
setIdentifierValue( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValueRole ) );
setIdentifierValues( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValuesRole ).toList() );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
}
@ -175,12 +185,26 @@ void QgsFeatureListComboBox::onDataChanged( const QModelIndex &topLeft, const QM
QString QgsFeatureListComboBox::identifierField() const
{
return mModel->identifierField();
QStringList list = mModel->identifierFields();
if ( list.isEmpty() )
return QString();
else
return list.at( 0 );
}
QStringList QgsFeatureListComboBox::identifierFields() const
{
return mModel->identifierFields();
}
void QgsFeatureListComboBox::setIdentifierField( const QString &identifierField )
{
mModel->setIdentifierField( identifierField );
mModel->setIdentifierFields( QStringList() << identifierField );
}
void QgsFeatureListComboBox::setIdentifierFields( const QStringList &identifierFields )
{
mModel->setIdentifierFields( identifierFields );
}
QModelIndex QgsFeatureListComboBox::currentModelIndex() const
@ -219,17 +243,46 @@ QVariant QgsFeatureListComboBox::identifierValue() const
return mModel->extraIdentifierValue();
}
QVariantList QgsFeatureListComboBox::identifierValues() const
{
return mModel->extraIdentifierValues();
}
void QgsFeatureListComboBox::setIdentifierValue( const QVariant &identifierValue )
{
mModel->setExtraIdentifierValue( identifierValue );
setIdentifierValues( QVariantList() << identifierValue );
}
void QgsFeatureListComboBox::setIdentifierValues( const QVariantList &identifierValues )
{
mModel->setExtraIdentifierValues( identifierValues );
}
QgsFeatureRequest QgsFeatureListComboBox::currentFeatureRequest() const
{
if ( mModel->extraIdentifierValue().isNull() )
if ( mModel->extraIdentifierValues().isEmpty() )
{
return QgsFeatureRequest().setFilterFids( QgsFeatureIds() ); // NULL: Return a request that's guaranteed to not return anything
}
else
return QgsFeatureRequest().setFilterExpression( QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( mModel->identifierField() ), QgsExpression::quotedValue( mModel->extraIdentifierValue() ) ) );
{
QStringList filtersAttrs;
const QStringList identifierFields = mModel->identifierFields();
const QVariantList values = mModel->extraIdentifierValues();
for ( int i = 0; i < identifierFields.count(); i++ )
{
if ( i >= values.count() )
{
filtersAttrs << QgsExpression::createFieldEqualityExpression( identifierFields.at( i ), QVariant() );
}
else
{
filtersAttrs << QgsExpression::createFieldEqualityExpression( identifierFields.at( i ), values.at( i ) );
}
}
const QString expression = filtersAttrs.join( QStringLiteral( " AND " ) );
return QgsFeatureRequest().setFilterExpression( expression );
}
}
QString QgsFeatureListComboBox::filterExpression() const

View File

@ -1,6 +1,5 @@
/***************************************************************************
qgsfieldlistcombobox.h - QgsFieldListComboBox
qgsfeaturelistcombobox.h - QgsFeatureListComboBox
---------------------
begin : 10.3.2017
copyright : (C) 2017 by Matthias Kuhn
@ -27,6 +26,7 @@ class QgsFeatureFilterModel;
class QgsAnimatedIcon;
class QgsFilterLineEdit;
/**
* \ingroup gui
* This offers a combobox with autocompleter that allows selecting features from a layer.
@ -44,6 +44,7 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
Q_PROPERTY( QString displayExpression READ displayExpression WRITE setDisplayExpression NOTIFY displayExpressionChanged )
Q_PROPERTY( QString filterExpression READ filterExpression WRITE setFilterExpression NOTIFY filterExpressionChanged )
Q_PROPERTY( QVariant identifierValue READ identifierValue WRITE setIdentifierValue NOTIFY identifierValueChanged )
Q_PROPERTY( QVariantList identifierValues READ identifierValues WRITE setIdentifierValues NOTIFY identifierValueChanged )
Q_PROPERTY( QString identifierField READ identifierField WRITE setIdentifierField NOTIFY identifierFieldChanged )
Q_PROPERTY( bool allowNull READ allowNull WRITE setAllowNull NOTIFY allowNullChanged )
@ -64,6 +65,12 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
*/
void setSourceLayer( QgsVectorLayer *sourceLayer );
/**
* Sets the current index by using the given feature
* \since QGIS 3.10
*/
void setCurrentFeature( const QgsFeature &feature );
/**
* The display expression will be used to display features as well as
* the value to match the typed text against.
@ -101,14 +108,31 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
/**
* The identifier value of the currently selected feature. A value from the
* identifierField.
* \deprecated since QGIS 3.10
*/
QVariant identifierValue() const;
Q_DECL_DEPRECATED QVariant identifierValue() const SIP_DEPRECATED;
/**
* The identifier values of the currently selected feature. A value from the
* identifierField.
* \since QGIS 3.10
*/
QVariantList identifierValues() const;
/**
* The identifier value of the currently selected feature. A value from the
* identifierField.
* \deprecated since QGIS 3.10 use setIdentifierValues
*/
void setIdentifierValue( const QVariant &identifierValue );
Q_DECL_DEPRECATED void setIdentifierValue( const QVariant &identifierValue ) SIP_DEPRECATED;
/**
* The identifier values of the currently selected feature. A value from the
* identifierFields.
* \since QGIS 3.10
*/
void setIdentifierValues( const QVariantList &identifierValues );
/**
* Shorthand for getting a feature request to query the currently selected
@ -129,14 +153,30 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
/**
* Field name that will be used to uniquely identify the current feature.
* Normally the primary key of the layer.
* \deprecated since QGIS 3.10
*/
QString identifierField() const;
Q_DECL_DEPRECATED QString identifierField() const SIP_DEPRECATED;
/**
* Field name that will be used to uniquely identify the current feature.
* Normally the primary key of the layer.
* \since QGIS 3.10
*/
void setIdentifierField( const QString &identifierField );
QStringList identifierFields() const;
/**
* Field name that will be used to uniquely identify the current feature.
* Normally the primary key of the layer.
* \deprecated since QGIS 3.10
*/
Q_DECL_DEPRECATED void setIdentifierField( const QString &identifierField ) SIP_DEPRECATED;
/**
* Field name that will be used to uniquely identify the current feature.
* Normally the primary key of the layer.
* \since QGIS 3.10
*/
void setIdentifierFields( const QStringList &identifierFields );
/**
* The index of the currently selected item.
@ -225,4 +265,6 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
friend class TestQgsFeatureListComboBox;
};
#endif // QGSFIELDLISTCOMBOBOX_H