43 QgsFeatureFilterWidget::QgsFeatureFilterWidget( QWidget *parent )
49 mFilterColumnsMenu =
new QMenu(
this );
50 mActionFilterColumnsMenu->setMenu( mFilterColumnsMenu );
51 mStoredFilterExpressionMenu =
new QMenu(
this );
52 mActionStoredFilterExpressions->setMenu( mStoredFilterExpressionMenu );
63 mStoreFilterExpressionButton->setDefaultAction( mActionHandleStoreFilterExpression );
64 connect( mActionSaveAsStoredFilterExpression, &QAction::triggered,
this, &QgsFeatureFilterWidget::saveAsStoredFilterExpression );
65 connect( mActionEditStoredFilterExpression, &QAction::triggered,
this, &QgsFeatureFilterWidget::editStoredFilterExpression );
66 connect( mActionHandleStoreFilterExpression, &QAction::triggered,
this, &QgsFeatureFilterWidget::handleStoreFilterExpression );
67 mApplyFilterButton->setDefaultAction( mActionApplyFilter );
70 connect( mActionAdvancedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterExpressionBuilder );
71 connect( mActionShowAllFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterShowAll );
72 connect( mActionSelectedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterSelected );
73 connect( mActionVisibleFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterVisible );
74 connect( mActionEditedFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterEdited );
75 connect( mFilterQuery, &QLineEdit::returnPressed,
this, &QgsFeatureFilterWidget::filterQueryAccepted );
76 connect( mActionApplyFilter, &QAction::triggered,
this, &QgsFeatureFilterWidget::filterQueryAccepted );
77 connect( mFilterQuery, &QLineEdit::textChanged,
this, &QgsFeatureFilterWidget::onFilterQueryTextChanged );
85 mEditorContext = context;
86 mMessageBar = messageBar;
92 mFilterQueryTimer.setSingleShot(
true );
93 connect( &mFilterQueryTimer, &QTimer::timeout,
this, &QgsFeatureFilterWidget::updateCurrentStoredFilterExpression );
96 storedFilterExpressionBoxInit();
97 storeExpressionButtonInit();
100 void QgsFeatureFilterWidget::filterShowAll()
102 mFilterButton->setDefaultAction( mActionShowAllFilter );
103 mFilterButton->setPopupMode( QToolButton::InstantPopup );
104 mFilterQuery->setVisible(
false );
105 mFilterQuery->setText( QString() );
106 if ( mCurrentSearchWidgetWrapper )
108 mCurrentSearchWidgetWrapper->widget()->setVisible(
false );
110 mApplyFilterButton->setVisible(
false );
111 mStoreFilterExpressionButton->setVisible(
false );
115 void QgsFeatureFilterWidget::filterSelected()
117 mFilterButton->setDefaultAction( mActionSelectedFilter );
118 mFilterButton->setPopupMode( QToolButton::InstantPopup );
119 mFilterQuery->setVisible(
false );
120 mApplyFilterButton->setVisible(
false );
121 mStoreFilterExpressionButton->setVisible(
false );
125 void QgsFeatureFilterWidget::filterVisible()
127 if ( !mLayer->isSpatial() )
133 mFilterButton->setDefaultAction( mActionVisibleFilter );
134 mFilterButton->setPopupMode( QToolButton::InstantPopup );
135 mFilterQuery->setVisible(
false );
136 mApplyFilterButton->setVisible(
false );
137 mStoreFilterExpressionButton->setVisible(
false );
141 void QgsFeatureFilterWidget::filterEdited()
143 mFilterButton->setDefaultAction( mActionEditedFilter );
144 mFilterButton->setPopupMode( QToolButton::InstantPopup );
145 mFilterQuery->setVisible(
false );
146 mApplyFilterButton->setVisible(
false );
147 mStoreFilterExpressionButton->setVisible(
false );
152 void QgsFeatureFilterWidget::filterQueryAccepted()
154 if ( ( mFilterQuery->isVisible() && mFilterQuery->text().isEmpty() ) ||
155 ( mCurrentSearchWidgetWrapper && mCurrentSearchWidgetWrapper->widget()->isVisible()
156 && mCurrentSearchWidgetWrapper->expression().isEmpty() ) )
161 filterQueryChanged( mFilterQuery->text() );
164 void QgsFeatureFilterWidget::filterQueryChanged(
const QString &query )
167 if ( mFilterButton->defaultAction() == mActionAdvancedFilter )
171 else if ( mCurrentSearchWidgetWrapper )
173 str = mCurrentSearchWidgetWrapper->expression();
176 setFilterExpression(
str );
179 void QgsFeatureFilterWidget::columnBoxInit()
181 const auto constActions = mFilterColumnsMenu->actions();
182 for ( QAction *a : constActions )
184 mFilterColumnsMenu->removeAction( a );
185 mFilterButton->removeAction( a );
189 mFilterButton->addAction( mActionShowAllFilter );
190 mFilterButton->addAction( mActionSelectedFilter );
191 if ( mLayer->isSpatial() )
193 mFilterButton->addAction( mActionVisibleFilter );
195 mFilterButton->addAction( mActionEditedFilter );
196 mFilterButton->addAction( mActionFilterColumnsMenu );
197 mFilterButton->addAction( mActionAdvancedFilter );
198 mFilterButton->addAction( mActionStoredFilterExpressions );
200 const QList<QgsField> fields = mLayer->fields().toList();
202 const auto constFields = fields;
205 const int idx = mLayer->fields().lookupField(
field.
name() );
211 const QIcon icon = mLayer->fields().iconForField( idx );
212 const QString alias = mLayer->attributeDisplayName( idx );
215 QAction *filterAction =
new QAction( icon, alias, mFilterButton );
218 connect( filterAction, &QAction::triggered,
this, [ = ] { filterColumnChanged( filterAction ); } );
219 mFilterColumnsMenu->addAction( filterAction );
224 void QgsFeatureFilterWidget::handleStoreFilterExpression()
226 if ( !mActionHandleStoreFilterExpression->isChecked() )
228 mLayer->storedExpressionManager()->removeStoredExpression( mActionHandleStoreFilterExpression->data().toString() );
232 mLayer->storedExpressionManager()->addStoredExpression( mFilterQuery->text(), mFilterQuery->text() );
235 updateCurrentStoredFilterExpression();
236 storedFilterExpressionBoxInit();
239 void QgsFeatureFilterWidget::storedFilterExpressionBoxInit()
241 const auto constActions = mStoredFilterExpressionMenu->actions();
242 for ( QAction *a : constActions )
244 mStoredFilterExpressionMenu->removeAction( a );
248 const QList< QgsStoredExpression > storedExpressions = mLayer->storedExpressionManager()->storedExpressions();
251 QAction *storedExpressionAction =
new QAction( storedExpression.name, mFilterButton );
252 connect( storedExpressionAction, &QAction::triggered,
this, [ = ]()
256 mStoredFilterExpressionMenu->addAction( storedExpressionAction );
260 void QgsFeatureFilterWidget::storeExpressionButtonInit()
262 if ( mActionHandleStoreFilterExpression->isChecked() )
264 mActionHandleStoreFilterExpression->setToolTip( tr(
"Delete stored expression" ) );
265 mActionHandleStoreFilterExpression->setText( tr(
"Delete Stored Expression" ) );
266 mActionHandleStoreFilterExpression->setIcon(
QgsApplication::getThemeIcon( QStringLiteral(
"mActionHandleStoreFilterExpressionChecked.svg" ) ) );
267 mStoreFilterExpressionButton->removeAction( mActionSaveAsStoredFilterExpression );
268 mStoreFilterExpressionButton->addAction( mActionEditStoredFilterExpression );
272 mActionHandleStoreFilterExpression->setToolTip( tr(
"Save expression with the text as name" ) );
273 mActionHandleStoreFilterExpression->setText( tr(
"Save Expression" ) );
274 mActionHandleStoreFilterExpression->setIcon(
QgsApplication::getThemeIcon( QStringLiteral(
"mActionHandleStoreFilterExpressionUnchecked.svg" ) ) );
275 mStoreFilterExpressionButton->addAction( mActionSaveAsStoredFilterExpression );
276 mStoreFilterExpressionButton->removeAction( mActionEditStoredFilterExpression );
281 void QgsFeatureFilterWidget::filterColumnChanged( QAction *filterAction )
283 mFilterButton->setDefaultAction( filterAction );
284 mFilterButton->setPopupMode( QToolButton::InstantPopup );
287 if ( mCurrentSearchWidgetWrapper )
289 mCurrentSearchWidgetWrapper->widget()->setVisible(
false );
290 delete mCurrentSearchWidgetWrapper;
292 const QString fieldName = mFilterButton->defaultAction()->data().toString();
294 const int fldIdx = mLayer->fields().lookupField( fieldName );
299 createSearchWidget( setup.
type(), mLayer, fldIdx, setup.
config(), mFilterContainer, mEditorContext );
300 if ( mCurrentSearchWidgetWrapper->applyDirectly() )
303 mApplyFilterButton->setVisible(
false );
304 mStoreFilterExpressionButton->setVisible(
false );
309 mApplyFilterButton->setVisible(
true );
310 mStoreFilterExpressionButton->setVisible(
true );
313 replaceSearchWidget( mFilterQuery, mCurrentSearchWidgetWrapper->widget() );
316 void QgsFeatureFilterWidget::filterExpressionBuilder()
322 dlg.setWindowTitle( tr(
"Expression Based Filter" ) );
327 dlg.setGeomCalculator( myDa );
329 if ( dlg.exec() == QDialog::Accepted )
335 void QgsFeatureFilterWidget::saveAsStoredFilterExpression()
337 QgsDialog *dlg =
new QgsDialog(
this, Qt::WindowFlags(), QDialogButtonBox::Save | QDialogButtonBox::Cancel );
338 dlg->setWindowTitle( tr(
"Save Expression As" ) );
339 QVBoxLayout *layout = dlg->
layout();
340 dlg->resize( std::max( 400, this->width() / 2 ), dlg->height() );
342 QLabel *nameLabel =
new QLabel( tr(
"Name" ), dlg );
343 QLineEdit *nameEdit =
new QLineEdit( dlg );
344 layout->addWidget( nameLabel );
345 layout->addWidget( nameEdit );
346 nameEdit->setFocus();
348 if ( dlg->exec() == QDialog::Accepted )
350 mLayer->storedExpressionManager()->addStoredExpression( nameEdit->text(), mFilterQuery->text() );
352 updateCurrentStoredFilterExpression();
353 storedFilterExpressionBoxInit();
357 void QgsFeatureFilterWidget::editStoredFilterExpression()
359 QgsDialog *dlg =
new QgsDialog(
this, Qt::WindowFlags(), QDialogButtonBox::Save | QDialogButtonBox::Cancel );
360 dlg->setWindowTitle( tr(
"Edit expression" ) );
361 QVBoxLayout *layout = dlg->
layout();
362 dlg->resize( std::max( 400, this->width() / 2 ), dlg->height() );
364 QLabel *nameLabel =
new QLabel( tr(
"Name" ), dlg );
365 QLineEdit *nameEdit =
new QLineEdit( mLayer->storedExpressionManager()->storedExpression( mActionHandleStoreFilterExpression->data().toString() ).name, dlg );
366 QLabel *expressionLabel =
new QLabel( tr(
"Expression" ), dlg );
368 expressionEdit->
setExpression( mLayer->storedExpressionManager()->storedExpression( mActionHandleStoreFilterExpression->data().toString() ).expression );
370 layout->addWidget( nameLabel );
371 layout->addWidget( nameEdit );
372 layout->addWidget( expressionLabel );
373 layout->addWidget( expressionEdit );
374 nameEdit->setFocus();
376 if ( dlg->exec() == QDialog::Accepted )
379 mLayer->storedExpressionManager()->updateStoredExpression( mActionHandleStoreFilterExpression->data().toString(), nameEdit->text(), expressionEdit->
expression(), QgsStoredExpression::Category::FilterExpression );
382 mFilterQuery->setValue( expressionEdit->
expression() );
384 storedFilterExpressionBoxInit();
388 void QgsFeatureFilterWidget::updateCurrentStoredFilterExpression()
390 const QgsStoredExpression currentStoredExpression = mLayer->storedExpressionManager()->findStoredExpressionByExpression( mFilterQuery->value() );
393 mActionHandleStoreFilterExpression->setChecked( !currentStoredExpression.
id.isNull() );
395 mActionHandleStoreFilterExpression->setData( currentStoredExpression.
id );
396 mActionEditStoredFilterExpression->setData( currentStoredExpression.
id );
399 storeExpressionButtonInit();
402 void QgsFeatureFilterWidget::setFilterExpression(
const QString &filterString,
QgsAttributeForm::FilterType type,
bool alwaysShowFilter )
405 if ( !mFilterQuery->text().isEmpty() && !filterString.isEmpty() )
410 filter = filterString;
414 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterQuery->text(), filterString );
418 filter = QStringLiteral(
"(%1) OR (%2)" ).arg( mFilterQuery->text(), filterString );
422 else if ( !filterString.isEmpty() )
424 filter = filterString;
432 mFilterQuery->setText( filter );
434 if ( alwaysShowFilter || !mCurrentSearchWidgetWrapper || !mCurrentSearchWidgetWrapper->applyDirectly() )
437 mFilterButton->setDefaultAction( mActionAdvancedFilter );
438 mFilterButton->setPopupMode( QToolButton::MenuButtonPopup );
439 mFilterQuery->setVisible(
true );
440 mApplyFilterButton->setVisible(
true );
441 mStoreFilterExpressionButton->setVisible(
true );
442 if ( mCurrentSearchWidgetWrapper )
445 replaceSearchWidget( mCurrentSearchWidgetWrapper->widget(), mFilterQuery );
451 if ( filterExpression.hasParserError() )
453 mMessageBar->pushMessage( tr(
"Parsing error" ), filterExpression.parserErrorString(), Qgis::MessageLevel::Warning );
459 if ( !filterExpression.prepare( &context ) )
461 mMessageBar->pushMessage( tr(
"Evaluation error" ), filterExpression.evalErrorString(), Qgis::MessageLevel::Warning );
464 mMainView->filterFeatures( filterExpression, context );
469 void QgsFeatureFilterWidget::replaceSearchWidget( QWidget *oldw, QWidget *neww )
471 mFilterLayout->removeWidget( oldw );
472 oldw->setVisible(
false );
473 mFilterLayout->addWidget( neww, 0, 0 );
474 neww->setVisible(
true );
478 void QgsFeatureFilterWidget::onFilterQueryTextChanged(
const QString &value )
481 mFilterQueryTimer.start( 300 );
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.
@ 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