QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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 <QToolButton>
24
25#include "moc_qgsfeaturepickerwidget.cpp"
26
28 : QWidget( parent )
29 , mModel( new QgsFeaturePickerModel( this ) )
30 , mCompleter( new QCompleter( mModel ) )
31{
32 QHBoxLayout *layout = new QHBoxLayout();
33 mComboBox = new QComboBox( this );
34 mComboBox->setEditable( true );
35 layout->addWidget( mComboBox );
36
37 mPreviousButton = new QToolButton( this );
38 mPreviousButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionArrowLeft.svg" ) ) );
39 mPreviousButton->setEnabled( false );
40 mPreviousButton->setVisible( mShowBrowserButtons );
41 layout->addWidget( mPreviousButton );
42
43 mNextButton = new QToolButton( this );
44 mNextButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionArrowRight.svg" ) ) );
45 mNextButton->setEnabled( false );
46 mNextButton->setVisible( mShowBrowserButtons );
47 layout->addWidget( mNextButton );
48 layout->setContentsMargins( 0, 0, 0, 0 );
49
50 setLayout( layout );
51
52 mCompleter->setCaseSensitivity( Qt::CaseInsensitive );
53 mCompleter->setFilterMode( Qt::MatchContains );
54 mComboBox->setCompleter( mCompleter );
55 mCompleter->setWidget( mComboBox );
59 connect( mModel, &QgsFeaturePickerModel::isLoadingChanged, this, &QgsFeaturePickerWidget::onLoadingChanged );
60 connect( mModel, &QgsFeaturePickerModel::filterJobCompleted, this, &QgsFeaturePickerWidget::onFilterUpdateCompleted );
64 connect( mModel, &QgsFeaturePickerModel::extraIdentifierValueIndexChanged, mComboBox, &QComboBox::setCurrentIndex );
66 connect( mCompleter, static_cast<void ( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeaturePickerWidget::onItemSelected );
67 connect( mCompleter, static_cast<void ( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeaturePickerWidget::onActivated );
68 connect( mModel, &QgsFeaturePickerModel::beginUpdate, this, &QgsFeaturePickerWidget::storeLineEditState );
69 connect( mModel, &QgsFeaturePickerModel::endUpdate, this, &QgsFeaturePickerWidget::restoreLineEditState );
71 connect( mModel, &QgsFeaturePickerModel::dataChanged, this, &QgsFeaturePickerWidget::onDataChanged );
72
73 connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFeaturePickerWidget::onCurrentIndexChanged );
74
75 connect( mPreviousButton, &QToolButton::clicked, this, [this]() { browseFeatures( -1 ); } );
76 connect( mNextButton, &QToolButton::clicked, this, [this]() { browseFeatures( 1 ); } );
77
78 mLineEdit = new QgsFilterLineEdit( nullptr, QgsApplication::nullRepresentation() );
79 mLineEdit->setSelectOnFocus( true );
80 mLineEdit->setShowClearButton( allowNull() );
81
82 mComboBox->setEditable( true );
83 mComboBox->setLineEdit( mLineEdit );
84 mComboBox->setModel( mModel );
85
86 connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeaturePickerWidget::onCurrentTextChanged );
87}
88
90{
91 return mModel->sourceLayer();
92}
93
95{
96 mModel->setSourceLayer( sourceLayer );
97}
98
100{
101 mModel->setFeature( featureId );
102}
103
105{
106 return mModel->feature();
107}
108
110{
111 return mModel->displayExpression();
112}
113
114void QgsFeaturePickerWidget::setDisplayExpression( const QString &expression )
115{
116 mModel->setDisplayExpression( expression );
117}
118
119void QgsFeaturePickerWidget::onCurrentTextChanged( const QString &text )
120{
121 mIsCurrentlyEdited = true;
122 mPopupRequested = true;
123 mModel->setFilterValue( text );
124}
125
126void QgsFeaturePickerWidget::onFilterUpdateCompleted()
127{
128 if ( mPopupRequested )
129 mCompleter->complete();
130
131 mPopupRequested = false;
132}
133
134void QgsFeaturePickerWidget::onLoadingChanged()
135{
136 mLineEdit->setShowSpinner( mModel->isLoading() );
137}
138
139void QgsFeaturePickerWidget::onItemSelected( const QModelIndex &index )
140{
141 mComboBox->setCurrentIndex( index.row() );
142}
143
144void QgsFeaturePickerWidget::onCurrentIndexChanged( int i )
145{
146 if ( !mLineEdit->hasStateStored() )
147 mIsCurrentlyEdited = false;
148
149 mPreviousButton->setEnabled( i > 0 );
150 mNextButton->setEnabled( i < mComboBox->model()->rowCount() - 1 );
151
152 if ( i < 0 )
153 return;
154
155 const QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
156 mModel->setFeature( mModel->data( modelIndex, static_cast<int>( QgsFeaturePickerModel::CustomRole::FeatureId ) ).value<QgsFeatureId>() );
157 mLineEdit->setText( mModel->data( modelIndex, static_cast<int>( QgsFeaturePickerModel::CustomRole::Value ) ).toString() );
158 mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
159 QPalette palette = mLineEdit->palette();
160 palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
161 mLineEdit->setPalette( palette );
162}
163
164void QgsFeaturePickerWidget::onActivated( QModelIndex modelIndex )
165{
166 setFeature( mModel->data( modelIndex, static_cast<int>( QgsFeaturePickerModel::CustomRole::FeatureId ) ).value<QgsFeatureId>() );
167 mLineEdit->setText( mModel->data( modelIndex, static_cast<int>( QgsFeaturePickerModel::CustomRole::Value ) ).toString() );
168}
169
170void QgsFeaturePickerWidget::storeLineEditState()
171{
172 if ( mIsCurrentlyEdited )
173 {
174 mLineEdit->storeState();
175 }
176}
177
178void QgsFeaturePickerWidget::restoreLineEditState()
179{
180 if ( mIsCurrentlyEdited )
181 {
182 mLineEdit->restoreState();
183 }
184}
185
187{
188 int index = -1;
189
190 if ( allowNull() )
191 {
192 index = mComboBox->findText( QgsApplication::nullRepresentation() );
193 }
194
195 return index;
196}
197
198void QgsFeaturePickerWidget::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
199{
200 Q_UNUSED( roles )
201 if ( !mIsCurrentlyEdited )
202 {
203 const int currentIndex = mModel->extraIdentifierValueIndex();
204 if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
205 {
206 const QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
207 mLineEdit->setText( mModel->data( modelIndex, static_cast<int>( QgsFeaturePickerModel::CustomRole::Value ) ).toString() );
208 }
209 }
210}
211
212void QgsFeaturePickerWidget::browseFeatures( int direction )
213{
214 const int newIndex = std::min( std::max( 0, mComboBox->currentIndex() + direction ), mComboBox->model()->rowCount() - 1 );
215 mComboBox->setCurrentIndex( newIndex );
216}
217
219{
220 return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
221}
222
224{
225 Q_UNUSED( event )
226 QWidget::focusOutEvent( event );
227 mLineEdit->setText( mModel->data( currentModelIndex(), static_cast<int>( QgsFeaturePickerModel::CustomRole::Value ) ).toString() );
228}
229
231{
232 if ( event->key() == Qt::Key_Escape )
233 {
234 mLineEdit->setText( mModel->data( currentModelIndex(), static_cast<int>( QgsFeaturePickerModel::CustomRole::Value ) ).toString() );
235 }
236 QWidget::keyReleaseEvent( event );
237}
238
240{
241 return mModel->allowNull();
242}
243
245{
246 mModel->setAllowNull( allowNull );
248}
249
251{
252 return mModel->filterExpression();
253}
254
256{
257 mModel->setFilterExpression( filterExpression );
258}
259
261{
262 return mModel->fetchGeometry();
263}
264
266{
267 mModel->setFetchGeometry( fetchGeometry );
268}
269
271{
272 return mModel->fetchLimit();
273}
274
276{
277 mModel->setFetchLimit( fetchLimit );
278}
279
281{
282 return mShowBrowserButtons;
283}
284
286{
287 if ( showBrowserButtons == mShowBrowserButtons )
288 return;
289
290 mShowBrowserButtons = showBrowserButtons;
291 mPreviousButton->setVisible( mShowBrowserButtons );
292 mNextButton->setVisible( mShowBrowserButtons );
294}
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:58
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