43QgsFeatureFilterWidget::QgsFeatureFilterWidget( QWidget *parent )
49 mFilterColumnsMenu =
new QMenu(
this );
50 mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu );
51 mStoredFilterExpressionMenu =
new QMenu(
this );
52 mActionStoredFilterExpressions->setMenu( mStoredFilterExpressionMenu );
64 mStoreFilterExpressionButton->setDefaultAction( mActionHandleStoreFilterExpression );
65 connect( mActionSaveAsStoredFilterExpression, &QAction::triggered,
this, &QgsFeatureFilterWidget::saveAsStoredFilterExpression );
66 connect( mActionEditStoredFilterExpression, &QAction::triggered,
this, &QgsFeatureFilterWidget::editStoredFilterExpression );
67 connect( mActionHandleStoreFilterExpression, &QAction::triggered,
this, &QgsFeatureFilterWidget::handleStoreFilterExpression );
68 mApplyFilterButton->setDefaultAction( mActionApplyFilter );
71 connect( mActionAdvancedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterExpressionBuilder );
72 connect( mActionShowAllFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterShowAll );
73 connect( mActionSelectedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterSelected );
74 connect( mActionInvalidFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterInvalid );
75 connect( mActionVisibleFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterVisible );
76 connect( mActionEditedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterEdited );
77 connect( mFilterQuery, &QLineEdit::returnPressed,
this, &QgsFeatureFilterWidget::filterQueryAccepted );
78 connect( mActionApplyFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterQueryAccepted );
79 connect( mFilterQuery, &QLineEdit::textChanged,
this, &QgsFeatureFilterWidget::onFilterQueryTextChanged );
87 mEditorContext = context;
88 mMessageBar = messageBar;
94 mFilterQueryTimer.setSingleShot(
true );
95 connect( &mFilterQueryTimer, &QTimer::timeout,
this, &QgsFeatureFilterWidget::updateCurrentStoredFilterExpression );
98 storedFilterExpressionBoxInit();
99 storeExpressionButtonInit();
102void QgsFeatureFilterWidget::filterShowAll()
104 mFilterButton->setDefaultAction( mActionShowAllFilter );
105 mFilterButton->setPopupMode( QToolButton::InstantPopup );
106 mFilterQuery->setVisible(
false );
107 mFilterQuery->setText( QString() );
108 if ( mCurrentSearchWidgetWrapper )
110 mCurrentSearchWidgetWrapper->widget()->setVisible(
false );
112 mApplyFilterButton->setVisible(
false );
113 mStoreFilterExpressionButton->setVisible(
false );
117void QgsFeatureFilterWidget::filterSelected()
119 mFilterButton->setDefaultAction( mActionSelectedFilter );
120 mFilterButton->setPopupMode( QToolButton::InstantPopup );
121 mFilterQuery->setVisible(
false );
122 mApplyFilterButton->setVisible(
false );
123 mStoreFilterExpressionButton->setVisible(
false );
127void QgsFeatureFilterWidget::filterVisible()
129 if ( !mLayer->isSpatial() )
135 mFilterButton->setDefaultAction( mActionVisibleFilter );
136 mFilterButton->setPopupMode( QToolButton::InstantPopup );
137 mFilterQuery->setVisible(
false );
138 mApplyFilterButton->setVisible(
false );
139 mStoreFilterExpressionButton->setVisible(
false );
143void QgsFeatureFilterWidget::filterInvalid()
145 mFilterButton->setDefaultAction( mActionInvalidFilter );
146 mFilterButton->setPopupMode( QToolButton::InstantPopup );
147 mFilterQuery->setVisible(
false );
148 mApplyFilterButton->setVisible(
false );
149 mStoreFilterExpressionButton->setVisible(
false );
151 mMainView->filterFeatures( QStringLiteral(
"is_feature_valid() = false" ), context );
155void QgsFeatureFilterWidget::filterEdited()
157 mFilterButton->setDefaultAction( mActionEditedFilter );
158 mFilterButton->setPopupMode( QToolButton::InstantPopup );
159 mFilterQuery->setVisible(
false );
160 mApplyFilterButton->setVisible(
false );
161 mStoreFilterExpressionButton->setVisible(
false );
166void QgsFeatureFilterWidget::filterQueryAccepted()
168 if ( ( mFilterQuery->isVisible() && mFilterQuery->text().isEmpty() ) ||
169 ( mCurrentSearchWidgetWrapper && mCurrentSearchWidgetWrapper->widget()->isVisible()
170 && mCurrentSearchWidgetWrapper->expression().isEmpty() ) )
175 filterQueryChanged( mFilterQuery->text() );
178void QgsFeatureFilterWidget::filterQueryChanged(
const QString &query )
181 if ( mFilterButton->defaultAction() == mActionAdvancedFilter )
185 else if ( mCurrentSearchWidgetWrapper )
187 str = mCurrentSearchWidgetWrapper->expression();
190 setFilterExpression(
str );
193void QgsFeatureFilterWidget::columnBoxInit()
195 const auto constActions = mFilterColumnsMenu->actions();
196 for ( QAction *a : constActions )
198 mFilterColumnsMenu->removeAction( a );
199 mFilterButton->removeAction( a );
203 mFilterButton->addAction( mActionShowAllFilter );
204 mFilterButton->addAction( mActionSelectedFilter );
205 if ( mLayer->isSpatial() )
207 mFilterButton->addAction( mActionVisibleFilter );
209 mFilterButton->addAction( mActionInvalidFilter );
210 mFilterButton->addAction( mActionEditedFilter );
211 mFilterButton->addAction( mActionFilterColumnsMenu );
212 mFilterButton->addAction( mActionAdvancedFilter );
213 mFilterButton->addAction( mActionStoredFilterExpressions );
215 const QList<QgsField> fields = mLayer->fields().toList();
217 const auto constFields = fields;
218 for (
const QgsField &field : constFields )
220 const int idx = mLayer->fields().lookupField( field.name() );
226 const QIcon icon = mLayer->fields().iconForField( idx );
227 const QString alias = mLayer->attributeDisplayName( idx );
230 QAction *filterAction =
new QAction( icon, alias, mFilterButton );
231 filterAction->setData( field.name() );
233 connect( filterAction, &QAction::triggered,
this, [ = ] { filterColumnChanged( filterAction ); } );
234 mFilterColumnsMenu->addAction( filterAction );
239void QgsFeatureFilterWidget::handleStoreFilterExpression()
241 if ( !mActionHandleStoreFilterExpression->isChecked() )
243 mLayer->storedExpressionManager()->removeStoredExpression( mActionHandleStoreFilterExpression->data().toString() );
247 mLayer->storedExpressionManager()->addStoredExpression( mFilterQuery->text(), mFilterQuery->text() );
250 updateCurrentStoredFilterExpression();
251 storedFilterExpressionBoxInit();
254void QgsFeatureFilterWidget::storedFilterExpressionBoxInit()
256 const auto constActions = mStoredFilterExpressionMenu->actions();
257 for ( QAction *a : constActions )
259 mStoredFilterExpressionMenu->removeAction( a );
263 const QList< QgsStoredExpression > storedExpressions = mLayer->storedExpressionManager()->storedExpressions();
266 QAction *storedExpressionAction =
new QAction( storedExpression.name, mFilterButton );
267 connect( storedExpressionAction, &QAction::triggered,
this, [ = ]()
271 mStoredFilterExpressionMenu->addAction( storedExpressionAction );
275void QgsFeatureFilterWidget::storeExpressionButtonInit()
277 if ( mActionHandleStoreFilterExpression->isChecked() )
279 mActionHandleStoreFilterExpression->setToolTip( tr(
"Delete stored expression" ) );
280 mActionHandleStoreFilterExpression->setText( tr(
"Delete Stored Expression" ) );
281 mActionHandleStoreFilterExpression->setIcon(
QgsApplication::getThemeIcon( QStringLiteral(
"mActionHandleStoreFilterExpressionChecked.svg" ) ) );
282 mStoreFilterExpressionButton->removeAction( mActionSaveAsStoredFilterExpression );
283 mStoreFilterExpressionButton->addAction( mActionEditStoredFilterExpression );
287 mActionHandleStoreFilterExpression->setToolTip( tr(
"Save expression with the text as name" ) );
288 mActionHandleStoreFilterExpression->setText( tr(
"Save Expression" ) );
289 mActionHandleStoreFilterExpression->setIcon(
QgsApplication::getThemeIcon( QStringLiteral(
"mActionHandleStoreFilterExpressionUnchecked.svg" ) ) );
290 mStoreFilterExpressionButton->addAction( mActionSaveAsStoredFilterExpression );
291 mStoreFilterExpressionButton->removeAction( mActionEditStoredFilterExpression );
296void QgsFeatureFilterWidget::filterColumnChanged( QAction *filterAction )
298 mFilterButton->setDefaultAction( filterAction );
299 mFilterButton->setPopupMode( QToolButton::InstantPopup );
302 if ( mCurrentSearchWidgetWrapper )
304 mCurrentSearchWidgetWrapper->widget()->setVisible(
false );
305 delete mCurrentSearchWidgetWrapper;
307 const QString fieldName = mFilterButton->defaultAction()->data().toString();
309 const int fldIdx = mLayer->fields().lookupField( fieldName );
314 createSearchWidget( setup.
type(), mLayer, fldIdx, setup.
config(), mFilterContainer, mEditorContext );
315 if ( mCurrentSearchWidgetWrapper->applyDirectly() )
318 mApplyFilterButton->setVisible(
false );
319 mStoreFilterExpressionButton->setVisible(
false );
324 mApplyFilterButton->setVisible(
true );
325 mStoreFilterExpressionButton->setVisible(
true );
328 replaceSearchWidget( mFilterQuery, mCurrentSearchWidgetWrapper->widget() );
331void QgsFeatureFilterWidget::filterExpressionBuilder()
337 dlg.setWindowTitle( tr(
"Expression Based Filter" ) );
342 dlg.setGeomCalculator( myDa );
344 if ( dlg.exec() == QDialog::Accepted )
350void QgsFeatureFilterWidget::saveAsStoredFilterExpression()
352 QgsDialog *dlg =
new QgsDialog(
this, Qt::WindowFlags(), QDialogButtonBox::Save | QDialogButtonBox::Cancel );
353 dlg->setWindowTitle( tr(
"Save Expression As" ) );
354 QVBoxLayout *layout = dlg->
layout();
355 dlg->resize( std::max( 400, this->width() / 2 ), dlg->height() );
357 QLabel *nameLabel =
new QLabel( tr(
"Name" ), dlg );
358 QLineEdit *nameEdit =
new QLineEdit( dlg );
359 layout->addWidget( nameLabel );
360 layout->addWidget( nameEdit );
361 nameEdit->setFocus();
363 if ( dlg->exec() == QDialog::Accepted )
365 mLayer->storedExpressionManager()->addStoredExpression( nameEdit->text(), mFilterQuery->text() );
367 updateCurrentStoredFilterExpression();
368 storedFilterExpressionBoxInit();
372void QgsFeatureFilterWidget::editStoredFilterExpression()
374 QgsDialog *dlg =
new QgsDialog(
this, Qt::WindowFlags(), QDialogButtonBox::Save | QDialogButtonBox::Cancel );
375 dlg->setWindowTitle( tr(
"Edit expression" ) );
376 QVBoxLayout *layout = dlg->
layout();
377 dlg->resize( std::max( 400, this->width() / 2 ), dlg->height() );
379 QLabel *nameLabel =
new QLabel( tr(
"Name" ), dlg );
380 QLineEdit *nameEdit =
new QLineEdit( mLayer->storedExpressionManager()->storedExpression( mActionHandleStoreFilterExpression->data().toString() ).name, dlg );
381 QLabel *expressionLabel =
new QLabel( tr(
"Expression" ), dlg );
383 expressionEdit->
setExpression( mLayer->storedExpressionManager()->storedExpression( mActionHandleStoreFilterExpression->data().toString() ).expression );
385 layout->addWidget( nameLabel );
386 layout->addWidget( nameEdit );
387 layout->addWidget( expressionLabel );
388 layout->addWidget( expressionEdit );
389 nameEdit->setFocus();
391 if ( dlg->exec() == QDialog::Accepted )
397 mFilterQuery->setValue( expressionEdit->
expression() );
399 storedFilterExpressionBoxInit();
403void QgsFeatureFilterWidget::updateCurrentStoredFilterExpression()
405 const QgsStoredExpression currentStoredExpression = mLayer->storedExpressionManager()->findStoredExpressionByExpression( mFilterQuery->value() );
408 mActionHandleStoreFilterExpression->setChecked( !currentStoredExpression.
id.isNull() );
410 mActionHandleStoreFilterExpression->setData( currentStoredExpression.
id );
411 mActionEditStoredFilterExpression->setData( currentStoredExpression.
id );
414 storeExpressionButtonInit();
417void QgsFeatureFilterWidget::setFilterExpression(
const QString &filterString,
QgsAttributeForm::FilterType type,
bool alwaysShowFilter )
420 if ( !mFilterQuery->text().isEmpty() && !filterString.isEmpty() )
425 filter = filterString;
429 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterQuery->text(), filterString );
433 filter = QStringLiteral(
"(%1) OR (%2)" ).arg( mFilterQuery->text(), filterString );
437 else if ( !filterString.isEmpty() )
439 filter = filterString;
447 mFilterQuery->setText( filter );
449 if ( alwaysShowFilter || !mCurrentSearchWidgetWrapper || !mCurrentSearchWidgetWrapper->applyDirectly() )
452 mFilterButton->setDefaultAction( mActionAdvancedFilter );
453 mFilterButton->setPopupMode( QToolButton::MenuButtonPopup );
454 mFilterQuery->setVisible(
true );
455 mApplyFilterButton->setVisible(
true );
456 mStoreFilterExpressionButton->setVisible(
true );
457 if ( mCurrentSearchWidgetWrapper )
460 replaceSearchWidget( mCurrentSearchWidgetWrapper->widget(), mFilterQuery );
466 if ( filterExpression.hasParserError() )
474 if ( !filterExpression.prepare( &context ) )
479 mMainView->filterFeatures( filterExpression, context );
483void QgsFeatureFilterWidget::replaceSearchWidget( QWidget *oldw, QWidget *neww )
485 mFilterLayout->removeWidget( oldw );
486 oldw->setVisible(
false );
487 mFilterLayout->addWidget( neww, 0, 0 );
488 neww->setVisible(
true );
492void QgsFeatureFilterWidget::onFilterQueryTextChanged(
const QString &value )
495 mFilterQueryTimer.start( 300 );
@ Warning
Warning message.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
This class contains context information for attribute editor widgets.
@ ShowFilteredList
Show only features whose ids are on the filter list. {.
@ ShowVisible
Show only visible features (depends on the map canvas)
@ ShowSelected
Show only selected features.
@ ShowInvalid
Show only features not respecting constraints (since QGIS 3.30)
@ ShowEdited
Show only features which have unsaved changes.
@ ShowAll
Show all features.
A generic dialog with layout and button box.
QVBoxLayout * layout()
Returns the central layout. Widgets added to it must have this dialog as parent.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
This widget is used to show the attributes of a set of features of a QgsVectorLayer.
A generic dialog for building expression strings.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
QString expression() const
Returns the current expression shown in the widget.
void setExpression(const QString &expression)
Sets the current expression to show in the widget.
Class for parsing and evaluation of expressions (formerly called "search strings").
Encapsulate a field in an attribute table or data source.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
A bar for displaying non-blocking messages to the user.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsCoordinateTransformContext transformContext
Represents a vector layer which manages a vector based data sets.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
Stored expression containing name, content (expression text) and a category tag.
@ FilterExpression
Expressions to filter features.
QString id
generated uuid used for identification