Skip to content
Permalink
Browse files

Fix "zoom" and "flash" features buttons have no effect when opening

filter mode in attribute form

(For reference: not a regression -- these buttons were originally
added for the "select by form" dialog only, and they've just never
been hooked up for use inside the attribute form itself!)

Fixes #34506
  • Loading branch information
nyalldawson committed Jun 4, 2020
1 parent 9fd82dc commit 6b27958948db2c88ae72b0b9ff99fc8aa8522bf2
@@ -0,0 +1,47 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsmapcanvasutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsMapCanvasUtils
{
%Docstring
Utility functions for working with QgsMapCanvas widgets.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgsmapcanvasutils.h"
%End
public:

static long zoomToMatchingFeatures( QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter );
%Docstring
Zooms a map ``canvas`` to features from the specified ``layer`` which match the given ``filter`` expression string.

The total count of matching features will be returned.
%End

static long flashMatchingFeatures( QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter );
%Docstring
Flashes features from the specified ``layer`` which match the given ``filter`` expression string with a map ``canvas``.

The total count of matching features will be returned.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsmapcanvasutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -123,6 +123,7 @@
%Include auto_generated/qgsmapcanvasitem.sip
%Include auto_generated/qgsmapcanvassnappingutils.sip
%Include auto_generated/qgsmapcanvastracer.sip
%Include auto_generated/qgsmapcanvasutils.sip
%Include auto_generated/qgsmaplayeractionregistry.sip
%Include auto_generated/qgsmaplayercombobox.sip
%Include auto_generated/qgsmaplayerconfigwidget.sip
@@ -22,7 +22,7 @@
#include "qgsmessagebar.h"
#include "qgsexpressioncontextutils.h"
#include "qgsgui.h"

#include "qgsmapcanvasutils.h"

QgsSelectByFormDialog::QgsSelectByFormDialog( QgsVectorLayer *layer, const QgsAttributeEditorContext &context, QWidget *parent, Qt::WindowFlags fl )
: QDialog( parent, fl )
@@ -65,35 +65,11 @@ void QgsSelectByFormDialog::setMapCanvas( QgsMapCanvas *canvas )

void QgsSelectByFormDialog::zoomToFeatures( const QString &filter )
{
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) );

QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( filter )
.setExpressionContext( context )
.setNoAttributes();

QgsFeatureIterator features = mLayer->getFeatures( request );

QgsRectangle bbox;
bbox.setMinimal();
QgsFeature feat;
int featureCount = 0;
while ( features.nextFeature( feat ) )
{
QgsGeometry geom = feat.geometry();
if ( geom.isNull() || geom.constGet()->isEmpty() )
continue;

QgsRectangle r = mMapCanvas->mapSettings().layerExtentToOutputExtent( mLayer, geom.boundingBox() );
bbox.combineExtentWith( r );
featureCount++;
}
features.close();

const long featureCount = QgsMapCanvasUtils::zoomToMatchingFeatures( mMapCanvas, mLayer, filter );
QgsSettings settings;
int timeout = settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
if ( featureCount > 0 )
{
mMapCanvas->zoomToFeatureExtent( bbox );
if ( mMessageBar )
{
mMessageBar->pushMessage( QString(),
@@ -113,28 +89,10 @@ void QgsSelectByFormDialog::zoomToFeatures( const QString &filter )

void QgsSelectByFormDialog::flashFeatures( const QString &filter )
{
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) );

QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( filter )
.setExpressionContext( context )
.setNoAttributes();

QgsFeatureIterator features = mLayer->getFeatures( request );
QgsFeature feat;
QList< QgsGeometry > geoms;
while ( features.nextFeature( feat ) )
{
if ( feat.hasGeometry() )
geoms << feat.geometry();
}

const long featureCount = QgsMapCanvasUtils::flashMatchingFeatures( mMapCanvas, mLayer, filter );
QgsSettings settings;
int timeout = settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
if ( !geoms.empty() )
{
mMapCanvas->flashGeometries( geoms, mLayer->crs() );
}
else if ( mMessageBar )
if ( featureCount == 0 && mMessageBar )
{
mMessageBar->pushMessage( QString(),
tr( "No matching features found" ),
@@ -452,6 +452,7 @@ SET(QGIS_GUI_SRCS
qgsmapcanvasmap.cpp
qgsmapcanvassnappingutils.cpp
qgsmapcanvastracer.cpp
qgsmapcanvasutils.cpp
qgsmaplayeractionregistry.cpp
qgsmaplayercombobox.cpp
qgsmaplayerconfigwidgetfactory.cpp
@@ -683,6 +684,7 @@ SET(QGIS_GUI_HDRS
qgsmapcanvasmap.h
qgsmapcanvassnappingutils.h
qgsmapcanvastracer.h
qgsmapcanvasutils.h
qgsmaplayeractionregistry.h
qgsmaplayercombobox.h
qgsmaplayerconfigwidget.h
@@ -43,6 +43,7 @@
#include "qgsexpressioncontextutils.h"
#include "qgsshortcutsmanager.h"
#include "qgsfieldconditionalformatwidget.h"
#include "qgsmapcanvasutils.h"


QgsDualView::QgsDualView( QWidget *parent )
@@ -149,6 +150,21 @@ void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const Qg
connect( mAttributeForm, &QgsAttributeForm::widgetValueChanged, this, &QgsDualView::featureFormAttributeChanged );
connect( mAttributeForm, &QgsAttributeForm::modeChanged, this, &QgsDualView::formModeChanged );
connect( mAttributeForm, &QgsAttributeForm::filterExpressionSet, this, &QgsDualView::filterExpressionSet );
connect( mAttributeForm, &QgsAttributeForm::flashFeatures, this, [ = ]( const QString & filter )
{
if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
{
QgsMapCanvasUtils::flashMatchingFeatures( canvas, mLayer, filter );
}
} );
connect( mAttributeForm, &QgsAttributeForm::zoomToFeatures, this, [ = ]( const QString & filter )
{
if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
{
QgsMapCanvasUtils::zoomToMatchingFeatures( canvas, mLayer, filter );
}
} );

connect( mMasterModel, &QgsAttributeTableModel::modelChanged, mAttributeForm, &QgsAttributeForm::refreshFeature );
connect( mFilterModel, &QgsAttributeTableFilterModel::sortColumnChanged, this, &QgsDualView::onSortColumnChanged );

@@ -0,0 +1,76 @@
/***************************************************************************
qgsmapcanvasutils.cpp
-------------------
begin : June 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmapcanvasutils.h"
#include "qgsmapcanvas.h"
#include "qgsvectorlayer.h"
#include "qgsexpressioncontextutils.h"

long QgsMapCanvasUtils::zoomToMatchingFeatures( QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter )
{
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );

QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( filter )
.setExpressionContext( context )
.setNoAttributes();

QgsFeatureIterator features = layer->getFeatures( request );

QgsRectangle bbox;
bbox.setMinimal();
QgsFeature feat;
int featureCount = 0;
while ( features.nextFeature( feat ) )
{
QgsGeometry geom = feat.geometry();
if ( geom.isNull() || geom.constGet()->isEmpty() )
continue;

QgsRectangle r = canvas->mapSettings().layerExtentToOutputExtent( layer, geom.boundingBox() );
bbox.combineExtentWith( r );
featureCount++;
}
features.close();

if ( featureCount > 0 )
{
canvas->zoomToFeatureExtent( bbox );
}
return featureCount;
}

long QgsMapCanvasUtils::flashMatchingFeatures( QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter )
{
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );

QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( filter )
.setExpressionContext( context )
.setNoAttributes();

QgsFeatureIterator features = layer->getFeatures( request );
QgsFeature feat;
QList< QgsGeometry > geoms;
while ( features.nextFeature( feat ) )
{
if ( feat.hasGeometry() )
geoms << feat.geometry();
}

if ( !geoms.empty() )
{
canvas->flashGeometries( geoms, layer->crs() );
}
return geoms.size();
}
@@ -0,0 +1,52 @@
/***************************************************************************
qgsmapcanvasutils.h
-------------------
begin : June 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMAPCANVASUTILS_H
#define QGSMAPCANVASUTILS_H

#include "qgis_gui.h"

class QgsMapCanvas;
class QgsVectorLayer;
class QString;

/**
* \ingroup gui
* \class QgsMapCanvasUtils
* Utility functions for working with QgsMapCanvas widgets.
* \since QGIS 3.14
*/
class GUI_EXPORT QgsMapCanvasUtils
{

public:

/**
* Zooms a map \a canvas to features from the specified \a layer which match the given \a filter expression string.
*
* The total count of matching features will be returned.
*/
static long zoomToMatchingFeatures( QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter );

/**
* Flashes features from the specified \a layer which match the given \a filter expression string with a map \a canvas.
*
* The total count of matching features will be returned.
*/
static long flashMatchingFeatures( QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter );

};

#endif //QGSMAPCANVASUTILS_H

0 comments on commit 6b27958

Please sign in to comment.
You can’t perform that action at this time.