Skip to content

Commit f815ebc

Browse files
committed
[FEATURE]: Zoom to feature with right-click in attribute table
1 parent 416c004 commit f815ebc

File tree

7 files changed

+93
-1
lines changed

7 files changed

+93
-1
lines changed

python/gui/attributetable/qgsdualview.sip

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ class QgsDualView : QStackedWidget
9898
* @return The master model
9999
*/
100100
QgsAttributeTableModel* masterModel() const;
101+
/**
102+
Returns the filter model
103+
@return the filter model
104+
*/
105+
QgsAttributeTableFilterModel* filterModel() const;
106+
/**
107+
Returns the table view
108+
@return the table view
109+
*/
110+
const QgsAttributeTableView* tableView() const;
101111

102112
void setRequest( const QgsFeatureRequest& request );
103113

python/gui/qgsmapcanvas.sip

Lines changed: 5 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

src/app/qgsattributetabledialog.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
240240
mMainView->setView( QgsDualView::AttributeTable );
241241

242242
editingToggled();
243+
244+
QObject::connect( mMainView->tableView(), SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) );
243245
}
244246

245247
QgsAttributeTableDialog::~QgsAttributeTableDialog()
@@ -351,6 +353,26 @@ void QgsAttributeTableDialog::updateFieldFromExpressionSelected()
351353
runFieldCalculation( mLayer, mFieldCombo->currentText(), mUpdateExpressionText->currentField(), filteredIds );
352354
}
353355

356+
void QgsAttributeTableDialog::viewWillShowContextMenu( QMenu* menu, QModelIndex atIndex )
357+
{
358+
if ( menu )
359+
{
360+
menu->addAction( tr( "Zoom to feature" ), this, SLOT( zoomToFeature() ) );
361+
}
362+
}
363+
364+
void QgsAttributeTableDialog::zoomToFeature()
365+
{
366+
QModelIndex currentIndex = mMainView->tableView()->currentIndex();
367+
if ( !currentIndex.isValid() )
368+
{
369+
return;
370+
}
371+
372+
QgsFeatureId id = mMainView->filterModel()->rowToId( currentIndex );
373+
QgisApp::instance()->mapCanvas()->zoomToFeatureId( mLayer, id );
374+
}
375+
354376
void QgsAttributeTableDialog::runFieldCalculation( QgsVectorLayer* layer, const QString& fieldName, const QString& expression, const QgsFeatureIds& filteredIds )
355377
{
356378
QApplication::setOverrideCursor( Qt::WaitCursor );

src/app/qgsattributetabledialog.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
203203
void updateFieldFromExpression();
204204
void updateFieldFromExpressionSelected();
205205

206+
/** Add items to the rightclick menu
207+
@menu the context menu
208+
@atIndex the current model index*/
209+
void viewWillShowContextMenu( QMenu* menu, QModelIndex atIndex );
210+
/** Zooms to the active feature*/
211+
void zoomToFeature();
212+
206213
private:
207214
QMenu* mMenuActions;
208215
QAction* mActionToggleEditing;

src/gui/attributetable/qgsdualview.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
136136
* @return The master model
137137
*/
138138
QgsAttributeTableModel* masterModel() const { return mMasterModel; }
139+
/**
140+
Returns the filter model
141+
@return the filter model
142+
*/
143+
QgsAttributeTableFilterModel* filterModel() const { return mFilterModel; }
144+
/**
145+
Returns the table view
146+
@return the table view
147+
*/
148+
const QgsAttributeTableView* tableView() const { return mTableView; }
139149

140150
void setRequest( const QgsFeatureRequest& request );
141151

src/gui/qgsmapcanvas.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,11 @@ void QgsMapCanvas::zoomToSelected( QgsVectorLayer* layer )
10421042
return;
10431043

10441044
QgsRectangle rect = mapSettings().layerExtentToOutputExtent( layer, layer->boundingBoxOfSelected() );
1045+
zoomToFeatureExtent( rect );
1046+
} // zoomToSelected
10451047

1048+
void QgsMapCanvas::zoomToFeatureExtent( QgsRectangle& rect )
1049+
{
10461050
// no selected features, only one selected point feature
10471051
//or two point features with the same x- or y-coordinates
10481052
if ( rect.isEmpty() )
@@ -1063,7 +1067,31 @@ void QgsMapCanvas::zoomToSelected( QgsVectorLayer* layer )
10631067

10641068
setExtent( rect );
10651069
refresh();
1066-
} // zoomToSelected
1070+
}
1071+
1072+
void QgsMapCanvas::zoomToFeatureId( QgsVectorLayer* layer, QgsFeatureId id )
1073+
{
1074+
if ( !layer )
1075+
{
1076+
return;
1077+
}
1078+
1079+
QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFid( id ).setSubsetOfAttributes( QgsAttributeList() ) );
1080+
QgsFeature fet;
1081+
if ( !it.nextFeature( fet ) )
1082+
{
1083+
return;
1084+
}
1085+
1086+
QgsGeometry* geom = fet.geometry();
1087+
if ( !geom )
1088+
{
1089+
return;
1090+
}
1091+
1092+
QgsRectangle rect = mapSettings().layerExtentToOutputExtent( layer, geom->boundingBox() );
1093+
zoomToFeatureExtent( rect );
1094+
}
10671095

10681096
void QgsMapCanvas::panToSelected( QgsVectorLayer* layer )
10691097
{

src/gui/qgsmapcanvas.h

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

2323
#include "qgsexpressioncontext.h"
24+
#include "qgsfeature.h"
2425
#include "qgsrectangle.h"
2526
#include "qgspoint.h"
2627
#include "qgis.h"
@@ -236,6 +237,11 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
236237
@param layer optionally specify different than current layer */
237238
void zoomToSelected( QgsVectorLayer* layer = nullptr );
238239

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

@@ -619,6 +625,10 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
619625
//! called when panning is in action, reset indicates end of panning
620626
void moveCanvasContents( bool reset = false );
621627

628+
//! Zooms to feature extent. Adds a small margin around the extent
629+
//! and does a pan if rect is empty (point extent)
630+
void zoomToFeatureExtent( QgsRectangle& rect );
631+
622632
//! called on resize or changed extent to notify canvas items to change their rectangle
623633
void updateCanvasItemPositions();
624634

0 commit comments

Comments
 (0)