1 /***************************************************************************
2                              qgsmodelviewtoolzoom.cpp
3                              -------------------------
4     Date                 : March 2020
5     Copyright            : (C) 2020 Nyall Dawson
6     Email                : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 #include "qgsmodelviewtoolzoom.h"
17 #include "qgsmodelviewmouseevent.h"
18 #include "qgsmodelgraphicsview.h"
19 #include "qgsmodelviewrubberband.h"
20 #include "qgsrectangle.h"
21 #include "qgsapplication.h"
22 #include <QScrollBar>
23 
QgsModelViewToolZoom(QgsModelGraphicsView * view)24 QgsModelViewToolZoom::QgsModelViewToolZoom( QgsModelGraphicsView *view )
25   : QgsModelViewTool( view, tr( "Pan" ) )
26 {
27   setCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::ZoomIn ) );
28   mRubberBand.reset( new QgsModelViewRectangularRubberBand( view ) );
29   mRubberBand->setBrush( QBrush( QColor( 70, 50, 255, 25 ) ) );
30   mRubberBand->setPen( QPen( QBrush( QColor( 70, 50, 255, 100 ) ), 0 ) );
31 }
32 
modelPressEvent(QgsModelViewMouseEvent * event)33 void QgsModelViewToolZoom::modelPressEvent( QgsModelViewMouseEvent *event )
34 {
35   if ( event->button() != Qt::LeftButton )
36   {
37     event->ignore();
38     return;
39   }
40 
41   mMousePressStartPos = event->pos();
42   if ( event->modifiers() & Qt::AltModifier )
43   {
44     //zoom out action, so zoom out and recenter on clicked point
45     const double scaleFactor = 2;
46     //get current visible part of scene
47     const QRect viewportRect( 0, 0, view()->viewport()->width(), view()->viewport()->height() );
48     QgsRectangle visibleRect = QgsRectangle( view()->mapToScene( viewportRect ).boundingRect() );
49 
50     visibleRect.scale( scaleFactor, event->modelPoint().x(), event->modelPoint().y() );
51     const QRectF boundsRect = visibleRect.toRectF();
52 
53     //zoom view to fit desired bounds
54     view()->fitInView( boundsRect, Qt::KeepAspectRatio );
55   }
56   else
57   {
58     //zoom in action
59     startMarqueeZoom( event->modelPoint() );
60   }
61 }
62 
modelMoveEvent(QgsModelViewMouseEvent * event)63 void QgsModelViewToolZoom::modelMoveEvent( QgsModelViewMouseEvent *event )
64 {
65   if ( !mMarqueeZoom )
66   {
67     event->ignore();
68     return;
69   }
70 
71   mRubberBand->update( event->modelPoint(), Qt::KeyboardModifiers() );
72 }
73 
modelReleaseEvent(QgsModelViewMouseEvent * event)74 void QgsModelViewToolZoom::modelReleaseEvent( QgsModelViewMouseEvent *event )
75 {
76   if ( !mMarqueeZoom || event->button() != Qt::LeftButton )
77   {
78     event->ignore();
79     return;
80   }
81 
82   mMarqueeZoom = false;
83   QRectF newBoundsRect = mRubberBand->finish( event->modelPoint() );
84 
85   // click? or click-and-drag?
86   if ( !isClickAndDrag( mMousePressStartPos, event->pos() ) )
87   {
88     //just a click, so zoom to clicked point and recenter
89     const double scaleFactor = 0.5;
90     //get current visible part of scene
91     const QRect viewportRect( 0, 0, view()->viewport()->width(), view()->viewport()->height() );
92     QgsRectangle visibleRect = QgsRectangle( view()->mapToScene( viewportRect ).boundingRect() );
93 
94     visibleRect.scale( scaleFactor, event->modelPoint().x(), event->modelPoint().y() );
95     newBoundsRect = visibleRect.toRectF();
96   }
97 
98   //zoom view to fit desired bounds
99   view()->fitInView( newBoundsRect, Qt::KeepAspectRatio );
100 }
101 
keyPressEvent(QKeyEvent * event)102 void QgsModelViewToolZoom::keyPressEvent( QKeyEvent *event )
103 {
104   //respond to changes in the alt key status and update cursor accordingly
105   if ( !event->isAutoRepeat() )
106   {
107 
108     view()->viewport()->setCursor( ( event->modifiers() & Qt::AltModifier ) ?
109                                    QgsApplication::getThemeCursor( QgsApplication::Cursor::ZoomOut ) :
110                                    QgsApplication::getThemeCursor( QgsApplication::Cursor::ZoomIn ) );
111   }
112   event->ignore();
113 }
114 
keyReleaseEvent(QKeyEvent * event)115 void QgsModelViewToolZoom::keyReleaseEvent( QKeyEvent *event )
116 {
117   //respond to changes in the alt key status and update cursor accordingly
118   if ( !event->isAutoRepeat() )
119   {
120 
121     view()->viewport()->setCursor( ( event->modifiers() & Qt::AltModifier ) ?
122                                    QgsApplication::getThemeCursor( QgsApplication::Cursor::ZoomOut ) :
123                                    QgsApplication::getThemeCursor( QgsApplication::Cursor::ZoomIn ) );
124   }
125   event->ignore();
126 }
127 
deactivate()128 void QgsModelViewToolZoom::deactivate()
129 {
130   if ( mMarqueeZoom )
131   {
132     mMarqueeZoom = false;
133     mRubberBand->finish();
134   }
135   QgsModelViewTool::deactivate();
136 }
137 
startMarqueeZoom(QPointF scenePoint)138 void QgsModelViewToolZoom::startMarqueeZoom( QPointF scenePoint )
139 {
140   mMarqueeZoom = true;
141 
142   mRubberBandStartPos = scenePoint;
143   mRubberBand->start( scenePoint, Qt::KeyboardModifiers() );
144 }
145