QGIS API Documentation  3.0.2-Girona (307d082)
qgsfeaturelistcombobox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfieldlistcombobox.cpp - QgsFieldListComboBox
3 
4  ---------------------
5  begin : 10.3.2017
6  copyright : (C) 2017 by Matthias Kuhn
7  email : [email protected]
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 #include "qgsfeaturelistcombobox.h"
17 
18 #include "qgsfeaturefiltermodel.h"
19 #include "qgsanimatedicon.h"
20 #include "qgsfilterlineedit.h"
21 #include "qgslogger.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  setCompleter( mCompleter );
35  mCompleter->setWidget( this );
39  connect( mModel, &QgsFeatureFilterModel::isLoadingChanged, this, &QgsFeatureListComboBox::onLoadingChanged );
40  connect( mModel, &QgsFeatureFilterModel::filterJobCompleted, this, &QgsFeatureListComboBox::onFilterUpdateCompleted );
43  connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueIndexChanged, this, &QgsFeatureListComboBox::setCurrentIndex );
45  connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeatureListComboBox::onItemSelected );
46  connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeatureListComboBox::onActivated );
47  connect( mModel, &QgsFeatureFilterModel::beginUpdate, this, &QgsFeatureListComboBox::storeLineEditState );
48  connect( mModel, &QgsFeatureFilterModel::endUpdate, this, &QgsFeatureListComboBox::restoreLineEditState );
49  connect( mModel, &QgsFeatureFilterModel::dataChanged, this, &QgsFeatureListComboBox::onDataChanged );
50 
51  connect( this, static_cast<void( QgsFeatureListComboBox::* )( int )>( &QgsFeatureListComboBox::currentIndexChanged ), this, &QgsFeatureListComboBox::onCurrentIndexChanged );
52 
53  mLineEdit = new QgsFilterLineEdit();
54  mLineEdit->setSelectOnFocus( true );
55  setEditable( true );
56  setLineEdit( mLineEdit );
57  setModel( mModel );
58 
59  connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeatureListComboBox::onCurrentTextChanged );
60 
61  setToolTip( tr( "Just start typing what you are looking for." ) );
62 }
63 
65 {
66  return mModel->sourceLayer();
67 }
68 
70 {
71  mModel->setSourceLayer( sourceLayer );
72 }
73 
75 {
76  return mModel->displayExpression();
77 }
78 
79 void QgsFeatureListComboBox::setDisplayExpression( const QString &expression )
80 {
81  mModel->setDisplayExpression( expression );
82 }
83 
84 void QgsFeatureListComboBox::onCurrentTextChanged( const QString &text )
85 {
86  mIsCurrentlyEdited = true;
87  mPopupRequested = true;
88  mModel->setFilterValue( text );
89 }
90 
91 void QgsFeatureListComboBox::onFilterUpdateCompleted()
92 {
93  if ( mPopupRequested )
94  mCompleter->complete();
95 
96  mPopupRequested = false;
97 }
98 
99 void QgsFeatureListComboBox::onLoadingChanged()
100 {
101  mLineEdit->setShowSpinner( mModel->isLoading() );
102 }
103 
104 void QgsFeatureListComboBox::onItemSelected( const QModelIndex &index )
105 {
106  setCurrentIndex( index.row() );
107 }
108 
109 void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
110 {
111  mIsCurrentlyEdited = false;
112  QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
114  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
115  mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
116  QPalette palette = mLineEdit->palette();
117  palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
118  mLineEdit->setPalette( palette );
119 }
120 
121 void QgsFeatureListComboBox::onActivated( QModelIndex modelIndex )
122 {
124  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
125 }
126 
127 void QgsFeatureListComboBox::storeLineEditState()
128 {
129  if ( mIsCurrentlyEdited )
130  mLineEditState.store( mLineEdit );
131 }
132 
133 void QgsFeatureListComboBox::restoreLineEditState()
134 {
135  if ( mIsCurrentlyEdited )
136  mLineEditState.restore( mLineEdit );
137 }
138 
139 void QgsFeatureListComboBox::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
140 {
141  Q_UNUSED( roles )
142  if ( !mIsCurrentlyEdited )
143  {
144  const int currentIndex = mModel->extraIdentifierValueIndex();
145  if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
146  {
147  QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
148  mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
149  }
150  }
151 }
152 
154 {
155  return mModel->identifierField();
156 }
157 
159 {
160  mModel->setIdentifierField( identifierField );
161 }
162 
164 {
165  return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
166 }
167 
168 void QgsFeatureListComboBox::focusOutEvent( QFocusEvent *event )
169 {
170  Q_UNUSED( event )
171  QComboBox::focusOutEvent( event );
172  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
173 }
174 
176 {
177  if ( event->key() == Qt::Key_Escape )
178  {
179  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
180  }
181  QComboBox::keyReleaseEvent( event );
182 }
183 
185 {
186  return mModel->allowNull();
187 }
188 
190 {
191  mModel->setAllowNull( allowNull );
192 }
193 
195 {
196  return mModel->extraIdentifierValue();
197 }
198 
200 {
201  mModel->setExtraIdentifierValue( identifierValue );
202 }
203 
205 {
206  if ( mModel->extraIdentifierValue().isNull() )
207  return QgsFeatureRequest().setFilterFids( QgsFeatureIds() ); // NULL: Return a request that's guaranteed to not return anything
208  else
209  return QgsFeatureRequest().setFilterExpression( QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( mModel->identifierField() ), QgsExpression::quotedValue( mModel->extraIdentifierValue() ) ) );
210 }
211 
213 {
214  return mModel->filterExpression();
215 }
216 
218 {
219  mModel->setFilterExpression( filterExpression );
220 }
221 
222 void QgsFeatureListComboBox::LineEditState::store( QLineEdit *lineEdit )
223 {
224  text = lineEdit->text();
225  selectionStart = lineEdit->selectionStart();
226  selectionLength = lineEdit->selectedText().length();
227  cursorPosition = lineEdit->cursorPosition();
228 
229 }
230 
231 void QgsFeatureListComboBox::LineEditState::restore( QLineEdit *lineEdit ) const
232 {
233  lineEdit->setText( text );
234  lineEdit->setCursorPosition( cursorPosition );
235  if ( selectionStart > -1 )
236  lineEdit->setSelection( selectionStart, selectionLength );
237 }
void setIdentifierValue(const QVariant &identifierValue)
The identifier value of the currently selected feature.
QString identifierField() const
Field name that will be used to uniquely identify the current feature.
Provides a list of features based on filter conditions.
This offers a combobox with autocompleter that allows selecting features from a layer.
QgsFeatureRequest currentFeatureRequest() const
Shorthand for getting a feature request to query the currently selected feature.
QModelIndex currentModelIndex() const
The index of the currently selected item.
void setSelectOnFocus(bool selectOnFocus)
Will select all text when this widget receives the focus.
void beginUpdate()
Notification that the model is about to be changed because a job was completed.
Used to retrieve the displayExpression of a feature.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:544
void identifierFieldChanged()
Field name that will be used to uniquely identify the current feature.
void setFilterExpression(const QString &filterExpression)
An additional filter expression to apply, next to the filterValue.
QString filterExpression() const
An additional expression to further restrict the available features.
void setShowSpinner(bool showSpinner)
Show a spinner icon.
void displayExpressionChanged()
The display expression will be used to display features as well as the the value to match the typed t...
void filterJobCompleted()
Indicates that a filter job has been completed and new data may be available.
void extraIdentifierValueIndexChanged(int index)
The index at which the extra identifier value is available within the model.
void setSourceLayer(QgsVectorLayer *sourceLayer)
The layer from which features should be listed.
void filterExpressionChanged()
An additional expression to further restrict the available features.
QgsVectorLayer * sourceLayer() const
The layer from which features should be listed.
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...
void setAllowNull(bool allowNull)
Determines if a NULL value should be available in the list.
QString displayExpression() const
The display expression will be used to display features as well as the the value to match the typed t...
QgsFeatureListComboBox(QWidget *parent=nullptr)
Create a new QgsFeatureListComboBox, optionally specifying a parent.
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
QString identifierField
A field of sourceLayer that is unique and should be used to identify features.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
QVariant extraIdentifierValue
The value that identifies the current feature.
void identifierValueChanged()
The identifier value of the currently selected feature.
void isLoadingChanged()
Indicator if the model is currently performing any feature iteration in the background.
void allowNullChanged()
Add a NULL entry to the list.
void filterExpressionChanged()
An additional filter expression to apply, next to the filterValue.
void endUpdate()
Notification that the model change is finished.
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.
void setFilterExpression(const QString &filterExpression)
An additional expression to further restrict the available features.
void sourceLayerChanged()
The source layer from which features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
void allowNullChanged()
Determines if a NULL value should be available in the list.
void keyPressEvent(QKeyEvent *event) override
void setExtraIdentifierValue(const QVariant &extraIdentifierValue)
Allows specifying one value that does not need to match the filter criteria but will still be availab...
void sourceLayerChanged()
The layer from which features should be listed.
void focusOutEvent(QFocusEvent *event) override
QVariant data(const QModelIndex &index, int role) const override
void setAllowNull(bool allowNull)
Add a NULL entry to the list.
QVariant identifierValue() const
The identifier value of the currently selected feature.
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.
void setDisplayExpression(const QString &displayExpression)
The display expression will be used to display features as well as the the value to match the typed t...
void setIdentifierField(const QString &identifierField)
Field name that will be used to uniquely identify the current feature.
bool allowNull() const
Determines if a NULL value should be available in the list.
void displayExpressionChanged()
The display expression will be used for.