QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsfeaturepickerwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeaturepickerwidget.cpp - QgsFeaturePickerWidget
3  ---------------------
4  begin : 03.04.2020
5  copyright : (C) 2020 by Denis Rouzaud
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 
16 #include <QHBoxLayout>
17 #include <QToolButton>
18 #include <QKeyEvent>
19 
20 #include "qgsfeaturepickerwidget.h"
21 #include "qgsfilterlineedit.h"
22 #include "qgsfeaturepickermodel.h"
23 
25  : QWidget( parent )
26  , mModel( new QgsFeaturePickerModel( this ) )
27  , mCompleter( new QCompleter( mModel ) )
28 {
29  QHBoxLayout *layout = new QHBoxLayout();
30  mComboBox = new QComboBox( this );
31  mComboBox->setEditable( true );
32  layout->addWidget( mComboBox );
33 
34  mPreviousButton = new QToolButton( this );
35  mPreviousButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionArrowLeft.svg" ) ) );
36  mPreviousButton->setEnabled( false );
37  mPreviousButton->setVisible( mShowBrowserButtons );
38  layout->addWidget( mPreviousButton );
39 
40  mNextButton = new QToolButton( this );
41  mNextButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionArrowRight.svg" ) ) );
42  mNextButton->setEnabled( false );
43  mNextButton->setVisible( mShowBrowserButtons );
44  layout->addWidget( mNextButton );
45  layout->setContentsMargins( 0, 0, 0, 0 );
46 
47  setLayout( layout );
48 
49  mCompleter->setCaseSensitivity( Qt::CaseInsensitive );
50  mCompleter->setFilterMode( Qt::MatchContains );
51  mComboBox->setCompleter( mCompleter );
52  mCompleter->setWidget( mComboBox );
56  connect( mModel, &QgsFeaturePickerModel::isLoadingChanged, this, &QgsFeaturePickerWidget::onLoadingChanged );
57  connect( mModel, &QgsFeaturePickerModel::filterJobCompleted, this, &QgsFeaturePickerWidget::onFilterUpdateCompleted );
61  connect( mModel, &QgsFeaturePickerModel::extraIdentifierValueIndexChanged, mComboBox, &QComboBox::setCurrentIndex );
63  connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeaturePickerWidget::onItemSelected );
64  connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeaturePickerWidget::onActivated );
65  connect( mModel, &QgsFeaturePickerModel::beginUpdate, this, &QgsFeaturePickerWidget::storeLineEditState );
66  connect( mModel, &QgsFeaturePickerModel::endUpdate, this, &QgsFeaturePickerWidget::restoreLineEditState );
68  connect( mModel, &QgsFeaturePickerModel::dataChanged, this, &QgsFeaturePickerWidget::onDataChanged );
69 
70  connect( mComboBox, static_cast<void( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFeaturePickerWidget::onCurrentIndexChanged );
71 
72  connect( mPreviousButton, &QToolButton::clicked, this, [ = ]() {browseFeatures( -1 );} );
73  connect( mNextButton, &QToolButton::clicked, this, [ = ]() {browseFeatures( 1 );} );
74 
75  mLineEdit = new QgsFilterLineEdit( nullptr, QgsApplication::nullRepresentation() );
76  mLineEdit->setSelectOnFocus( true );
77  mLineEdit->setShowClearButton( allowNull() );
78 
79  mComboBox->setEditable( true );
80  mComboBox->setLineEdit( mLineEdit );
81  mComboBox->setModel( mModel );
82 
83  connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeaturePickerWidget::onCurrentTextChanged );
84 }
85 
87 {
88  return mModel->sourceLayer();
89 }
90 
92 {
93  mModel->setSourceLayer( sourceLayer );
94 }
95 
97 {
98  mModel->setFeature( featureId );
99 }
100 
102 {
103  return mModel->feature();
104 }
105 
107 {
108  return mModel->displayExpression();
109 }
110 
111 void QgsFeaturePickerWidget::setDisplayExpression( const QString &expression )
112 {
113  mModel->setDisplayExpression( expression );
114 }
115 
116 void QgsFeaturePickerWidget::onCurrentTextChanged( const QString &text )
117 {
118  mIsCurrentlyEdited = true;
119  mPopupRequested = true;
120  mModel->setFilterValue( text );
121 }
122 
123 void QgsFeaturePickerWidget::onFilterUpdateCompleted()
124 {
125  if ( mPopupRequested )
126  mCompleter->complete();
127 
128  mPopupRequested = false;
129 }
130 
131 void QgsFeaturePickerWidget::onLoadingChanged()
132 {
133  mLineEdit->setShowSpinner( mModel->isLoading() );
134 }
135 
136 void QgsFeaturePickerWidget::onItemSelected( const QModelIndex &index )
137 {
138  mComboBox->setCurrentIndex( index.row() );
139 }
140 
141 void QgsFeaturePickerWidget::onCurrentIndexChanged( int i )
142 {
143  if ( !mLineEdit->hasStateStored() )
144  mIsCurrentlyEdited = false;
145 
146  mPreviousButton->setEnabled( i > 0 );
147  mNextButton->setEnabled( i < mComboBox->model()->rowCount() - 1 );
148 
149  if ( i < 0 )
150  return;
151 
152  QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
153  mModel->setFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
154  mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
155  mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
156  QPalette palette = mLineEdit->palette();
157  palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
158  mLineEdit->setPalette( palette );
159 }
160 
161 void QgsFeaturePickerWidget::onActivated( QModelIndex modelIndex )
162 {
163  setFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
164  mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
165 }
166 
167 void QgsFeaturePickerWidget::storeLineEditState()
168 {
169  if ( mIsCurrentlyEdited )
170  {
171  mLineEdit->storeState( );
172  }
173 }
174 
175 void QgsFeaturePickerWidget::restoreLineEditState()
176 {
177  if ( mIsCurrentlyEdited )
178  {
179  mLineEdit->restoreState( );
180  }
181 }
182 
184 {
185  int index = -1;
186 
187  if ( allowNull() )
188  {
189  index = mComboBox->findText( QgsApplication::nullRepresentation( ) );
190  }
191 
192  return index;
193 }
194 
195 void QgsFeaturePickerWidget::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
196 {
197  Q_UNUSED( roles )
198  if ( !mIsCurrentlyEdited )
199  {
200  const int currentIndex = mModel->extraIdentifierValueIndex();
201  if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
202  {
203  QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
204  mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
205  }
206  }
207 }
208 
209 void QgsFeaturePickerWidget::browseFeatures( int direction )
210 {
211  int newIndex = std::min( std::max( 0, mComboBox->currentIndex() + direction ), mComboBox->model()->rowCount() - 1 );
212  mComboBox->setCurrentIndex( newIndex );
213 }
214 
216 {
217  return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
218 }
219 
220 void QgsFeaturePickerWidget::focusOutEvent( QFocusEvent *event )
221 {
222  Q_UNUSED( event )
223  QWidget::focusOutEvent( event );
224  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeaturePickerModel::ValueRole ).toString() );
225 }
226 
228 {
229  if ( event->key() == Qt::Key_Escape )
230  {
231  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeaturePickerModel::ValueRole ).toString() );
232  }
233  QWidget::keyReleaseEvent( event );
234 }
235 
237 {
238  return mModel->allowNull();
239 }
240 
242 {
243  mModel->setAllowNull( allowNull );
245 }
246 
248 {
249  return mModel->filterExpression();
250 }
251 
252 void QgsFeaturePickerWidget::setFilterExpression( const QString &filterExpression )
253 {
255 }
256 
258 {
259  return mModel->fetchGeometry();
260 }
261 
263 {
264  mModel->setFetchGeometry( fetchGeometry );
265 }
266 
268 {
269  return mModel->fetchLimit();
270 }
271 
273 {
274  mModel->setFetchLimit( fetchLimit );
275 }
276 
278 {
279  return mShowBrowserButtons;
280 }
281 
282 void QgsFeaturePickerWidget::setShowBrowserButtons( bool showBrowserButtons )
283 {
284  if ( showBrowserButtons == mShowBrowserButtons )
285  return;
286 
287  mShowBrowserButtons = showBrowserButtons;
288  mPreviousButton->setVisible( mShowBrowserButtons );
289  mNextButton->setVisible( mShowBrowserButtons );
291 }
QgsFeaturePickerModel::featureChanged
void featureChanged(const QgsFeature &feature)
Emitted when the current feature changes.
QgsFeaturePickerWidget::filterExpressionChanged
void filterExpressionChanged()
An additional expression to further restrict the available features.
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.
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsFeaturePickerWidget::layerChanged
void layerChanged()
The layer from which features should be listed.
QgsFeaturePickerWidget::filterExpression
QString filterExpression
Definition: qgsfeaturepickerwidget.h:50
QgsFeaturePickerModelBase::filterExpression
QString filterExpression
Definition: qgsfeaturepickermodelbase.h:37
QgsFeaturePickerWidget::showBrowserButtonsChanged
void showBrowserButtonsChanged()
Emitted when showing the browser buttons changes.
QgsFeaturePickerWidget::currentModelIndex
QModelIndex currentModelIndex() const
The index of the currently selected item.
Definition: qgsfeaturepickerwidget.cpp:215
QgsFilterLineEdit::restoreState
void restoreState()
Restores the current state of the line edit (selection and cursor position)
Definition: qgsfilterlineedit.cpp:226
QgsFeaturePickerWidget::modelUpdated
void modelUpdated()
The underlying model has been updated.
QgsFeaturePickerWidget::nullIndex
int nullIndex() const
Returns the current index of the NULL value, or -1 if NULL values are not allowed.
Definition: qgsfeaturepickerwidget.cpp:183
QgsFeaturePickerWidget::showBrowserButtons
bool showBrowserButtons
Definition: qgsfeaturepickerwidget.h:54
QgsFeaturePickerWidget::setFeature
void setFeature(QgsFeatureId featureId)
Sets the current index by using the given feature.
Definition: qgsfeaturepickerwidget.cpp:96
qgsfilterlineedit.h
QgsFilterLineEdit
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Definition: qgsfilterlineedit.h:40
QgsFeaturePickerWidget::featureChanged
void featureChanged(const QgsFeature &feature)
Sends the feature as soon as it is chosen.
QgsFilterLineEdit::ClearToNull
@ ClearToNull
Reset value to null.
Definition: qgsfilterlineedit.h:65
QgsFilterLineEdit::setShowSpinner
void setShowSpinner(bool showSpinner)
Show a spinner icon.
Definition: qgsfilterlineedit.cpp:169
QgsFeaturePickerWidget::fetchLimit
int fetchLimit
Definition: qgsfeaturepickerwidget.h:53
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
QgsFeaturePickerModelBase::filterJobCompleted
void filterJobCompleted()
Indicates that a filter job has been completed and new data may be available.
QgsFeaturePickerModel
Provides a list of features based on filter conditions.
Definition: qgsfeaturepickermodel.h:32
qgsfeaturepickerwidget.h
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.
QgsFeaturePickerModelBase::fetchGeometry
bool fetchGeometry
Definition: qgsfeaturepickermodelbase.h:39
QgsFeaturePickerWidget::setLayer
void setLayer(QgsVectorLayer *layer)
The layer from which features should be listed.
Definition: qgsfeaturepickerwidget.cpp:91
QgsFeaturePickerModelBase::allowNull
bool allowNull
Definition: qgsfeaturepickermodelbase.h:38
QgsFilterLineEdit::hasStateStored
bool hasStateStored() const
Returns if a state is already saved.
Definition: qgsfilterlineedit.h:229
QgsFeaturePickerModelBase::sourceLayer
QgsVectorLayer * sourceLayer
Definition: qgsfeaturepickermodelbase.h:34
QgsFeaturePickerWidget::displayExpressionChanged
void displayExpressionChanged()
The display expression will be used to display features as well as the the value to match the typed t...
QgsFeaturePickerModelBase::data
QVariant data(const QModelIndex &index, int role) const override
Definition: qgsfeaturepickermodelbase.cpp:145
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.
QgsFeaturePickerModelBase::fetchLimitChanged
void fetchLimitChanged()
Emitted when the fetching limit for the feature request changes.
QgsFeaturePickerWidget::layer
QgsVectorLayer * layer
Definition: qgsfeaturepickerwidget.h:48
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
QgsFeaturePickerWidget::setAllowNull
void setAllowNull(bool allowNull)
Determines if a NULL value should be available in the list.
Definition: qgsfeaturepickerwidget.cpp:241
QgsFeaturePickerWidget::focusOutEvent
void focusOutEvent(QFocusEvent *event) override
Definition: qgsfeaturepickerwidget.cpp:220
QgsFilterLineEdit::storeState
void storeState()
Stores the current state of the line edit (selection and cursor position)
Definition: qgsfilterlineedit.cpp:217
QgsFeaturePickerModelBase::setAllowNull
void setAllowNull(bool allowNull)
Add a NULL entry to the list.
Definition: qgsfeaturepickermodelbase.cpp:562
QgsFeaturePickerWidget::QgsFeaturePickerWidget
QgsFeaturePickerWidget(QWidget *parent=nullptr)
Create a new QgsFeaturePickerWidget, optionally specifying a parent.
Definition: qgsfeaturepickerwidget.cpp:24
QgsFeaturePickerWidget::setFetchLimit
void setFetchLimit(int fetchLimit)
Defines the feature request fetch limit If set to 0, no limit is applied when fetching.
Definition: qgsfeaturepickerwidget.cpp:272
QgsFeaturePickerWidget::feature
QgsFeature feature() const
Returns the current feature.
Definition: qgsfeaturepickerwidget.cpp:101
QgsFeaturePickerWidget::setShowBrowserButtons
void setShowBrowserButtons(bool showBrowserButtons)
Defines if the browsing buttons are shown.
Definition: qgsfeaturepickerwidget.cpp:282
QgsFeaturePickerWidget::fetchGeometryChanged
void fetchGeometryChanged()
Emitted when the fetching of the geometry changes.
QgsFeaturePickerModelBase::setDisplayExpression
void setDisplayExpression(const QString &displayExpression)
The display expression will be used for.
Definition: qgsfeaturepickermodelbase.cpp:67
QgsFeaturePickerModel::setFeature
void setFeature(const QgsFeatureId &fid)
Set the feature to the given feature id.
Definition: qgsfeaturepickermodel.cpp:69
QgsFeaturePickerModelBase::fetchLimit
int fetchLimit
Definition: qgsfeaturepickermodelbase.h:40
QgsFeaturePickerWidget::setFetchGeometry
void setFetchGeometry(bool fetchGeometry)
Defines if the geometry will be fetched.
Definition: qgsfeaturepickerwidget.cpp:262
qgsfeaturepickermodel.h
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsFeaturePickerModel::feature
QgsFeature feature() const
Returns the current feature.
Definition: qgsfeaturepickermodel.cpp:74
QgsFeaturePickerModelBase::allowNullChanged
void allowNullChanged()
Add a NULL entry to the list.
QgsFeaturePickerWidget::displayExpression
QString displayExpression
Definition: qgsfeaturepickerwidget.h:49
QgsFeaturePickerWidget::fetchGeometry
bool fetchGeometry
Definition: qgsfeaturepickerwidget.h:52
QgsFeaturePickerWidget::allowNull
bool allowNull
Definition: qgsfeaturepickerwidget.h:51
QgsFeaturePickerWidget::fetchLimitChanged
void fetchLimitChanged()
Emitted when the fetching limit for the feature request changes.
QgsFeaturePickerModelBase::fetchGeometryChanged
void fetchGeometryChanged()
Emitted when the fetching of the geometry changes.
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsFeaturePickerWidget::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: qgsfeaturepickerwidget.cpp:227
QgsFeaturePickerWidget::setFilterExpression
void setFilterExpression(const QString &filterExpression)
An additional expression to further restrict the available features.
Definition: qgsfeaturepickerwidget.cpp:252
QgsFeaturePickerModelBase::setFetchLimit
void setFetchLimit(int fetchLimit)
Defines the feature request fetch limit If set to 0, no limit is applied when fetching.
Definition: qgsfeaturepickermodelbase.cpp:592
QgsFeaturePickerModelBase::setFetchGeometry
void setFetchGeometry(bool fetchGeometry)
Defines if the geometry will be fetched.
Definition: qgsfeaturepickermodelbase.cpp:578
QgsFeaturePickerModelBase::setSourceLayer
void setSourceLayer(QgsVectorLayer *sourceLayer)
The source layer from which features will be fetched.
Definition: qgsfeaturepickermodelbase.cpp:47
QgsFeaturePickerModelBase::FeatureIdRole
@ FeatureIdRole
Used to retrieve the id of a feature.
Definition: qgsfeaturepickermodelbase.h:54
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
QgsFeaturePickerWidget::allowNullChanged
void allowNullChanged()
Determines if a NULL value should be available in the list.
QgsFeaturePickerModelBase::beginUpdate
void beginUpdate()
Notification that the model is about to be changed because a job was completed.
QgsFeaturePickerWidget::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: qgsfeaturepickerwidget.cpp:111
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsFeaturePickerModelBase::filterExpressionChanged
void filterExpressionChanged()
An additional filter expression to apply, next to the filterValue.