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