QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 }
86 
88 {
89  return mModel->sourceLayer();
90 }
91 
93 {
94  mModel->setSourceLayer( sourceLayer );
95 }
96 
98 {
99  mModel->setFeature( featureId );
100 }
101 
103 {
104  return mModel->feature();
105 }
106 
108 {
109  return mModel->displayExpression();
110 }
111 
112 void QgsFeaturePickerWidget::setDisplayExpression( const QString &expression )
113 {
114  mModel->setDisplayExpression( expression );
115 }
116 
117 void QgsFeaturePickerWidget::onCurrentTextChanged( const QString &text )
118 {
119  mIsCurrentlyEdited = true;
120  mPopupRequested = true;
121  mModel->setFilterValue( text );
122 }
123 
124 void QgsFeaturePickerWidget::onFilterUpdateCompleted()
125 {
126  if ( mPopupRequested )
127  mCompleter->complete();
128 
129  mPopupRequested = false;
130 }
131 
132 void QgsFeaturePickerWidget::onLoadingChanged()
133 {
134  mLineEdit->setShowSpinner( mModel->isLoading() );
135 }
136 
137 void QgsFeaturePickerWidget::onItemSelected( const QModelIndex &index )
138 {
139  mComboBox->setCurrentIndex( index.row() );
140 }
141 
142 void QgsFeaturePickerWidget::onCurrentIndexChanged( int i )
143 {
144  if ( !mLineEdit->hasStateStored() )
145  mIsCurrentlyEdited = false;
146 
147  mPreviousButton->setEnabled( i > 0 );
148  mNextButton->setEnabled( i < mComboBox->model()->rowCount() - 1 );
149 
150  if ( i < 0 )
151  return;
152 
153  QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
154  mModel->setFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
155  mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
156  mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
157  QPalette palette = mLineEdit->palette();
158  palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
159  mLineEdit->setPalette( palette );
160 }
161 
162 void QgsFeaturePickerWidget::onActivated( QModelIndex modelIndex )
163 {
164  setFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
165  mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
166 }
167 
168 void QgsFeaturePickerWidget::storeLineEditState()
169 {
170  if ( mIsCurrentlyEdited )
171  {
172  mLineEdit->storeState( );
173  }
174 }
175 
176 void QgsFeaturePickerWidget::restoreLineEditState()
177 {
178  if ( mIsCurrentlyEdited )
179  {
180  mLineEdit->restoreState( );
181  }
182 }
183 
185 {
186  int index = -1;
187 
188  if ( allowNull() )
189  {
190  index = mComboBox->findText( QgsApplication::nullRepresentation( ) );
191  }
192 
193  return index;
194 }
195 
196 void QgsFeaturePickerWidget::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
197 {
198  Q_UNUSED( roles )
199  if ( !mIsCurrentlyEdited )
200  {
201  const int currentIndex = mModel->extraIdentifierValueIndex();
202  if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
203  {
204  QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
205  mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
206  }
207  }
208 }
209 
210 void QgsFeaturePickerWidget::browseFeatures( int direction )
211 {
212  int newIndex = std::min( std::max( 0, mComboBox->currentIndex() + direction ), mComboBox->model()->rowCount() - 1 );
213  mComboBox->setCurrentIndex( newIndex );
214 }
215 
217 {
218  return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
219 }
220 
221 void QgsFeaturePickerWidget::focusOutEvent( QFocusEvent *event )
222 {
223  Q_UNUSED( event )
224  QWidget::focusOutEvent( event );
225  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeaturePickerModel::ValueRole ).toString() );
226 }
227 
229 {
230  if ( event->key() == Qt::Key_Escape )
231  {
232  mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeaturePickerModel::ValueRole ).toString() );
233  }
234  QWidget::keyReleaseEvent( event );
235 }
236 
238 {
239  return mModel->allowNull();
240 }
241 
243 {
244  mModel->setAllowNull( allowNull );
246 }
247 
249 {
250  return mModel->filterExpression();
251 }
252 
253 void QgsFeaturePickerWidget::setFilterExpression( const QString &filterExpression )
254 {
256 }
257 
259 {
260  return mModel->fetchGeometry();
261 }
262 
264 {
265  mModel->setFetchGeometry( fetchGeometry );
266 }
267 
269 {
270  return mModel->fetchLimit();
271 }
272 
274 {
275  mModel->setFetchLimit( fetchLimit );
276 }
277 
279 {
280  return mShowBrowserButtons;
281 }
282 
283 void QgsFeaturePickerWidget::setShowBrowserButtons( bool showBrowserButtons )
284 {
285  if ( showBrowserButtons == mShowBrowserButtons )
286  return;
287 
288  mShowBrowserButtons = showBrowserButtons;
289  mPreviousButton->setVisible( mShowBrowserButtons );
290  mNextButton->setVisible( mShowBrowserButtons );
292 }
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:54
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:605
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:50
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:216
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:184
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:97
qgsfilterlineedit.h
QgsFilterLineEdit
Definition: qgsfilterlineedit.h:39
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:65
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
Definition: qgsfeaturepickermodel.h:31
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:52
QgsFeaturePickerWidget::setLayer
void setLayer(QgsVectorLayer *layer)
The layer from which features should be listed.
Definition: qgsfeaturepickerwidget.cpp:92
QgsFeaturePickerModelBase::allowNull
bool allowNull
Definition: qgsfeaturepickermodelbase.h:51
QgsFilterLineEdit::hasStateStored
bool hasStateStored() const
Returns if a state is already saved.
Definition: qgsfilterlineedit.h:229
QgsFeaturePickerModelBase::sourceLayer
QgsVectorLayer sourceLayer
Definition: qgsfeaturepickermodelbase.h:47
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:1802
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:48
QgsFeaturePickerWidget::setAllowNull
void setAllowNull(bool allowNull)
Determines if a NULL value should be available in the list.
Definition: qgsfeaturepickerwidget.cpp:242
QgsFeaturePickerWidget::focusOutEvent
void focusOutEvent(QFocusEvent *event) override
Definition: qgsfeaturepickerwidget.cpp:221
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:545
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:273
QgsFeaturePickerWidget::feature
QgsFeature feature() const
Returns the current feature.
Definition: qgsfeaturepickerwidget.cpp:102
QgsFeaturePickerWidget::setShowBrowserButtons
void setShowBrowserButtons(bool showBrowserButtons)
Defines if the browsing buttons are shown.
Definition: qgsfeaturepickerwidget.cpp:283
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:53
QgsFeaturePickerWidget::setFetchGeometry
void setFetchGeometry(bool fetchGeometry)
Defines if the geometry will be fetched.
Definition: qgsfeaturepickerwidget.cpp:263
qgsfeaturepickermodel.h
QgsVectorLayer
Definition: qgsvectorlayer.h:385
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
Definition: qgsfeature.h:55
QgsFeaturePickerWidget::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: qgsfeaturepickerwidget.cpp:228
QgsFeaturePickerWidget::setFilterExpression
void setFilterExpression(const QString &filterExpression)
An additional expression to further restrict the available features.
Definition: qgsfeaturepickerwidget.cpp:253
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:575
QgsFeaturePickerModelBase::setFetchGeometry
void setFetchGeometry(bool fetchGeometry)
Defines if the geometry will be fetched.
Definition: qgsfeaturepickermodelbase.cpp:561
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:67
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:112
QgsFeatureId
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
QgsFeaturePickerModelBase::filterExpressionChanged
void filterExpressionChanged()
An additional filter expression to apply, next to the filterValue.