Skip to content
Permalink
Browse files

[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 00502620c004520e1144957d2fc5f949d6343e50
@@ -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;

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


};


QFlags<QgsMapTool::Flag> operator|(QgsMapTool::Flag f1, QFlags<QgsMapTool::Flag> f2);
@@ -9,6 +9,8 @@ class QgsMapToolEmitPoint : QgsMapTool
//! constructor
QgsMapToolEmitPoint( QgsMapCanvas* canvas );

virtual Flags flags() const;

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

@@ -47,6 +47,8 @@ class QgsMapToolIdentify : QgsMapTool

virtual ~QgsMapToolIdentify();

virtual Flags flags() const;

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

@@ -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;

@@ -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
@@ -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;

@@ -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; }

@@ -62,6 +62,7 @@ email : sherman at mrcc.com
#include "qgsproject.h"
#include "qgsrubberband.h"
#include "qgsvectorlayer.h"
#include "qgscursors.h"
#include <math.h>


@@ -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();
@@ -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();
@@ -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
@@ -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() );
}
}
}

@@ -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 )
{
@@ -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
@@ -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
@@ -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
@@ -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 )

@@ -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
@@ -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:

@@ -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;

@@ -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;

@@ -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;
@@ -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;

1 comment on commit 0050262

@andreasneumann

This comment has been minimized.

Copy link
Member

@andreasneumann andreasneumann commented on 0050262 May 30, 2016

Cool!

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