QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
64  setToolTip( tr( "Just start typing what you are looking for." ) );
65 }
66 
68 {
69  return mModel->sourceLayer();
70 }
71 
73 {
74  mModel->setSourceLayer( sourceLayer );
75 }
76 
78 {
79  QVariantList values;
80  const QStringList fields = mModel->identifierFields();
81  for ( const QString &field : fields )
82  {
83  values << feature.attribute( field );
84  }
85  setIdentifierValues( values );
86 }
87 
89 {
90  return mModel->displayExpression();
91 }
92 
93 void QgsFeatureListComboBox::setDisplayExpression( const QString &expression )
94 {
95  mModel->setDisplayExpression( expression );
96 }
97 
98 void QgsFeatureListComboBox::onCurrentTextChanged( const QString &text )
99 {
100  mIsCurrentlyEdited = true;
101  mPopupRequested = true;
102  mModel->setFilterValue( text );
103 }
104 
105 void QgsFeatureListComboBox::onFilterUpdateCompleted()
106 {
107  if ( mPopupRequested )
108  mCompleter->complete();
109 
110  mPopupRequested = false;
111 }
112 
113 void QgsFeatureListComboBox::onLoadingChanged()
114 {
115  mLineEdit->setShowSpinner( mModel->isLoading() );
116 }
117 
118 void QgsFeatureListComboBox::onItemSelected( const QModelIndex &index )
119 {
120  setCurrentIndex( index.row() );
121 }
122 
123 void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
124 {
125  if ( !mLineEdit->hasStateStored() )
126  mIsCurrentlyEdited = false;
127  QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
128  mModel->setExtraIdentifierValues( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValuesRole ).toList() );
129  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
130  mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
131  QPalette palette = mLineEdit->palette();
132  palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
133  mLineEdit->setPalette( palette );
134 }
135 
136 void QgsFeatureListComboBox::onActivated( QModelIndex modelIndex )
137 {
138  setIdentifierValues( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValuesRole ).toList() );
139  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
140 }
141 
142 void QgsFeatureListComboBox::storeLineEditState()
143 {
144  if ( mIsCurrentlyEdited )
145  {
146  mLineEdit->storeState( );
147  }
148 }
149 
150 void QgsFeatureListComboBox::restoreLineEditState()
151 {
152  if ( mIsCurrentlyEdited )
153  {
154  mLineEdit->restoreState( );
155  }
156 }
157 
159 {
160  int index = -1;
161 
162  if ( allowNull() )
163  {
164  index = findText( QgsApplication::nullRepresentation( ) );
165  }
166 
167  return index;
168 }
169 
170 void QgsFeatureListComboBox::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
171 {
172  Q_UNUSED( roles )
173  if ( !mIsCurrentlyEdited )
174  {
175  const int currentIndex = mModel->extraIdentifierValueIndex();
176  if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
177  {
178  QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
179  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
180  }
181  }
182 }
183 
185 {
186  QStringList list = mModel->identifierFields();
187  if ( list.isEmpty() )
188  return QString();
189  else
190  return list.at( 0 );
191 }
192 
194 {
195  return mModel->identifierFields();
196 }
197 
198 void QgsFeatureListComboBox::setIdentifierField( const QString &identifierField )
199 {
200  mModel->setIdentifierFields( QStringList() << identifierField );
201 }
202 
203 void QgsFeatureListComboBox::setIdentifierFields( const QStringList &identifierFields )
204 {
206 }
207 
209 {
210  return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
211 }
212 
213 void QgsFeatureListComboBox::focusOutEvent( QFocusEvent *event )
214 {
215  Q_UNUSED( event )
216  QComboBox::focusOutEvent( event );
217  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
218 }
219 
221 {
222  if ( event->key() == Qt::Key_Escape )
223  {
224  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
225  }
226  QComboBox::keyReleaseEvent( event );
227 }
228 
230 {
231  return mModel->allowNull();
232 }
233 
235 {
236  mModel->setAllowNull( allowNull );
238 }
239 
241 {
243  return mModel->extraIdentifierValues().value( 0 );
245 }
246 
248 {
249  return mModel->extraIdentifierValues();
250 }
251 
252 void QgsFeatureListComboBox::setIdentifierValue( const QVariant &identifierValue )
253 {
254  setIdentifierValues( QVariantList() << identifierValue );
255 }
256 
257 void QgsFeatureListComboBox::setIdentifierValues( const QVariantList &identifierValues )
258 {
260 }
261 
263 {
265 }
266 
268 {
269  if ( mModel->extraIdentifierValues().isEmpty() )
270  {
271  return QgsFeatureRequest().setFilterFids( QgsFeatureIds() ); // NULL: Return a request that's guaranteed to not return anything
272  }
273  else
274  {
275  QStringList filtersAttrs;
276  const QStringList identifierFields = mModel->identifierFields();
277  const QVariantList values = mModel->extraIdentifierValues();
278  for ( int i = 0; i < identifierFields.count(); i++ )
279  {
280  if ( i >= values.count() )
281  {
282  filtersAttrs << QgsExpression::createFieldEqualityExpression( identifierFields.at( i ), QVariant() );
283  }
284  else
285  {
286  filtersAttrs << QgsExpression::createFieldEqualityExpression( identifierFields.at( i ), values.at( i ) );
287  }
288  }
289  const QString expression = filtersAttrs.join( QLatin1String( " AND " ) );
290  return QgsFeatureRequest().setFilterExpression( expression );
291  }
292 }
293 
295 {
296  return mModel->filterExpression();
297 }
298 
299 void QgsFeatureListComboBox::setFilterExpression( const QString &filterExpression )
300 {
302 }
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:193
QgsFeaturePickerModelBase::isLoading
bool isLoading() const
Indicator if the model is currently performing any feature iteration in the background.
Definition: qgsfeaturepickermodelbase.cpp:112
QgsFeaturePickerModelBase::extraIdentifierValueIndex
int extraIdentifierValueIndex
Definition: qgsfeaturepickermodelbase.h:41
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:37
QgsFeatureListComboBox::setCurrentFeature
void setCurrentFeature(const QgsFeature &feature)
Sets the current index by using the given feature.
Definition: qgsfeaturelistcombobox.cpp:77
QgsFeatureListComboBox::allowNullChanged
void allowNullChanged()
Determines if a NULL value should be available in the list.
QgsFeaturePickerModelBase::filterExpression
QString filterExpression
Definition: qgsfeaturepickermodelbase.h:37
qgsfeaturelistcombobox.h
QgsFeatureListComboBox::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: qgsfeaturelistcombobox.cpp:220
QgsFeatureListComboBox::setFilterExpression
void setFilterExpression(const QString &filterExpression)
An additional expression to further restrict the available features.
Definition: qgsfeaturelistcombobox.cpp:299
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:213
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:51
QgsFeatureFilterModel::extraIdentifierValues
QVariantList extraIdentifierValues
The values that identifies the current feature.
Definition: qgsfeaturefiltermodel.h:42
qgsfilterlineedit.h
QgsFilterLineEdit
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Definition: qgsfilterlineedit.h:40
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:456
QgsFeaturePickerModelBase::ValueRole
@ ValueRole
Used to retrieve the displayExpression of a feature.
Definition: qgsfeaturepickermodelbase.h:52
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::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:198
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:124
qgsapplication.h
QgsFeaturePickerModelBase::allowNull
bool allowNull
Definition: qgsfeaturepickermodelbase.h:38
QgsFeatureFilterModel
Provides a list of features based on filter conditions.
Definition: qgsfeaturefiltermodel.h:29
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:93
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:797
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:76
QgsFeaturePickerModelBase::sourceLayer
QgsVectorLayer * sourceLayer
Definition: qgsfeaturepickermodelbase.h:34
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:145
QgsFeatureListComboBox::setIdentifierValues
void setIdentifierValues(const QVariantList &identifierValues)
The identifier values of the currently selected feature.
Definition: qgsfeaturelistcombobox.cpp:257
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:1851
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:252
QgsFeaturePickerModelBase::index
QModelIndex index(int row, int column, const QModelIndex &parent) const override
Definition: qgsfeaturepickermodelbase.cpp:123
QgsFeaturePickerModelBase::displayExpression
QString displayExpression
Definition: qgsfeaturepickermodelbase.h:35
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:264
QgsFeatureListComboBox
This offers a combobox with autocompleter that allows selecting features from a layer.
Definition: qgsfeaturelistcombobox.h:40
QgsFeatureRequest::setFilterFids
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
Definition: qgsfeaturerequest.cpp:105
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:267
QgsFeatureListComboBox::currentModelIndex
QModelIndex currentModelIndex() const
The index of the currently selected item.
Definition: qgsfeaturelistcombobox.cpp:208
QgsFeaturePickerModelBase::setAllowNull
void setAllowNull(bool allowNull)
Add a NULL entry to the list.
Definition: qgsfeaturepickermodelbase.cpp:562
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:72
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:67
QgsExpression::createFieldEqualityExpression
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
Definition: qgsexpression.cpp:1079
QgsFeatureListComboBox::setIdentifierFields
void setIdentifierFields(const QStringList &identifierFields)
Field name that will be used to uniquely identify the current feature.
Definition: qgsfeaturelistcombobox.cpp:203
QgsFeatureListComboBox::nullIndex
int nullIndex() const
Returns the current index of the NULL value, or -1 if NULL values are not allowed.
Definition: qgsfeaturelistcombobox.cpp:158
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
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:234
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 id, geometry and a list of field/values...
Definition: qgsfeature.h:56
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:262
QgsFeaturePickerModelBase::setSourceLayer
void setSourceLayer(QgsVectorLayer *sourceLayer)
The source layer from which features will be fetched.
Definition: qgsfeaturepickermodelbase.cpp:47
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:796
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:101
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:84
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.