43 QgsFeatureFilterWidget::QgsFeatureFilterWidget( QWidget *parent )
49 mFilterColumnsMenu =
new QMenu(
this );
50 mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu );
51 mStoredFilterExpressionMenu =
new QMenu(
this );
52 mActionStoredFilterExpressions->setMenu( mStoredFilterExpressionMenu );
56 mActionShowAllFilter->setIcon( filterIcon );
57 mActionAdvancedFilter->setIcon( filterIcon );
58 mActionSelectedFilter->setIcon( filterIcon );
59 mActionVisibleFilter->setIcon( filterIcon );
60 mActionEditedFilter->setIcon( filterIcon );
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( mActionVisibleFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterVisible );
75 connect( mActionEditedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterEdited );
76 connect( mFilterQuery, &QLineEdit::returnPressed,
this, &QgsFeatureFilterWidget::filterQueryAccepted );
77 connect( mActionApplyFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterQueryAccepted );
78 connect( mFilterQuery, &QLineEdit::textChanged,
this, &QgsFeatureFilterWidget::onFilterQueryTextChanged );
86 mEditorContext = context;
87 mMessageBar = messageBar;
93 mFilterQueryTimer.setSingleShot(
true );
94 connect( &mFilterQueryTimer, &QTimer::timeout,
this, &QgsFeatureFilterWidget::updateCurrentStoredFilterExpression );
97 storedFilterExpressionBoxInit();
98 storeExpressionButtonInit();
101 void QgsFeatureFilterWidget::filterShowAll()
103 mFilterButton->setDefaultAction( mActionShowAllFilter );
104 mFilterButton->setPopupMode( QToolButton::InstantPopup );
105 mFilterQuery->setVisible(
false );
106 mFilterQuery->setText( QString() );
107 if ( mCurrentSearchWidgetWrapper )
109 mCurrentSearchWidgetWrapper->widget()->setVisible(
false );
111 mApplyFilterButton->setVisible(
false );
112 mStoreFilterExpressionButton->setVisible(
false );
116 void QgsFeatureFilterWidget::filterSelected()
118 mFilterButton->setDefaultAction( mActionSelectedFilter );
119 mFilterButton->setPopupMode( QToolButton::InstantPopup );
120 mFilterQuery->setVisible(
false );
121 mApplyFilterButton->setVisible(
false );
122 mStoreFilterExpressionButton->setVisible(
false );
126 void QgsFeatureFilterWidget::filterVisible()
128 if ( !mLayer->isSpatial() )
134 mFilterButton->setDefaultAction( mActionVisibleFilter );
135 mFilterButton->setPopupMode( QToolButton::InstantPopup );
136 mFilterQuery->setVisible(
false );
137 mApplyFilterButton->setVisible(
false );
138 mStoreFilterExpressionButton->setVisible(
false );
142 void QgsFeatureFilterWidget::filterEdited()
144 mFilterButton->setDefaultAction( mActionEditedFilter );
145 mFilterButton->setPopupMode( QToolButton::InstantPopup );
146 mFilterQuery->setVisible(
false );
147 mApplyFilterButton->setVisible(
false );
148 mStoreFilterExpressionButton->setVisible(
false );
153 void QgsFeatureFilterWidget::filterQueryAccepted()
155 if ( ( mFilterQuery->isVisible() && mFilterQuery->text().isEmpty() ) ||
156 ( mCurrentSearchWidgetWrapper && mCurrentSearchWidgetWrapper->widget()->isVisible()
157 && mCurrentSearchWidgetWrapper->expression().isEmpty() ) )
162 filterQueryChanged( mFilterQuery->text() );
165 void QgsFeatureFilterWidget::filterQueryChanged(
const QString &query )
168 if ( mFilterButton->defaultAction() == mActionAdvancedFilter )
172 else if ( mCurrentSearchWidgetWrapper )
174 str = mCurrentSearchWidgetWrapper->expression();
177 setFilterExpression( str );
180 void QgsFeatureFilterWidget::columnBoxInit()
182 const auto constActions = mFilterColumnsMenu->actions();
183 for ( QAction *a : constActions )
185 mFilterColumnsMenu->removeAction( a );
186 mFilterButton->removeAction( a );
190 mFilterButton->addAction( mActionShowAllFilter );
191 mFilterButton->addAction( mActionSelectedFilter );
192 if ( mLayer->isSpatial() )
194 mFilterButton->addAction( mActionVisibleFilter );
196 mFilterButton->addAction( mActionEditedFilter );
197 mFilterButton->addAction( mActionFilterColumnsMenu );
198 mFilterButton->addAction( mActionAdvancedFilter );
199 mFilterButton->addAction( mActionStoredFilterExpressions );
201 const QList<QgsField> fields = mLayer->fields().toList();
203 const auto constFields = fields;
206 int idx = mLayer->fields().lookupField(
field.
name() );
212 QIcon icon = mLayer->fields().iconForField( idx );
213 QString alias = mLayer->attributeDisplayName( idx );
216 QAction *filterAction =
new QAction( icon, alias, mFilterButton );
219 connect( filterAction, &QAction::triggered,
this, [ = ] { filterColumnChanged( filterAction ); } );
220 mFilterColumnsMenu->addAction( filterAction );
225 void QgsFeatureFilterWidget::handleStoreFilterExpression()
227 if ( !mActionHandleStoreFilterExpression->isChecked() )
229 mLayer->storedExpressionManager()->removeStoredExpression( mActionHandleStoreFilterExpression->data().toString() );
233 mLayer->storedExpressionManager()->addStoredExpression( mFilterQuery->text(), mFilterQuery->text() );
236 updateCurrentStoredFilterExpression();
237 storedFilterExpressionBoxInit();
240 void QgsFeatureFilterWidget::storedFilterExpressionBoxInit()
242 const auto constActions = mStoredFilterExpressionMenu->actions();
243 for ( QAction *a : constActions )
245 mStoredFilterExpressionMenu->removeAction( a );
249 const QList< QgsStoredExpression > storedExpressions = mLayer->storedExpressionManager()->storedExpressions();
252 QAction *storedExpressionAction =
new QAction( storedExpression.name, mFilterButton );
253 connect( storedExpressionAction, &QAction::triggered,
this, [ = ]()
257 mStoredFilterExpressionMenu->addAction( storedExpressionAction );
261 void QgsFeatureFilterWidget::storeExpressionButtonInit()
263 if ( mActionHandleStoreFilterExpression->isChecked() )
265 mActionHandleStoreFilterExpression->setToolTip( tr(
"Delete stored expression" ) );
266 mActionHandleStoreFilterExpression->setText( tr(
"Delete Stored Expression" ) );
267 mActionHandleStoreFilterExpression->setIcon(
QgsApplication::getThemeIcon( QStringLiteral(
"mActionHandleStoreFilterExpressionChecked.svg" ) ) );
268 mStoreFilterExpressionButton->removeAction( mActionSaveAsStoredFilterExpression );
269 mStoreFilterExpressionButton->addAction( mActionEditStoredFilterExpression );
273 mActionHandleStoreFilterExpression->setToolTip( tr(
"Save expression with the text as name" ) );
274 mActionHandleStoreFilterExpression->setText( tr(
"Save Expression" ) );
275 mActionHandleStoreFilterExpression->setIcon(
QgsApplication::getThemeIcon( QStringLiteral(
"mActionHandleStoreFilterExpressionUnchecked.svg" ) ) );
276 mStoreFilterExpressionButton->addAction( mActionSaveAsStoredFilterExpression );
277 mStoreFilterExpressionButton->removeAction( mActionEditStoredFilterExpression );
282 void QgsFeatureFilterWidget::filterColumnChanged( QAction *filterAction )
284 mFilterButton->setDefaultAction( filterAction );
285 mFilterButton->setPopupMode( QToolButton::InstantPopup );
288 if ( mCurrentSearchWidgetWrapper )
290 mCurrentSearchWidgetWrapper->widget()->setVisible(
false );
291 delete mCurrentSearchWidgetWrapper;
293 QString fieldName = mFilterButton->defaultAction()->data().toString();
295 int fldIdx = mLayer->fields().lookupField( fieldName );
300 createSearchWidget( setup.
type(), mLayer, fldIdx, setup.
config(), mFilterContainer, mEditorContext );
301 if ( mCurrentSearchWidgetWrapper->applyDirectly() )
304 mApplyFilterButton->setVisible(
false );
305 mStoreFilterExpressionButton->setVisible(
false );
310 mApplyFilterButton->setVisible(
true );
311 mStoreFilterExpressionButton->setVisible(
true );
314 replaceSearchWidget( mFilterQuery, mCurrentSearchWidgetWrapper->widget() );
317 void QgsFeatureFilterWidget::filterExpressionBuilder()
323 dlg.setWindowTitle( tr(
"Expression Based Filter" ) );
328 dlg.setGeomCalculator( myDa );
330 if ( dlg.exec() == QDialog::Accepted )
336 void QgsFeatureFilterWidget::saveAsStoredFilterExpression()
338 QgsDialog *dlg =
new QgsDialog(
this, Qt::WindowFlags(), QDialogButtonBox::Save | QDialogButtonBox::Cancel );
339 dlg->setWindowTitle( tr(
"Save Expression As" ) );
340 QVBoxLayout *layout = dlg->
layout();
341 dlg->resize( std::max( 400, this->width() / 2 ), dlg->height() );
343 QLabel *nameLabel =
new QLabel( tr(
"Name" ), dlg );
344 QLineEdit *nameEdit =
new QLineEdit( dlg );
345 layout->addWidget( nameLabel );
346 layout->addWidget( nameEdit );
347 nameEdit->setFocus();
349 if ( dlg->exec() == QDialog::Accepted )
351 mLayer->storedExpressionManager()->addStoredExpression( nameEdit->text(), mFilterQuery->text() );
353 updateCurrentStoredFilterExpression();
354 storedFilterExpressionBoxInit();
358 void QgsFeatureFilterWidget::editStoredFilterExpression()
360 QgsDialog *dlg =
new QgsDialog(
this, Qt::WindowFlags(), QDialogButtonBox::Save | QDialogButtonBox::Cancel );
361 dlg->setWindowTitle( tr(
"Edit expression" ) );
362 QVBoxLayout *layout = dlg->
layout();
363 dlg->resize( std::max( 400, this->width() / 2 ), dlg->height() );
365 QLabel *nameLabel =
new QLabel( tr(
"Name" ), dlg );
366 QLineEdit *nameEdit =
new QLineEdit( mLayer->storedExpressionManager()->storedExpression( mActionHandleStoreFilterExpression->data().toString() ).name, dlg );
367 QLabel *expressionLabel =
new QLabel( tr(
"Expression" ), dlg );
369 expressionEdit->
setExpression( mLayer->storedExpressionManager()->storedExpression( mActionHandleStoreFilterExpression->data().toString() ).expression );
371 layout->addWidget( nameLabel );
372 layout->addWidget( nameEdit );
373 layout->addWidget( expressionLabel );
374 layout->addWidget( expressionEdit );
375 nameEdit->setFocus();
377 if ( dlg->exec() == QDialog::Accepted )
380 mLayer->storedExpressionManager()->updateStoredExpression( mActionHandleStoreFilterExpression->data().toString(), nameEdit->text(), expressionEdit->
expression(), QgsStoredExpression::Category::FilterExpression );
383 mFilterQuery->setValue( expressionEdit->
expression() );
385 storedFilterExpressionBoxInit();
389 void QgsFeatureFilterWidget::updateCurrentStoredFilterExpression()
391 QgsStoredExpression currentStoredExpression = mLayer->storedExpressionManager()->findStoredExpressionByExpression( mFilterQuery->value() );
394 mActionHandleStoreFilterExpression->setChecked( !currentStoredExpression.
id.isNull() );
396 mActionHandleStoreFilterExpression->setData( currentStoredExpression.
id );
397 mActionEditStoredFilterExpression->setData( currentStoredExpression.
id );
400 storeExpressionButtonInit();
403 void QgsFeatureFilterWidget::setFilterExpression(
const QString &filterString,
QgsAttributeForm::FilterType type,
bool alwaysShowFilter )
406 if ( !mFilterQuery->text().isEmpty() && !filterString.isEmpty() )
411 filter = filterString;
415 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterQuery->text(), filterString );
419 filter = QStringLiteral(
"(%1) OR (%2)" ).arg( mFilterQuery->text(), filterString );
423 else if ( !filterString.isEmpty() )
425 filter = filterString;
433 mFilterQuery->setText( filter );
435 if ( alwaysShowFilter || !mCurrentSearchWidgetWrapper || !mCurrentSearchWidgetWrapper->applyDirectly() )
438 mFilterButton->setDefaultAction( mActionAdvancedFilter );
439 mFilterButton->setPopupMode( QToolButton::MenuButtonPopup );
440 mFilterQuery->setVisible(
true );
441 mApplyFilterButton->setVisible(
true );
442 mStoreFilterExpressionButton->setVisible(
true );
443 if ( mCurrentSearchWidgetWrapper )
446 replaceSearchWidget( mCurrentSearchWidgetWrapper->widget(), mFilterQuery );
452 if ( filterExpression.hasParserError() )
454 mMessageBar->pushMessage( tr(
"Parsing error" ), filterExpression.parserErrorString(),
Qgis::Warning );
460 if ( !filterExpression.prepare( &context ) )
462 mMessageBar->pushMessage( tr(
"Evaluation error" ), filterExpression.evalErrorString(),
Qgis::Warning );
465 mMainView->filterFeatures( filterExpression, context );
470 void QgsFeatureFilterWidget::replaceSearchWidget( QWidget *oldw, QWidget *neww )
472 mFilterLayout->removeWidget( oldw );
473 oldw->setVisible(
false );
474 mFilterLayout->addWidget( neww, 0, 0 );
475 neww->setVisible(
true );
479 void QgsFeatureFilterWidget::onFilterQueryTextChanged(
const QString &value )
482 mFilterQueryTimer.start( 300 );
static QIcon getThemeIcon(const QString &name)
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.
@ 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.
QString id
generated uuid used for identification