Skip to content

Commit

Permalink
[ui] select by form/expression harmonization and feature parity (#3912)
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Dec 28, 2016
1 parent 95ff9a1 commit efaf5ea
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 18 deletions.
18 changes: 12 additions & 6 deletions python/gui/qgsexpressionselectiondialog.sip
Expand Up @@ -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:
/**
Expand Down
2 changes: 2 additions & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion src/gui/editorwidgets/core/qgssearchwidgetwrapper.cpp
Expand Up @@ -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:
Expand Down
12 changes: 9 additions & 3 deletions src/gui/qgsattributeform.cpp
Expand Up @@ -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 );

Expand Down
76 changes: 76 additions & 0 deletions src/gui/qgsexpressionselectiondialog.cpp
Expand Up @@ -14,15 +14,20 @@
***************************************************************************/

#include "qgsexpressionselectiondialog.h"

#include "qgsapplication.h"
#include "qgsexpression.h"
#include "qgsgeometry.h"
#include "qgsmessagebar.h"
#include "qgsvectorlayer.h"

#include <QSettings>

QgsExpressionSelectionDialog::QgsExpressionSelectionDialog( QgsVectorLayer* layer, const QString& startText, QWidget* parent )
: QDialog( parent )
, mLayer( layer )
, mMessageBar( nullptr )
, mMapCanvas( nullptr )
{
setupUi( this );

Expand Down Expand Up @@ -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() );
}
Expand All @@ -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(),
Expand Down Expand Up @@ -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 );
Expand Down
24 changes: 22 additions & 2 deletions src/gui/qgsexpressionselectiondialog.h
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand All @@ -88,6 +106,8 @@ class GUI_EXPORT QgsExpressionSelectionDialog : public QDialog, private Ui::QgsE
private:
void saveRecent();
QgsVectorLayer* mLayer;
QgsMessageBar* mMessageBar;
QgsMapCanvas* mMapCanvas;
};

#endif
19 changes: 13 additions & 6 deletions src/ui/qgsexpressionselectiondialogbase.ui
Expand Up @@ -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>
Expand All @@ -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>
Expand Down

0 comments on commit efaf5ea

Please sign in to comment.