QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsfeaturelistcombobox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeaturelistcombobox.cpp - QgsFeatureListComboBox
3  ---------------------
4  begin : 10.3.2017
5  copyright : (C) 2017 by Matthias Kuhn
6  email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsfeaturelistcombobox.h"
16 
17 #include "qgsfeaturefiltermodel.h"
18 #include "qgsanimatedicon.h"
19 #include "qgsfilterlineedit.h"
20 #include "qgslogger.h"
21 #include "qgsapplication.h"
22 
23 #include <QCompleter>
24 #include <QLineEdit>
25 #include <QKeyEvent>
26 
28  : QComboBox( parent )
29  , mModel( new QgsFeatureFilterModel( this ) )
30  , mCompleter( new QCompleter( mModel ) )
31 {
32  mCompleter->setCaseSensitivity( Qt::CaseInsensitive );
33  mCompleter->setFilterMode( Qt::MatchContains );
34  setEditable( true );
35  setCompleter( mCompleter );
36  mCompleter->setWidget( this );
40  connect( mModel, &QgsFeatureFilterModel::isLoadingChanged, this, &QgsFeatureListComboBox::onLoadingChanged );
41  connect( mModel, &QgsFeatureFilterModel::filterJobCompleted, this, &QgsFeatureListComboBox::onFilterUpdateCompleted );
44  connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueIndexChanged, this, &QgsFeatureListComboBox::setCurrentIndex );
46  connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeatureListComboBox::onItemSelected );
47  connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeatureListComboBox::onActivated );
48  connect( mModel, &QgsFeatureFilterModel::beginUpdate, this, &QgsFeatureListComboBox::storeLineEditState );
49  connect( mModel, &QgsFeatureFilterModel::endUpdate, this, &QgsFeatureListComboBox::restoreLineEditState );
51  connect( mModel, &QgsFeatureFilterModel::dataChanged, this, &QgsFeatureListComboBox::onDataChanged );
52 
53  connect( this, static_cast<void( QgsFeatureListComboBox::* )( int )>( &QgsFeatureListComboBox::currentIndexChanged ), this, &QgsFeatureListComboBox::onCurrentIndexChanged );
54 
55  mLineEdit = new QgsFilterLineEdit( nullptr, QgsApplication::nullRepresentation() );
56  mLineEdit->setSelectOnFocus( true );
57  mLineEdit->setShowClearButton( true );
58 
59  setLineEdit( mLineEdit );
60  setModel( mModel );
61 
62  connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeatureListComboBox::onCurrentTextChanged );
63 
65 
66  setToolTip( tr( "Just start typing what you are looking for." ) );
67 }
68 
70 {
71  return mModel->sourceLayer();
72 }
73 
75 {
76  mModel->setSourceLayer( sourceLayer );
77 }
78 
80 {
81  QVariantList values;
82  const QStringList fields = mModel->identifierFields();
83  for ( const QString &field : fields )
84  {
85  values << feature.attribute( field );
86  }
87  setIdentifierValues( values );
88 }
89 
91 {
92  return mModel->displayExpression();
93 }
94 
95 void QgsFeatureListComboBox::setDisplayExpression( const QString &expression )
96 {
97  mModel->setDisplayExpression( expression );
98 }
99 
100 void QgsFeatureListComboBox::onCurrentTextChanged( const QString &text )
101 {
102  mIsCurrentlyEdited = true;
103  mPopupRequested = true;
104  mModel->setFilterValue( text );
105 }
106 
107 void QgsFeatureListComboBox::onFilterUpdateCompleted()
108 {
109  if ( mPopupRequested )
110  mCompleter->complete();
111 
112  mPopupRequested = false;
113 }
114 
115 void QgsFeatureListComboBox::onLoadingChanged()
116 {
117  mLineEdit->setShowSpinner( mModel->isLoading() );
118 }
119 
120 void QgsFeatureListComboBox::onItemSelected( const QModelIndex &index )
121 {
122  setCurrentIndex( index.row() );
123 }
124 
125 void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
126 {
127  if ( !mLineEdit->hasStateStored() )
128  mIsCurrentlyEdited = false;
129  const QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
130  mModel->setExtraIdentifierValues( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValuesRole ).toList() );
131  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
132  mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
133  QPalette palette = mLineEdit->palette();
134  palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
135  mLineEdit->setPalette( palette );
136 }
137 
138 void QgsFeatureListComboBox::onActivated( QModelIndex modelIndex )
139 {
140  setIdentifierValues( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValuesRole ).toList() );
141  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
142 }
143 
144 void QgsFeatureListComboBox::storeLineEditState()
145 {
146  if ( mIsCurrentlyEdited )
147  {
148  mLineEdit->storeState( );
149  }
150 }
151 
152 void QgsFeatureListComboBox::restoreLineEditState()
153 {
154  if ( mIsCurrentlyEdited )
155  {
156  mLineEdit->restoreState( );
157  }
158 }
159 
161 {
162  int index = -1;
163 
164  if ( allowNull() )
165  {
166  index = findText( QgsApplication::nullRepresentation( ) );
167  }
168 
169  return index;
170 }
171 
172 void QgsFeatureListComboBox::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
173 {
174  Q_UNUSED( roles )
175  if ( !mIsCurrentlyEdited )
176  {
177  const int currentIndex = mModel->extraIdentifierValueIndex();
178  if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
179  {
180  const QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
181  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
182  }
183  }
184 }
185 
187 {
188  const QStringList list = mModel->identifierFields();
189  if ( list.isEmpty() )
190  return QString();
191  else
192  return list.at( 0 );
193 }
194 
196 {
197  return mModel->identifierFields();
198 }
199 
200 void QgsFeatureListComboBox::setIdentifierField( const QString &identifierField )
201 {
202  mModel->setIdentifierFields( QStringList() << identifierField );
203 }
204 
205 void QgsFeatureListComboBox::setIdentifierFields( const QStringList &identifierFields )
206 {
208 }
209 
211 {
212  return mModel->index( currentIndex(), 0, QModelIndex() );
213 }
214 
215 void QgsFeatureListComboBox::focusOutEvent( QFocusEvent *event )
216 {
217  Q_UNUSED( event )
218  QComboBox::focusOutEvent( event );
219  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
220 }
221 
223 {
224  if ( event->key() == Qt::Key_Escape )
225  {
226  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
227  }
228  QComboBox::keyReleaseEvent( event );
229 }
230 
232 {
233  return mModel->allowNull();
234 }
235 
237 {
238  mModel->setAllowNull( allowNull );
240 }
241 
243 {
245  return mModel->extraIdentifierValues().value( 0 );
247 }
248 
249 QVariantList QgsFeatureListComboBox::identifierValues() const
250 {
251  return mModel->extraIdentifierValues();
252 }
253 
254 void QgsFeatureListComboBox::setIdentifierValue( const QVariant &identifierValue )
255 {
256  setIdentifierValues( QVariantList() << identifierValue );
257 }
258 
259 void QgsFeatureListComboBox::setIdentifierValues( const QVariantList &identifierValues )
260 {
262 }
263 
265 {
267 }
268 
270 {
271  if ( mModel->extraIdentifierValues().isEmpty() )
272  {
273  return QgsFeatureRequest().setFilterFids( QgsFeatureIds() ); // NULL: Return a request that's guaranteed to not return anything
274  }
275  else
276  {
277  QStringList filtersAttrs;
278  const QStringList identifierFields = mModel->identifierFields();
279  const QVariantList values = mModel->extraIdentifierValues();
280  for ( int i = 0; i < identifierFields.count(); i++ )
281  {
282  if ( i >= values.count() )
283  {
284  filtersAttrs << QgsExpression::createFieldEqualityExpression( identifierFields.at( i ), QVariant() );
285  }
286  else
287  {
288  filtersAttrs << QgsExpression::createFieldEqualityExpression( identifierFields.at( i ), values.at( i ) );
289  }
290  }
291  const QString expression = filtersAttrs.join( QLatin1String( " AND " ) );
292  return QgsFeatureRequest().setFilterExpression( expression );
293  }
294 }
295 
297 {
298  return mModel->filterExpression();
299 }
300 
301 void QgsFeatureListComboBox::setFilterExpression( const QString &filterExpression )
302 {
304 }
QgsFeatureListComboBox::identifierField
QString identifierField
Definition: qgsfeaturelistcombobox.h:48
qgsfeaturefiltermodel.h
QgsFeatureListComboBox::filterExpression
QString filterExpression
Definition: qgsfeaturelistcombobox.h:45
QgsFeatureListComboBox::identifierFields
QStringList identifierFields() const
Field name that will be used to uniquely identify the current feature.
Definition: qgsfeaturelistcombobox.cpp:195
QgsFeaturePickerModelBase::isLoading
bool isLoading() const
Indicator if the model is currently performing any feature iteration in the background.
Definition: qgsfeaturepickermodelbase.cpp:120
QgsFeaturePickerModelBase::extraIdentifierValueIndex
int extraIdentifierValueIndex
Definition: qgsfeaturepickermodelbase.h:56
QgsFeaturePickerModelBase::displayExpressionChanged
void displayExpressionChanged()
The display expression will be used for.
QgsFeatureFilterModel::identifierFields
QStringList identifierFields
A set of fields of sourceLayer that is unique and should be used to identify features.
Definition: qgsfeaturefiltermodel.h:50
QgsFeatureListComboBox::setCurrentFeature
void setCurrentFeature(const QgsFeature &feature)
Sets the current index by using the given feature.
Definition: qgsfeaturelistcombobox.cpp:79
QgsFeatureListComboBox::allowNullChanged
void allowNullChanged()
Determines if a NULL value should be available in the list.
QgsFeaturePickerModelBase::filterExpression
QString filterExpression
Definition: qgsfeaturepickermodelbase.h:52
qgsfeaturelistcombobox.h
QgsFeatureListComboBox::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: qgsfeaturelistcombobox.cpp:222
QgsFeatureListComboBox::setFilterExpression
void setFilterExpression(const QString &filterExpression)
An additional expression to further restrict the available features.
Definition: qgsfeaturelistcombobox.cpp:301
QgsFilterLineEdit::restoreState
void restoreState()
Restores the current state of the line edit (selection and cursor position)
Definition: qgsfilterlineedit.cpp:226
QgsFeatureListComboBox::sourceLayerChanged
void sourceLayerChanged()
The layer from which features should be listed.
QgsFeatureListComboBox::focusOutEvent
void focusOutEvent(QFocusEvent *event) override
Definition: qgsfeaturelistcombobox.cpp:215
QgsFeatureListComboBox::identifierValueChanged
void identifierValueChanged()
The identifier value of the currently selected feature.
QgsFeaturePickerModelBase::IdentifierValuesRole
@ IdentifierValuesRole
Used to retrieve the identifierValues (primary keys) of a feature.
Definition: qgsfeaturepickermodelbase.h:66
QgsFeatureFilterModel::extraIdentifierValues
QVariantList extraIdentifierValues
The values that identifies the current feature.
Definition: qgsfeaturefiltermodel.h:55
qgsfilterlineedit.h
QgsFilterLineEdit
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Definition: qgsfilterlineedit.h:39
QgsFeatureListComboBox::identifierValues
QVariantList identifierValues
Definition: qgsfeaturelistcombobox.h:47
QgsFilterLineEdit::ClearToNull
@ ClearToNull
Reset value to null.
Definition: qgsfilterlineedit.h:65
QgsFilterLineEdit::setSelectOnFocus
void setSelectOnFocus(bool selectOnFocus)
Will select all text when this widget receives the focus.
Definition: qgsfilterlineedit.cpp:155
QgsFilterLineEdit::setShowSpinner
void setShowSpinner(bool showSpinner)
Show a spinner icon.
Definition: qgsfilterlineedit.cpp:169
field
const QgsField & field
Definition: qgsfield.h:463
QgsFeaturePickerModelBase::ValueRole
@ ValueRole
Used to retrieve the displayExpression of a feature.
Definition: qgsfeaturepickermodelbase.h:67
QgsFilterLineEdit::setClearMode
void setClearMode(ClearMode mode)
Sets the clear mode for the widget.
Definition: qgsfilterlineedit.h:106
QgsFeatureFilterModel::setIdentifierFields
void setIdentifierFields(const QStringList &identifierFields)
The identifier field should be a unique field that can be used to identify individual features.
Definition: qgsfeaturefiltermodel.cpp:121
QgsFeaturePickerModelBase::currentFeatureChanged
void currentFeatureChanged()
Emitted when the current feature in the model has changed This emitted both when the extra value chan...
QgsFeaturePickerModelBase::filterJobCompleted
void filterJobCompleted()
Indicates that a filter job has been completed and new data may be available.
QgsFeatureListComboBox::setIdentifierField
Q_DECL_DEPRECATED void setIdentifierField(const QString &identifierField)
Field name that will be used to uniquely identify the current feature.
Definition: qgsfeaturelistcombobox.cpp:200
QgsFeaturePickerModelBase::endUpdate
void endUpdate()
Notification that the model change is finished.
QgsFeaturePickerModelBase::isLoadingChanged
void isLoadingChanged()
Indicator if the model is currently performing any feature iteration in the background.
QgsFeatureRequest::setFilterExpression
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
Definition: qgsfeaturerequest.cpp:167
qgsapplication.h
QgsFeaturePickerModelBase::allowNull
bool allowNull
Definition: qgsfeaturepickermodelbase.h:53
QgsFeatureFilterModel
Provides a list of features based on filter conditions. Features are fetched asynchronously.
Definition: qgsfeaturefiltermodel.h:28
QgsFeatureListComboBox::setDisplayExpression
void setDisplayExpression(const QString &displayExpression)
The display expression will be used to display features as well as the value to match the typed text ...
Definition: qgsfeaturelistcombobox.cpp:95
QgsFilterLineEdit::hasStateStored
bool hasStateStored() const
Returns if a state is already saved.
Definition: qgsfilterlineedit.h:229
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsFeaturePickerModelBase::sourceLayer
QgsVectorLayer sourceLayer
Definition: qgsfeaturepickermodelbase.h:49
QgsFeatureListComboBox::modelUpdated
void modelUpdated()
The underlying model has been updated.
QgsFeatureListComboBox::allowNull
bool allowNull
Definition: qgsfeaturelistcombobox.h:49
QgsFeaturePickerModelBase::data
QVariant data(const QModelIndex &index, int role) const override
Definition: qgsfeaturepickermodelbase.cpp:153
QgsFeatureListComboBox::setIdentifierValues
void setIdentifierValues(const QVariantList &identifierValues)
The identifier values of the currently selected feature.
Definition: qgsfeaturelistcombobox.cpp:259
QgsFilterLineEdit::ClearToDefault
@ ClearToDefault
Reset value to default value (see defaultValue() )
Definition: qgsfilterlineedit.h:66
QgsApplication::nullRepresentation
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Definition: qgsapplication.cpp:2018
QgsFeaturePickerModelBase::extraIdentifierValueIndexChanged
void extraIdentifierValueIndexChanged(int index)
The index at which the extra identifier value is available within the model.
QgsFeatureFilterModel::identifierFieldsChanged
void identifierFieldsChanged()
The identifier field should be a unique field that can be used to identify individual features.
QgsFeatureListComboBox::setIdentifierValue
Q_DECL_DEPRECATED void setIdentifierValue(const QVariant &identifierValue)
The identifier value of the currently selected feature.
Definition: qgsfeaturelistcombobox.cpp:254
QgsFeaturePickerModelBase::index
QModelIndex index(int row, int column, const QModelIndex &parent) const override
Definition: qgsfeaturepickermodelbase.cpp:131
QgsFeaturePickerModelBase::displayExpression
QString displayExpression
Definition: qgsfeaturepickermodelbase.h:50
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:327
QgsFeatureListComboBox
This offers a combobox with autocompleter that allows selecting features from a layer.
Definition: qgsfeaturelistcombobox.h:39
QgsFeatureRequest::setFilterFids
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
Definition: qgsfeaturerequest.cpp:148
QgsFilterLineEdit::storeState
void storeState()
Stores the current state of the line edit (selection and cursor position)
Definition: qgsfilterlineedit.cpp:217
QgsFeatureListComboBox::currentFeatureRequest
QgsFeatureRequest currentFeatureRequest() const
Shorthand for getting a feature request to query the currently selected feature.
Definition: qgsfeaturelistcombobox.cpp:269
QgsFeatureListComboBox::currentModelIndex
QModelIndex currentModelIndex() const
The index of the currently selected item.
Definition: qgsfeaturelistcombobox.cpp:210
QgsExpression::createFieldEqualityExpression
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QVariant::Type fieldType=QVariant::Type::Invalid)
Create an expression allowing to evaluate if a field is equal to a value.
Definition: qgsexpression.cpp:1126
QgsFeaturePickerModelBase::setAllowNull
void setAllowNull(bool allowNull)
Add a NULL entry to the list.
Definition: qgsfeaturepickermodelbase.cpp:575
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsFeatureListComboBox::setSourceLayer
void setSourceLayer(QgsVectorLayer *sourceLayer)
The layer from which features should be listed.
Definition: qgsfeaturelistcombobox.cpp:74
QgsFeatureListComboBox::identifierFieldChanged
void identifierFieldChanged()
Field name that will be used to uniquely identify the current feature.
QgsFeaturePickerModelBase::setDisplayExpression
void setDisplayExpression(const QString &displayExpression)
The display expression will be used for.
Definition: qgsfeaturepickermodelbase.cpp:75
QgsFeatureListComboBox::setIdentifierFields
void setIdentifierFields(const QStringList &identifierFields)
Field name that will be used to uniquely identify the current feature.
Definition: qgsfeaturelistcombobox.cpp:205
QgsFeatureListComboBox::nullIndex
int nullIndex() const
Returns the current index of the NULL value, or -1 if NULL values are not allowed.
Definition: qgsfeaturelistcombobox.cpp:160
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsFeatureListComboBox::currentFeatureChanged
void currentFeatureChanged()
Emitted when the current feature changes.
QgsFeaturePickerModelBase::allowNullChanged
void allowNullChanged()
Add a NULL entry to the list.
QgsFeatureListComboBox::identifierValue
QVariant identifierValue
Definition: qgsfeaturelistcombobox.h:46
qgsanimatedicon.h
QgsFeatureListComboBox::displayExpressionChanged
void displayExpressionChanged()
The display expression will be used to display features as well as the the value to match the typed t...
QgsFeaturePickerModelBase::extraIdentifierValueChanged
void extraIdentifierValueChanged()
Allows specifying one value that does not need to match the filter criteria but will still be availab...
QgsFeatureListComboBox::setAllowNull
void setAllowNull(bool allowNull)
Determines if a NULL value should be available in the list.
Definition: qgsfeaturelistcombobox.cpp:236
QgsFeatureListComboBox::QgsFeatureListComboBox
QgsFeatureListComboBox(QWidget *parent=nullptr)
Create a new QgsFeatureListComboBox, optionally specifying a parent.
Definition: qgsfeaturelistcombobox.cpp:27
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsFilterLineEdit::setShowClearButton
void setShowClearButton(bool visible)
Sets whether the widget's clear button is visible.
Definition: qgsfilterlineedit.cpp:43
qgslogger.h
QgsFeatureListComboBox::displayExpression
QString displayExpression
Definition: qgsfeaturelistcombobox.h:44
QgsFeatureListComboBox::setIdentifierValuesToNull
void setIdentifierValuesToNull()
Sets the identifier values of the currently selected feature to NULL value(s).
Definition: qgsfeaturelistcombobox.cpp:264
QgsFeaturePickerModelBase::setSourceLayer
void setSourceLayer(QgsVectorLayer *sourceLayer)
The source layer from which features will be fetched.
Definition: qgsfeaturepickermodelbase.cpp:52
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsFeatureListComboBox::filterExpressionChanged
void filterExpressionChanged()
An additional expression to further restrict the available features.
QgsFeaturePickerModelBase::setFilterExpression
void setFilterExpression(const QString &filterExpression)
An additional filter expression to apply, next to the filterValue.
Definition: qgsfeaturepickermodelbase.cpp:109
QgsFeaturePickerModelBase::sourceLayerChanged
void sourceLayerChanged()
The source layer from which features will be fetched.
QgsFeaturePickerModelBase::setFilterValue
void setFilterValue(const QString &filterValue)
This value will be used to filter the features available from this model.
Definition: qgsfeaturepickermodelbase.cpp:92
QgsFeatureListComboBox::sourceLayer
QgsVectorLayer sourceLayer
Definition: qgsfeaturelistcombobox.h:43
QgsFeaturePickerModelBase::beginUpdate
void beginUpdate()
Notification that the model is about to be changed because a job was completed.
QgsFeatureFilterModel::setExtraIdentifierValueToNull
void setExtraIdentifierValueToNull() override
Allows specifying one value that does not need to match the filter criteria but will still be availab...
Definition: qgsfeaturefiltermodel.cpp:152
QgsFeatureFilterModel::setExtraIdentifierValues
void setExtraIdentifierValues(const QVariantList &extraIdentifierValues)
Allows specifying one value that does not need to match the filter criteria but will still be availab...
Definition: qgsfeaturefiltermodel.cpp:147
QgsFeaturePickerModelBase::filterExpressionChanged
void filterExpressionChanged()
An additional filter expression to apply, next to the filterValue.