Skip to content

Commit 3febba2

Browse files
committedJan 12, 2016
Merge pull request #2619 from mhugent/zoom_to_feature
[FEATURE]: Zoom to feature with right-click in attribute table
2 parents e351d24 + fb996ae commit 3febba2

File tree

9 files changed

+113
-1
lines changed

9 files changed

+113
-1
lines changed
 

‎python/gui/attributetable/qgsattributetablefiltermodel.sip

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ class QgsAttributeTableFilterModel: QSortFilterProxyModel, QgsFeatureModel
9696

9797
virtual QModelIndex mapFromMaster( const QModelIndex &sourceIndex ) const;
9898

99+
/** Returns the map canvas*/
100+
QgsMapCanvas* mapCanvas() const;
101+
99102
protected:
100103
/**
101104
* Returns true if the source row will be accepted

‎python/gui/qgsmapcanvas.sip

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ class QgsMapCanvas : QGraphicsView
168168
@param layer optionally specify different than current layer */
169169
void zoomToSelected( QgsVectorLayer* layer = NULL );
170170

171+
/** Set canvas extent to the bounding box of a feature
172+
@param layer the vector layer
173+
@param id the feature id*/
174+
void zoomToFeatureId( QgsVectorLayer* layer, QgsFeatureId id );
175+
171176
/** Pan to the selected features of current (vector) layer keeping same extent. */
172177
void panToSelected( QgsVectorLayer* layer = NULL );
173178

@@ -501,6 +506,9 @@ class QgsMapCanvas : QGraphicsView
501506
//! @note added in 2.12
502507
void layerStyleOverridesChanged();
503508

509+
//! emit a message (usually to be displayed in a message bar)
510+
void messageEmitted( const QString& title, const QString& message, QgsMessageBar::MessageLevel = QgsMessageBar::INFO );
511+
504512
protected:
505513
//! Overridden standard event to be gestures aware
506514
bool event( QEvent * e );
@@ -538,6 +546,10 @@ class QgsMapCanvas : QGraphicsView
538546
//! called when panning is in action, reset indicates end of panning
539547
void moveCanvasContents( bool reset = false );
540548

549+
//! Zooms to feature extent. Adds a small margin around the extent
550+
//! and does a pan if rect is empty (point extent)
551+
void zoomToFeatureExtent( QgsRectangle& rect );
552+
541553
//! called on resize or changed extent to notify canvas items to change their rectangle
542554
void updateCanvasItemPositions();
543555

‎src/app/qgisapp.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,8 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
620620

621621
// "theMapCanvas" used to find this canonical instance later
622622
mMapCanvas = new QgsMapCanvas( centralWidget, "theMapCanvas" );
623+
connect( mMapCanvas, SIGNAL( messageEmitted( const QString&, const QString&, QgsMessageBar::MessageLevel ) ),
624+
this, SLOT( displayMessage( const QString&, const QString&, QgsMessageBar::MessageLevel ) ) );
623625
mMapCanvas->setWhatsThis( tr( "Map canvas. This is where raster and vector "
624626
"layers are displayed when added to the map" ) );
625627

@@ -1034,6 +1036,8 @@ QgisApp::QgisApp()
10341036
setupUi( this );
10351037
mInternalClipboard = new QgsClipboard;
10361038
mMapCanvas = new QgsMapCanvas();
1039+
connect( mMapCanvas, SIGNAL( messageEmitted( const QString&, const QString&, QgsMessageBar::MessageLevel ) ),
1040+
this, SLOT( displayMessage( const QString&, const QString&, QgsMessageBar::MessageLevel ) ) );
10371041
mMapCanvas->freeze();
10381042
mLayerTreeView = new QgsLayerTreeView( this );
10391043
mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas );
@@ -9459,6 +9463,11 @@ void QgisApp::displayMapToolMessage( const QString& message, QgsMessageBar::Mess
94599463
}
94609464
}
94619465

9466+
void QgisApp::displayMessage( const QString& title, const QString& message, QgsMessageBar::MessageLevel level )
9467+
{
9468+
messageBar()->pushMessage( title, message, level, messageTimeout() );
9469+
}
9470+
94629471
void QgisApp::removeMapToolMessage()
94639472
{
94649473
// remove previous message

‎src/app/qgisapp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
10881088
void showRotation();
10891089
void showStatusMessage( const QString& theMessage );
10901090
void displayMapToolMessage( const QString& message, QgsMessageBar::MessageLevel level = QgsMessageBar::INFO );
1091+
void displayMessage( const QString& title, const QString& message, QgsMessageBar::MessageLevel level );
10911092
void removeMapToolMessage();
10921093
void updateMouseCoordinatePrecision();
10931094
void hasCrsTransformEnabled( bool theFlag );

‎src/gui/attributetable/qgsattributetablefiltermodel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
151151
*/
152152
virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override;
153153

154+
/** Returns the map canvas*/
155+
QgsMapCanvas* mapCanvas() const { return mCanvas; }
156+
154157
protected:
155158
/**
156159
* Returns true if the source row will be accepted

‎src/gui/attributetable/qgsdualview.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,18 @@ int QgsDualView::filteredFeatureCount()
348348

349349
void QgsDualView::viewWillShowContextMenu( QMenu* menu, const QModelIndex& atIndex )
350350
{
351+
if ( !menu )
352+
{
353+
return;
354+
}
355+
356+
QgsVectorLayer* vl = mFilterModel->layer();
357+
QgsMapCanvas* canvas = mFilterModel->mapCanvas();
358+
if ( canvas && vl && vl->geometryType() != QGis::NoGeometry )
359+
{
360+
menu->addAction( tr( "Zoom to feature" ), this, SLOT( zoomToCurrentFeature() ) );
361+
}
362+
351363
QModelIndex sourceIndex = mFilterModel->mapToSource( atIndex );
352364

353365
//add user-defined actions to context menu
@@ -389,6 +401,22 @@ void QgsDualView::viewWillShowContextMenu( QMenu* menu, const QModelIndex& atInd
389401
menu->addAction( tr( "Open form" ), a, SLOT( featureForm() ) );
390402
}
391403

404+
void QgsDualView::zoomToCurrentFeature()
405+
{
406+
QModelIndex currentIndex = mTableView->currentIndex();
407+
if ( !currentIndex.isValid() )
408+
{
409+
return;
410+
}
411+
412+
QgsFeatureId id = mFilterModel->rowToId( currentIndex );
413+
QgsMapCanvas* canvas = mFilterModel->mapCanvas();
414+
if ( canvas )
415+
{
416+
canvas->zoomToFeatureId( mLayerCache->layer(), id );
417+
}
418+
}
419+
392420
void QgsDualView::previewExpressionChanged( const QString& expression )
393421
{
394422
mLayerCache->layer()->setDisplayExpression( expression );

‎src/gui/attributetable/qgsdualview.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
217217
*/
218218
virtual void finished();
219219

220+
/** Zooms to the active feature*/
221+
void zoomToCurrentFeature();
222+
220223
private:
221224
void initLayerCache( QgsVectorLayer *layer, bool cacheGeometry );
222225
void initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request );

‎src/gui/qgsmapcanvas.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,11 @@ void QgsMapCanvas::zoomToSelected( QgsVectorLayer* layer )
10441044
return;
10451045

10461046
QgsRectangle rect = mapSettings().layerExtentToOutputExtent( layer, layer->boundingBoxOfSelected() );
1047+
zoomToFeatureExtent( rect );
1048+
} // zoomToSelected
10471049

1050+
void QgsMapCanvas::zoomToFeatureExtent( QgsRectangle& rect )
1051+
{
10481052
// no selected features, only one selected point feature
10491053
//or two point features with the same x- or y-coordinates
10501054
if ( rect.isEmpty() )
@@ -1065,7 +1069,42 @@ void QgsMapCanvas::zoomToSelected( QgsVectorLayer* layer )
10651069

10661070
setExtent( rect );
10671071
refresh();
1068-
} // zoomToSelected
1072+
}
1073+
1074+
void QgsMapCanvas::zoomToFeatureId( QgsVectorLayer* layer, QgsFeatureId id )
1075+
{
1076+
if ( !layer )
1077+
{
1078+
return;
1079+
}
1080+
1081+
QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFid( id ).setSubsetOfAttributes( QgsAttributeList() ) );
1082+
QgsFeature fet;
1083+
if ( !it.nextFeature( fet ) )
1084+
{
1085+
return;
1086+
}
1087+
1088+
QgsGeometry* geom = fet.geometry();
1089+
1090+
QString errorMessage;
1091+
if ( !geom || !geom->geometry() )
1092+
{
1093+
errorMessage = tr( "Feature does not have a geometry" );
1094+
}
1095+
else if ( geom->geometry()->isEmpty() )
1096+
{
1097+
errorMessage = tr( "Feature geometry is empty" );
1098+
}
1099+
if ( !errorMessage.isEmpty() )
1100+
{
1101+
emit messageEmitted( tr( "Zoom to feature id failed" ), errorMessage, QgsMessageBar::WARNING );
1102+
return;
1103+
}
1104+
1105+
QgsRectangle rect = mapSettings().layerExtentToOutputExtent( layer, geom->boundingBox() );
1106+
zoomToFeatureExtent( rect );
1107+
}
10691108

10701109
void QgsMapCanvas::panToSelected( QgsVectorLayer* layer )
10711110
{

‎src/gui/qgsmapcanvas.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "qgsconfig.h"
2222

2323
#include "qgsexpressioncontext.h"
24+
#include "qgsfeature.h"
25+
#include "qgsmessagebar.h"
2426
#include "qgsrectangle.h"
2527
#include "qgspoint.h"
2628
#include "qgis.h"
@@ -236,6 +238,11 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
236238
@param layer optionally specify different than current layer */
237239
void zoomToSelected( QgsVectorLayer* layer = nullptr );
238240

241+
/** Set canvas extent to the bounding box of a feature
242+
@param layer the vector layer
243+
@param id the feature id*/
244+
void zoomToFeatureId( QgsVectorLayer* layer, QgsFeatureId id );
245+
239246
/** Pan to the selected features of current (vector) layer keeping same extent. */
240247
void panToSelected( QgsVectorLayer* layer = nullptr );
241248

@@ -580,6 +587,9 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
580587
//! @note added in 2.12
581588
void layerStyleOverridesChanged();
582589

590+
//! emit a message (usually to be displayed in a message bar)
591+
void messageEmitted( const QString& title, const QString& message, QgsMessageBar::MessageLevel = QgsMessageBar::INFO );
592+
583593
protected:
584594
#ifdef HAVE_TOUCH
585595
//! Overridden standard event to be gestures aware
@@ -619,6 +629,10 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
619629
//! called when panning is in action, reset indicates end of panning
620630
void moveCanvasContents( bool reset = false );
621631

632+
//! Zooms to feature extent. Adds a small margin around the extent
633+
//! and does a pan if rect is empty (point extent)
634+
void zoomToFeatureExtent( QgsRectangle& rect );
635+
622636
//! called on resize or changed extent to notify canvas items to change their rectangle
623637
void updateCanvasItemPositions();
624638

0 commit comments

Comments
 (0)
Please sign in to comment.