QGIS API Documentation  3.23.0-Master (eb871beae0)
qgsexpressionselectiondialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgisexpressionselectiondialog.cpp
3  --------------------------------------
4  Date : 24.1.2013
5  Copyright : (C) 2013 by Matthias kuhn
6  Email : matthias at opengis dot ch
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 
18 #include "qgsapplication.h"
19 #include "qgsexpression.h"
20 #include "qgsgeometry.h"
21 #include "qgsmapcanvas.h"
22 #include "qgsmessagebar.h"
23 #include "qgsvectorlayer.h"
24 #include "qgssettings.h"
25 #include "qgsgui.h"
27 
28 
29 QgsExpressionSelectionDialog::QgsExpressionSelectionDialog( QgsVectorLayer *layer, const QString &startText, QWidget *parent )
30  : QDialog( parent )
31  , mLayer( layer )
32 
33 {
34  setupUi( this );
35 
37 
38  connect( mActionSelect, &QAction::triggered, this, &QgsExpressionSelectionDialog::mActionSelect_triggered );
39  connect( mActionAddToSelection, &QAction::triggered, this, &QgsExpressionSelectionDialog::mActionAddToSelection_triggered );
40  connect( mActionRemoveFromSelection, &QAction::triggered, this, &QgsExpressionSelectionDialog::mActionRemoveFromSelection_triggered );
41  connect( mActionSelectIntersect, &QAction::triggered, this, &QgsExpressionSelectionDialog::mActionSelectIntersect_triggered );
42  connect( mButtonZoomToFeatures, &QToolButton::clicked, this, &QgsExpressionSelectionDialog::mButtonZoomToFeatures_clicked );
43  connect( mPbnClose, &QPushButton::clicked, this, &QgsExpressionSelectionDialog::mPbnClose_clicked );
44  connect( mLayer, &QgsVectorLayer::willBeDeleted, this, &QgsExpressionSelectionDialog::close );
45 
46  setWindowTitle( tr( "%1 — Select by Expression" ).arg( layer->name() ) );
47 
48  mActionSelect->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpressionSelect.svg" ) ) );
49  mActionAddToSelection->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelectAdd.svg" ) ) );
50  mActionRemoveFromSelection->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelectRemove.svg" ) ) );
51  mActionSelectIntersect->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelectIntersect.svg" ) ) );
52 
53  mButtonSelect->addAction( mActionSelect );
54  mButtonSelect->addAction( mActionAddToSelection );
55  mButtonSelect->addAction( mActionRemoveFromSelection );
56  mButtonSelect->addAction( mActionSelectIntersect );
57  mButtonSelect->setDefaultAction( mActionSelect );
58 
60  mExpressionBuilder->initWithLayer( layer, context, QStringLiteral( "selection" ) );
61  mExpressionBuilder->setExpressionText( startText );
62 
63  // by default, zoom to features is hidden, shown only if canvas is set
64  mButtonZoomToFeatures->setVisible( false );
65 
66  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsExpressionSelectionDialog::showHelp );
67 }
68 
70 {
71  return mExpressionBuilder;
72 }
73 
75 {
76  mExpressionBuilder->setExpressionText( text );
77 }
78 
80 {
81  return mExpressionBuilder->expressionText();
82 }
83 
85 {
86  // Store in child widget only.
87  mExpressionBuilder->setGeomCalculator( da );
88 }
89 
91 {
92  mMessageBar = messageBar;
93 }
94 
96 {
97  mMapCanvas = canvas;
98  mButtonZoomToFeatures->setVisible( true );
99 }
100 
101 void QgsExpressionSelectionDialog::mActionSelect_triggered()
102 {
103  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
105  pushSelectedFeaturesMessage();
106  saveRecent();
107 }
108 
109 void QgsExpressionSelectionDialog::mActionAddToSelection_triggered()
110 {
111  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
113  pushSelectedFeaturesMessage();
114  saveRecent();
115 }
116 
117 void QgsExpressionSelectionDialog::mActionSelectIntersect_triggered()
118 {
119  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
121  pushSelectedFeaturesMessage();
122  saveRecent();
123 }
124 
125 void QgsExpressionSelectionDialog::mActionRemoveFromSelection_triggered()
126 {
127  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
129  pushSelectedFeaturesMessage();
130  saveRecent();
131 }
132 
133 void QgsExpressionSelectionDialog::pushSelectedFeaturesMessage()
134 {
135  if ( !mMessageBar )
136  return;
137 
138  const int count = mLayer->selectedFeatureCount();
139  if ( count > 0 )
140  {
141  mMessageBar->pushMessage( QString(),
142  tr( "%n matching feature(s) selected", "matching features", count ),
143  Qgis::MessageLevel::Info );
144  }
145  else
146  {
147  mMessageBar->pushMessage( QString(),
148  tr( "No matching features found" ),
149  Qgis::MessageLevel::Info );
150  }
151 }
152 
153 void QgsExpressionSelectionDialog::mButtonZoomToFeatures_clicked()
154 {
155  if ( mExpressionBuilder->expressionText().isEmpty() || !mMapCanvas )
156  return;
157 
159 
160  const QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( mExpressionBuilder->expressionText() )
161  .setExpressionContext( context )
162  .setNoAttributes();
163 
164  QgsFeatureIterator features = mLayer->getFeatures( request );
165 
166  QgsRectangle bbox;
167  bbox.setMinimal();
168  QgsFeature feat;
169  int featureCount = 0;
170  while ( features.nextFeature( feat ) )
171  {
172  const QgsGeometry geom = feat.geometry();
173  if ( geom.isNull() || geom.constGet()->isEmpty() )
174  continue;
175 
176  const QgsRectangle r = mMapCanvas->mapSettings().layerExtentToOutputExtent( mLayer, geom.boundingBox() );
177  bbox.combineExtentWith( r );
178  featureCount++;
179  }
180  features.close();
181 
182  if ( featureCount > 0 )
183  {
184  mMapCanvas->zoomToFeatureExtent( bbox );
185  if ( mMessageBar )
186  {
187  mMessageBar->pushMessage( QString(),
188  tr( "Zoomed to %n matching feature(s)", "number of matching features", featureCount ),
189  Qgis::MessageLevel::Info );
190  }
191  }
192  else if ( mMessageBar )
193  {
194  mMessageBar->pushMessage( QString(),
195  tr( "No matching features found" ),
196  Qgis::MessageLevel::Info );
197  }
198  saveRecent();
199 }
200 
201 void QgsExpressionSelectionDialog::closeEvent( QCloseEvent *closeEvent )
202 {
203  QDialog::closeEvent( closeEvent );
204 }
205 
206 void QgsExpressionSelectionDialog::mPbnClose_clicked()
207 {
208  close();
209 }
210 
212 {
213  QDialog::done( r );
214  close();
215 }
216 
217 void QgsExpressionSelectionDialog::saveRecent()
218 {
219  mExpressionBuilder->expressionTree()->saveToRecent( mExpressionBuilder->expressionText(), QStringLiteral( "selection" ) );
220 }
221 
222 void QgsExpressionSelectionDialog::showHelp()
223 {
224  QgsHelp::openHelp( QStringLiteral( "introduction/general_tools.html#automatic-selection" ) );
225 }
@ SetSelection
Set selection, removing any existing selection.
@ AddToSelection
Add selection to current selection.
@ IntersectSelection
Modify current selection to include only select features which match.
@ RemoveFromSelection
Remove from current selection.
virtual bool isEmpty() const
Returns true if the geometry is empty.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
A reusable widget that can be used to build a expression string.
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...
QgsExpressionBuilderWidget * expressionBuilder()
The builder widget that is used by the dialog.
QString expressionText()
Returns the current expression text.
void closeEvent(QCloseEvent *closeEvent) override
Implementation for closeEvent Saves the window geometry.
void setExpressionText(const QString &text)
Sets the current expression text.
QgsExpressionSelectionDialog(QgsVectorLayer *layer, const QString &startText=QString(), QWidget *parent=nullptr)
Creates a new selection dialog.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas associated with the dialog.
void setMessageBar(QgsMessageBar *messageBar)
Sets the message bar to display feedback from the dialog.
void setGeomCalculator(const QgsDistanceArea &da)
Sets geometry calculator used in distance/area calculations.
void done(int r) override
Implementation for done (default behavior when pressing esc) Calls close, so the window geometry gets...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Q_GADGET bool isNull
Definition: qgsgeometry.h:127
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:168
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
void zoomToFeatureExtent(QgsRectangle &rect)
Zooms to feature extent.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QString name
Definition: qgsmaplayer.h:76
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
QgsRectangle layerExtentToOutputExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from layer's CRS to output CRS
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE void selectByExpression(const QString &expression, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using an expression.