1919#include " qgslayout.h"
2020#include " qgslayoutviewtool.h"
2121#include " qgslayoutviewmouseevent.h"
22+ #include " qgssettings.h"
23+ #include " qgsrectangle.h"
2224#include < memory>
2325
26+ #define MIN_VIEW_SCALE 0.05
27+ #define MAX_VIEW_SCALE 1000.0
28+
2429QgsLayoutView::QgsLayoutView ( QWidget *parent )
2530 : QGraphicsView( parent )
2631{
@@ -74,6 +79,14 @@ void QgsLayoutView::unsetTool( QgsLayoutViewTool *tool )
7479 }
7580}
7681
82+ void QgsLayoutView::scaleSafe ( double scale )
83+ {
84+ double currentScale = transform ().m11 ();
85+ scale *= currentScale;
86+ scale = qBound ( MIN_VIEW_SCALE, scale, MAX_VIEW_SCALE );
87+ setTransform ( QTransform::fromScale ( scale, scale ) );
88+ }
89+
7790void QgsLayoutView::mousePressEvent ( QMouseEvent *event )
7891{
7992 if ( mTool )
@@ -134,7 +147,10 @@ void QgsLayoutView::wheelEvent( QWheelEvent *event )
134147 }
135148
136149 if ( !mTool || !event->isAccepted () )
137- QGraphicsView::wheelEvent ( event );
150+ {
151+ event->accept ();
152+ wheelZoom ( event );
153+ }
138154}
139155
140156void QgsLayoutView::keyPressEvent ( QKeyEvent *event )
@@ -158,3 +174,53 @@ void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
158174 if ( !mTool || !event->isAccepted () )
159175 QGraphicsView::keyReleaseEvent ( event );
160176}
177+
178+ void QgsLayoutView::wheelZoom ( QWheelEvent *event )
179+ {
180+ // get mouse wheel zoom behavior settings
181+ QgsSettings settings;
182+ double zoomFactor = settings.value ( QStringLiteral ( " qgis/zoom_factor" ), 2 ).toDouble ();
183+
184+ // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
185+ zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * qAbs ( event->angleDelta ().y () );
186+
187+ if ( event->modifiers () & Qt::ControlModifier )
188+ {
189+ // holding ctrl while wheel zooming results in a finer zoom
190+ zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0 ;
191+ }
192+
193+ // calculate zoom scale factor
194+ bool zoomIn = event->angleDelta ().y () > 0 ;
195+ double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
196+
197+ // get current visible part of scene
198+ QRect viewportRect ( 0 , 0 , viewport ()->width (), viewport ()->height () );
199+ QgsRectangle visibleRect = QgsRectangle ( mapToScene ( viewportRect ).boundingRect () );
200+
201+ // transform the mouse pos to scene coordinates
202+ QPointF scenePoint = mapToScene ( event->pos () );
203+
204+ // adjust view center
205+ QgsPointXY oldCenter ( visibleRect.center () );
206+ QgsPointXY newCenter ( scenePoint.x () + ( ( oldCenter.x () - scenePoint.x () ) * scaleFactor ),
207+ scenePoint.y () + ( ( oldCenter.y () - scenePoint.y () ) * scaleFactor ) );
208+ centerOn ( newCenter.x (), newCenter.y () );
209+
210+ // zoom layout
211+ if ( zoomIn )
212+ {
213+ scaleSafe ( zoomFactor );
214+ }
215+ else
216+ {
217+ scaleSafe ( 1 / zoomFactor );
218+ }
219+
220+ // update layout for new zoom
221+ #if 0 // TODO
222+ emit zoomLevelChanged();
223+ updateRulers();
224+ #endif
225+ update ();
226+ }
0 commit comments