Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Allow web map style shift-drag zoom
When certain map tools are active, you can hold down shift
and drag a rectangle on the map to zoom to that area. This
is enabled for the map tools which are not selection tools
(since they use shift for adding to selection), and edit
tools.

Gracias a Girona!
  • Loading branch information
nyalldawson committed May 30, 2016
1 parent 8628f21 commit 0050262
Show file tree
Hide file tree
Showing 16 changed files with 209 additions and 8 deletions.
4 changes: 4 additions & 0 deletions python/gui/qgsmaptool.sip
Expand Up @@ -38,6 +38,7 @@ class QgsMapTool : QObject
If it does, the tool can be operated once and then a previous map
tool automatically restored. */
EditTool, /*!< Map tool is an edit tool, which can only be used when layer is editable*/
AllowZoomRect, /*!< Allow zooming by rectangle (by holding shift and dragging) while the tool is active*/
};
typedef QFlags<QgsMapTool::Flag> Flags;

Expand Down Expand Up @@ -183,3 +184,6 @@ class QgsMapTool : QObject


};


QFlags<QgsMapTool::Flag> operator|(QgsMapTool::Flag f1, QFlags<QgsMapTool::Flag> f2);
2 changes: 2 additions & 0 deletions python/gui/qgsmaptoolemitpoint.sip
Expand Up @@ -9,6 +9,8 @@ class QgsMapToolEmitPoint : QgsMapTool
//! constructor
QgsMapToolEmitPoint( QgsMapCanvas* canvas );

virtual Flags flags() const;

//! Overridden mouse move event
virtual void canvasMoveEvent( QgsMapMouseEvent * e );

Expand Down
2 changes: 2 additions & 0 deletions python/gui/qgsmaptoolidentify.sip
Expand Up @@ -47,6 +47,8 @@ class QgsMapToolIdentify : QgsMapTool

virtual ~QgsMapToolIdentify();

virtual Flags flags() const;

//! Overridden mouse move event
virtual void canvasMoveEvent( QgsMapMouseEvent * e );

Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsmaptoolfeatureaction.h
Expand Up @@ -36,6 +36,8 @@ class APP_EXPORT QgsMapToolFeatureAction : public QgsMapTool

~QgsMapToolFeatureAction();

virtual Flags flags() const override { return QgsMapTool::AllowZoomRect; }

//! Overridden mouse move event
virtual void canvasMoveEvent( QgsMapMouseEvent* e ) override;

Expand Down
4 changes: 3 additions & 1 deletion src/app/qgsmaptoolmeasureangle.h
Expand Up @@ -31,7 +31,9 @@ class APP_EXPORT QgsMapToolMeasureAngle: public QgsMapTool
QgsMapToolMeasureAngle( QgsMapCanvas* canvas );
~QgsMapToolMeasureAngle();

//! Mouse move event for overridingqgs
virtual Flags flags() const override { return QgsMapTool::AllowZoomRect; }

//! Mouse move event for overriding
void canvasMoveEvent( QgsMapMouseEvent* e ) override;

//! Mouse release event for overriding
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsmaptoolpointsymbol.h
Expand Up @@ -34,7 +34,7 @@ class APP_EXPORT QgsMapToolPointSymbol: public QgsMapToolEdit
public:
QgsMapToolPointSymbol( QgsMapCanvas* canvas );

virtual Flags flags() const { return QgsMapTool::EditTool; }
virtual Flags flags() const override { return QgsMapTool::EditTool; }

void canvasPressEvent( QgsMapMouseEvent* e ) override;

Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsmeasuretool.h
Expand Up @@ -36,6 +36,8 @@ class APP_EXPORT QgsMeasureTool : public QgsMapTool

~QgsMeasureTool();

virtual Flags flags() const override { return QgsMapTool::AllowZoomRect; }

//! returns whether measuring distance or area
bool measureArea() { return mMeasureArea; }

Expand Down
75 changes: 72 additions & 3 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -62,6 +62,7 @@ email : sherman at mrcc.com
#include "qgsproject.h"
#include "qgsrubberband.h"
#include "qgsvectorlayer.h"
#include "qgscursors.h"
#include <math.h>


Expand Down Expand Up @@ -212,6 +213,7 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
, mSnappingUtils( nullptr )
, mScaleLocked( false )
, mExpressionContextScope( tr( "Map Canvas" ) )
, mZoomDragging( false )
{
setObjectName( name );
mScene = new QGraphicsScene();
Expand Down Expand Up @@ -273,6 +275,9 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
mPreviewEffect = new QgsPreviewEffect( this );
viewport()->setGraphicsEffect( mPreviewEffect );

QPixmap zoomPixmap = QPixmap(( const char ** )( zoom_in ) );
mZoomCursor = QCursor( zoomPixmap, 7, 7 );

setInteractive( false );

refresh();
Expand Down Expand Up @@ -1342,6 +1347,50 @@ void QgsMapCanvas::mouseDoubleClickEvent( QMouseEvent* e )
}// mouseDoubleClickEvent


void QgsMapCanvas::beginZoomRect( QPoint pos )
{
mZoomRect.setRect( 0, 0, 0, 0 );
QApplication::setOverrideCursor( mZoomCursor );
mZoomDragging = true;
mZoomRubberBand.reset( new QgsRubberBand( this, QGis::Polygon ) );
QColor color( Qt::blue );
color.setAlpha( 63 );
mZoomRubberBand->setColor( color );
mZoomRect.setTopLeft( pos );
}

void QgsMapCanvas::endZoomRect( QPoint pos )
{
mZoomDragging = false;
mZoomRubberBand.reset( nullptr );
QApplication::restoreOverrideCursor();

// store the rectangle
mZoomRect.setRight( pos.x() );
mZoomRect.setBottom( pos.y() );

if ( mZoomRect.width() < 5 && mZoomRect.height() < 5 )
{
//probably a mistake - would result in huge zoom!
return;
}

//account for bottom right -> top left dragging
mZoomRect = mZoomRect.normalized();

// set center and zoom
const QSize& zoomRectSize = mZoomRect.size();
const QSize& canvasSize = mSettings.outputSize();
double sfx = ( double )zoomRectSize.width() / canvasSize.width();
double sfy = ( double )zoomRectSize.height() / canvasSize.height();
double sf = qMax( sfx, sfy );

QgsPoint c = mSettings.mapToPixel().toMapCoordinates( mZoomRect.center() );

zoomByFactor( sf, &c );
refresh();
}

void QgsMapCanvas::mousePressEvent( QMouseEvent* e )
{
//use middle mouse button for panning, map tools won't receive any events in that case
Expand All @@ -1352,12 +1401,20 @@ void QgsMapCanvas::mousePressEvent( QMouseEvent* e )
}
else
{

// call handler of current map tool
if ( mMapTool )
{
QScopedPointer<QgsMapMouseEvent> me( new QgsMapMouseEvent( this, e ) );
mMapTool->canvasPressEvent( me.data() );
if ( mMapTool->flags() & QgsMapTool::AllowZoomRect && e->button() == Qt::LeftButton
&& e->modifiers() & Qt::ShiftModifier )
{
beginZoomRect( e->pos() );
return;
}
else
{
QScopedPointer<QgsMapMouseEvent> me( new QgsMapMouseEvent( this, e ) );
mMapTool->canvasPressEvent( me.data() );
}
}
}

Expand All @@ -1382,6 +1439,12 @@ void QgsMapCanvas::mouseReleaseEvent( QMouseEvent* e )
}
else
{
if ( mZoomDragging && e->button() == Qt::LeftButton )
{
endZoomRect( e->pos() );
return;
}

// call handler of current map tool
if ( mMapTool )
{
Expand Down Expand Up @@ -1572,6 +1635,12 @@ void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
{
panAction( e );
}
else if ( mZoomDragging )
{
mZoomRect.setBottomRight( e->pos() );
mZoomRubberBand->setToCanvasRectangle( mZoomRect );
mZoomRubberBand->show();
}
else
{
// call handler of current map tool
Expand Down
24 changes: 24 additions & 0 deletions src/gui/qgsmapcanvas.h
Expand Up @@ -65,6 +65,7 @@ class QgsMapCanvasMap;
class QgsMapOverviewCanvas;
class QgsMapTool;
class QgsSnappingUtils;
class QgsRubberBand;

/** \ingroup gui
* A class that stores visibility and presence in overview flags together
Expand Down Expand Up @@ -785,10 +786,33 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView

QgsExpressionContextScope mExpressionContextScope;

//! Stores zoom rect
QRect mZoomRect;

//! Flag to indicate a zoom by rectangle operation is taking place
bool mZoomDragging;

//! Zoom by rectangle rubber band
QScopedPointer< QgsRubberBand > mZoomRubberBand;

QCursor mZoomCursor;

//! Force a resize of the map canvas item
//! @note added in 2.16
void updateMapSize();

/** Starts zooming via rectangle
* @param pos start position for rectangle
* @note added in QGIS 2.16
*/
void beginZoomRect( QPoint pos );

/** Ends zooming via rectangle
* @param pos end position for rectangle
* @note added in QGIS 2.16
*/
void endZoomRect( QPoint pos );

friend class TestQgsMapCanvas;

}; // class QgsMapCanvas
Expand Down
4 changes: 4 additions & 0 deletions src/gui/qgsmaptool.h
Expand Up @@ -62,6 +62,7 @@ class GUI_EXPORT QgsMapTool : public QObject
If it does, the tool can be operated once and then a previous map
tool automatically restored. */
EditTool = 1 << 2, /*!< Map tool is an edit tool, which can only be used when layer is editable*/
AllowZoomRect = 1 << 3, /*!< Allow zooming by rectangle (by holding shift and dragging) while the tool is active*/
};
Q_DECLARE_FLAGS( Flags, Flag )

Expand Down Expand Up @@ -224,6 +225,9 @@ class GUI_EXPORT QgsMapTool : public QObject

//! translated name of the map tool
QString mToolName;

};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapTool::Flags )

#endif
2 changes: 1 addition & 1 deletion src/gui/qgsmaptooledit.h
Expand Up @@ -33,7 +33,7 @@ class GUI_EXPORT QgsMapToolEdit: public QgsMapTool
QgsMapToolEdit( QgsMapCanvas* canvas );
virtual ~QgsMapToolEdit();

virtual Flags flags() const { return QgsMapTool::EditTool; }
virtual Flags flags() const override { return QgsMapTool::EditTool; }

protected:

Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsmaptoolemitpoint.h
Expand Up @@ -34,6 +34,8 @@ class GUI_EXPORT QgsMapToolEmitPoint : public QgsMapTool
//! constructor
QgsMapToolEmitPoint( QgsMapCanvas* canvas );

virtual Flags flags() const override { return QgsMapTool::AllowZoomRect; }

//! Overridden mouse move event
virtual void canvasMoveEvent( QgsMapMouseEvent* e ) override;

Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsmaptoolidentify.h
Expand Up @@ -92,6 +92,8 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool

virtual ~QgsMapToolIdentify();

virtual Flags flags() const override { return QgsMapTool::AllowZoomRect; }

//! Overridden mouse move event
virtual void canvasMoveEvent( QgsMapMouseEvent* e ) override;

Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsmaptoolpan.h
Expand Up @@ -32,7 +32,7 @@ class GUI_EXPORT QgsMapToolPan : public QgsMapTool
//! constructor
QgsMapToolPan( QgsMapCanvas* canvas );

virtual Flags flags() const { return QgsMapTool::Transient; }
virtual Flags flags() const override { return QgsMapTool::Transient | QgsMapTool::AllowZoomRect; }

//! Mouse press event
virtual void canvasPressEvent( QgsMapMouseEvent* e ) override;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsmaptoolzoom.h
Expand Up @@ -35,7 +35,7 @@ class GUI_EXPORT QgsMapToolZoom : public QgsMapTool

~QgsMapToolZoom();

virtual Flags flags() const { return QgsMapTool::Transient; }
virtual Flags flags() const override { return QgsMapTool::Transient; }

//! Overridden mouse move event
virtual void canvasMoveEvent( QgsMapMouseEvent* e ) override;
Expand Down

1 comment on commit 0050262

@andreasneumann
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

Please sign in to comment.