[ui] select by form/expression harmonization and feature parity (#3912)

This commit is contained in:
Mathieu Pellerin 2016-12-28 11:16:55 +07:00 committed by GitHub
parent 95ff9a1c4c
commit efaf5ea926
7 changed files with 135 additions and 18 deletions

View File

@ -35,12 +35,18 @@ class QgsExpressionSelectionDialog : QDialog
*/
void setGeomCalculator( const QgsDistanceArea & da );
public slots:
void on_mActionSelect_triggered();
void on_mActionAddToSelection_triggered();
void on_mActionRemoveFromSelection_triggered();
void on_mActionSelectIntersect_triggered();
void on_mPbnClose_clicked();
/** Sets the message bar to display feedback from the dialog. This is used when zooming to
* features to display the count of selected features.
* @param messageBar target message bar
* @note added in QGIS 3.0
*/
void setMessageBar( QgsMessageBar* messageBar );
/**
* Sets a map canvas associated with the dialog.
* @note added in QGIS 3.0
*/
void setMapCanvas( QgsMapCanvas* canvas );
protected:
/**

View File

@ -7496,6 +7496,8 @@ void QgisApp::selectByExpression()
}
QgsExpressionSelectionDialog* dlg = new QgsExpressionSelectionDialog( vlayer, QString(), this );
dlg->setMessageBar( messageBar() );
dlg->setMapCanvas( mapCanvas() );
dlg->setAttribute( Qt::WA_DeleteOnClose );
dlg->show();
}

View File

@ -50,7 +50,7 @@ QString QgsSearchWidgetWrapper::toString( QgsSearchWidgetWrapper::FilterFlag fla
case EqualTo:
return QObject::tr( "Equal to (=)" );
case NotEqualTo:
return QObject::tr( "Not equal to" );
return QObject::tr( "Not equal to (!=)" );
case GreaterThan:
return QObject::tr( "Greater than (>)" );
case LessThan:

View File

@ -1328,21 +1328,27 @@ void QgsAttributeForm::init()
QToolButton* selectButton = new QToolButton();
selectButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
selectButton->setText( tr( "&Select features" ) );
selectButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFormSelect.svg" ) ) );
selectButton->setPopupMode( QToolButton::MenuButtonPopup );
selectButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
connect( selectButton, &QToolButton::clicked, this, &QgsAttributeForm::searchSetSelection );
QMenu* selectMenu = new QMenu( selectButton );
QAction* selectAction = new QAction( tr( "Select features" ), selectMenu );
selectAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFormSelect.svg" ) ) );
connect( selectAction, &QAction::triggered, this, &QgsAttributeForm::searchSetSelection );
selectMenu->addAction( selectAction );
QAction* addSelectAction = new QAction( tr( "Add to current selection" ), selectMenu );
addSelectAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelectAdd.svg" ) ) );
connect( addSelectAction, &QAction::triggered, this, &QgsAttributeForm::searchAddToSelection );
selectMenu->addAction( addSelectAction );
QAction* filterSelectAction = new QAction( tr( "Filter current selection" ), selectMenu );
connect( filterSelectAction, &QAction::triggered, this, &QgsAttributeForm::searchIntersectSelection );
selectMenu->addAction( filterSelectAction );
QAction* deselectAction = new QAction( tr( "Remove from current selection" ), selectMenu );
deselectAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelectRemove.svg" ) ) );
connect( deselectAction, &QAction::triggered, this, &QgsAttributeForm::searchRemoveFromSelection );
selectMenu->addAction( deselectAction );
QAction* filterSelectAction = new QAction( tr( "Filter current selection" ), selectMenu );
filterSelectAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelectIntersect.svg" ) ) );
connect( filterSelectAction, &QAction::triggered, this, &QgsAttributeForm::searchIntersectSelection );
selectMenu->addAction( filterSelectAction );
selectButton->setMenu( selectMenu );
boxLayout->addWidget( selectButton );

View File

@ -14,8 +14,11 @@
***************************************************************************/
#include "qgsexpressionselectiondialog.h"
#include "qgsapplication.h"
#include "qgsexpression.h"
#include "qgsgeometry.h"
#include "qgsmessagebar.h"
#include "qgsvectorlayer.h"
#include <QSettings>
@ -23,6 +26,8 @@
QgsExpressionSelectionDialog::QgsExpressionSelectionDialog( QgsVectorLayer* layer, const QString& startText, QWidget* parent )
: QDialog( parent )
, mLayer( layer )
, mMessageBar( nullptr )
, mMapCanvas( nullptr )
{
setupUi( this );
@ -50,6 +55,9 @@ QgsExpressionSelectionDialog::QgsExpressionSelectionDialog( QgsVectorLayer* laye
<< QgsExpressionContextUtils::layerScope( mLayer );
mExpressionBuilder->setExpressionContext( context );
// by default, zoom to features is hidden, shown only if canvas is set
mButtonZoomToFeatures->setVisible( false );
QSettings settings;
restoreGeometry( settings.value( QStringLiteral( "/Windows/ExpressionSelectionDialog/geometry" ) ).toByteArray() );
}
@ -75,6 +83,17 @@ void QgsExpressionSelectionDialog::setGeomCalculator( const QgsDistanceArea & da
mExpressionBuilder->setGeomCalculator( da );
}
void QgsExpressionSelectionDialog::setMessageBar( QgsMessageBar* messageBar )
{
mMessageBar = messageBar;
}
void QgsExpressionSelectionDialog::setMapCanvas( QgsMapCanvas* canvas )
{
mMapCanvas = canvas;
mButtonZoomToFeatures->setVisible( true );
}
void QgsExpressionSelectionDialog::on_mActionSelect_triggered()
{
mLayer->selectByExpression( mExpressionBuilder->expressionText(),
@ -103,6 +122,63 @@ void QgsExpressionSelectionDialog::on_mActionRemoveFromSelection_triggered()
saveRecent();
}
void QgsExpressionSelectionDialog::on_mButtonZoomToFeatures_clicked()
{
if ( mExpressionBuilder->expressionText().isEmpty() || !mMapCanvas )
return;
QgsFeatureIds ids;
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope()
<< QgsExpressionContextUtils::layerScope( mLayer );
QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( mExpressionBuilder->expressionText() )
.setExpressionContext( context )
.setSubsetOfAttributes( QgsAttributeList() );
QgsFeatureIterator features = mLayer->getFeatures( request );
QgsRectangle bbox;
bbox.setMinimal();
QgsFeature feat;
int featureCount = 0;
while ( features.nextFeature( feat ) )
{
QgsGeometry geom = feat.geometry();
if ( geom.isEmpty() || geom.geometry()->isEmpty() )
continue;
QgsRectangle r = mMapCanvas->mapSettings().layerExtentToOutputExtent( mLayer, geom.boundingBox() );
bbox.combineExtentWith( r );
featureCount++;
}
features.close();
QSettings settings;
int timeout = settings.value( QStringLiteral( "/qgis/messageTimeout" ), 5 ).toInt();
if ( featureCount > 0 )
{
mMapCanvas->zoomToFeatureExtent( bbox );
if ( mMessageBar )
{
mMessageBar->pushMessage( QString(),
tr( "Zoomed to %n matching feature(s)", "number of matching features", featureCount ),
QgsMessageBar::INFO,
timeout );
}
}
else if ( mMessageBar )
{
mMessageBar->pushMessage( QString(),
tr( "No matching features found" ),
QgsMessageBar::INFO,
timeout );
}
saveRecent();
}
void QgsExpressionSelectionDialog::closeEvent( QCloseEvent *closeEvent )
{
QDialog::closeEvent( closeEvent );

View File

@ -16,9 +16,13 @@
#ifndef QGSEXPRESSIONSELECTIONDIALOG_H
#define QGSEXPRESSIONSELECTIONDIALOG_H
#include <QDialog>
#include "ui_qgsexpressionselectiondialogbase.h"
#include "qgsmapcanvas.h"
#include "qgsmessagebar.h"
#include <QDialog>
/** \ingroup gui
* This class offers a dialog to change feature selections.
* To do so, a QgsExpressionBuilderWidget is shown in a dialog.
@ -62,11 +66,25 @@ class GUI_EXPORT QgsExpressionSelectionDialog : public QDialog, private Ui::QgsE
*/
void setGeomCalculator( const QgsDistanceArea & da );
public slots:
/** Sets the message bar to display feedback from the dialog. This is used when zooming to
* features to display the count of selected features.
* @param messageBar target message bar
* @note added in QGIS 3.0
*/
void setMessageBar( QgsMessageBar* messageBar );
/**
* Sets a map canvas associated with the dialog.
* @note added in QGIS 3.0
*/
void setMapCanvas( QgsMapCanvas* canvas );
private slots:
void on_mActionSelect_triggered();
void on_mActionAddToSelection_triggered();
void on_mActionRemoveFromSelection_triggered();
void on_mActionSelectIntersect_triggered();
void on_mButtonZoomToFeatures_clicked();
void on_mPbnClose_clicked();
protected:
@ -88,6 +106,8 @@ class GUI_EXPORT QgsExpressionSelectionDialog : public QDialog, private Ui::QgsE
private:
void saveRecent();
QgsVectorLayer* mLayer;
QgsMessageBar* mMessageBar;
QgsMapCanvas* mMapCanvas;
};
#endif

View File

@ -30,14 +30,14 @@
</property>
</spacer>
</item>
<item row="1" column="2">
<item row="1" column="3">
<widget class="QPushButton" name="mPbnClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="1" column="2">
<widget class="QToolButton" name="mButtonSelect">
<property name="minimumSize">
<size>
@ -56,28 +56,35 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="mButtonZoomToFeatures">
<property name="text">
<string>Zoom to features</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QgsExpressionBuilderWidget" name="mExpressionBuilder" native="true"/>
</item>
</layout>
<action name="mActionSelect">
<property name="text">
<string>Select</string>
<string>Select features</string>
</property>
</action>
<action name="mActionAddToSelection">
<property name="text">
<string>Add to selection</string>
<string>Add to current selection</string>
</property>
</action>
<action name="mActionRemoveFromSelection">
<property name="text">
<string>Remove from selection</string>
<string>Remove from current selection</string>
</property>
</action>
<action name="mActionSelectIntersect">
<property name="text">
<string>Select within selection</string>
<string>Filter current selection</string>
</property>
</action>
</widget>