Port ability to wheel zoom into/out of layout designer

This commit is contained in:
Nyall Dawson 2017-07-05 19:00:32 +10:00
parent 4065a7ff67
commit 20ca51b59c
5 changed files with 146 additions and 1 deletions

View File

@ -67,6 +67,12 @@ class QgsLayoutView: QGraphicsView
You don't have to call it manually, QgsLayoutViewTool takes care of it.
%End
void scaleSafe( double scale );
%Docstring
Scales the view in a safe way, by limiting the acceptable range
of the scale applied. The ``scale`` parameter specifies the zoom factor to scale the view by.
%End
signals:
void layoutSet( QgsLayout *layout );

View File

@ -19,8 +19,13 @@
#include "qgslayout.h"
#include "qgslayoutviewtool.h"
#include "qgslayoutviewmouseevent.h"
#include "qgssettings.h"
#include "qgsrectangle.h"
#include <memory>
#define MIN_VIEW_SCALE 0.05
#define MAX_VIEW_SCALE 1000.0
QgsLayoutView::QgsLayoutView( QWidget *parent )
: QGraphicsView( parent )
{
@ -74,6 +79,14 @@ void QgsLayoutView::unsetTool( QgsLayoutViewTool *tool )
}
}
void QgsLayoutView::scaleSafe( double scale )
{
double currentScale = transform().m11();
scale *= currentScale;
scale = qBound( MIN_VIEW_SCALE, scale, MAX_VIEW_SCALE );
setTransform( QTransform::fromScale( scale, scale ) );
}
void QgsLayoutView::mousePressEvent( QMouseEvent *event )
{
if ( mTool )
@ -134,7 +147,10 @@ void QgsLayoutView::wheelEvent( QWheelEvent *event )
}
if ( !mTool || !event->isAccepted() )
QGraphicsView::wheelEvent( event );
{
event->accept();
wheelZoom( event );
}
}
void QgsLayoutView::keyPressEvent( QKeyEvent *event )
@ -158,3 +174,53 @@ void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
if ( !mTool || !event->isAccepted() )
QGraphicsView::keyReleaseEvent( event );
}
void QgsLayoutView::wheelZoom( QWheelEvent *event )
{
//get mouse wheel zoom behavior settings
QgsSettings settings;
double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
// "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * qAbs( event->angleDelta().y() );
if ( event->modifiers() & Qt::ControlModifier )
{
//holding ctrl while wheel zooming results in a finer zoom
zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
}
//calculate zoom scale factor
bool zoomIn = event->angleDelta().y() > 0;
double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
//get current visible part of scene
QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
//transform the mouse pos to scene coordinates
QPointF scenePoint = mapToScene( event->pos() );
//adjust view center
QgsPointXY oldCenter( visibleRect.center() );
QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ),
scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
centerOn( newCenter.x(), newCenter.y() );
//zoom layout
if ( zoomIn )
{
scaleSafe( zoomFactor );
}
else
{
scaleSafe( 1 / zoomFactor );
}
//update layout for new zoom
#if 0 // TODO
emit zoomLevelChanged();
updateRulers();
#endif
update();
}

View File

@ -85,6 +85,12 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
*/
void unsetTool( QgsLayoutViewTool *tool );
/**
* Scales the view in a safe way, by limiting the acceptable range
* of the scale applied. The \a scale parameter specifies the zoom factor to scale the view by.
*/
void scaleSafe( double scale );
signals:
/**
@ -111,6 +117,9 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
private:
//! Zoom layout from a mouse wheel event
void wheelZoom( QWheelEvent *event );
QPointer< QgsLayoutViewTool > mTool;
friend class TestQgsLayoutView;

View File

@ -73,6 +73,7 @@ ADD_PYTHON_TEST(PyQgsJsonUtils test_qgsjsonutils.py)
ADD_PYTHON_TEST(PyQgsLayerTreeMapCanvasBridge test_qgslayertreemapcanvasbridge.py)
ADD_PYTHON_TEST(PyQgsLayerTree test_qgslayertree.py)
ADD_PYTHON_TEST(PyQgsLayoutManager test_qgslayoutmanager.py)
ADD_PYTHON_TEST(PyQgsLayoutView test_qgslayoutview.py)
ADD_PYTHON_TEST(PyQgsLineSymbolLayers test_qgslinesymbollayers.py)
ADD_PYTHON_TEST(PyQgsLayerMetadata test_qgslayermetadata.py)
ADD_PYTHON_TEST(PyQgsLocator test_qgslocator.py)

View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsLayoutView.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '05/07/2017'
__copyright__ = 'Copyright 2017, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.gui import QgsLayoutView
from qgis.PyQt.QtCore import QRectF
from qgis.PyQt.QtGui import QTransform
from qgis.testing import start_app, unittest
start_app()
class TestQgsLayoutView(unittest.TestCase):
def testScaleSafe(self):
""" test scaleSafe method """
view = QgsLayoutView()
view.fitInView(QRectF(0, 0, 10, 10))
scale = view.transform().m11()
view.scaleSafe(2)
self.assertAlmostEqual(view.transform().m11(), 2)
view.scaleSafe(4)
self.assertAlmostEqual(view.transform().m11(), 8)
# try to zoom in heaps
view.scaleSafe(99999999)
# assume we have hit the limit
scale = view.transform().m11()
view.scaleSafe(2)
self.assertAlmostEqual(view.transform().m11(), scale)
view.setTransform(QTransform.fromScale(1, 1))
self.assertAlmostEqual(view.transform().m11(), 1)
# test zooming out
view.scaleSafe(0.5)
self.assertAlmostEqual(view.transform().m11(), 0.5)
view.scaleSafe(0.1)
self.assertAlmostEqual(view.transform().m11(), 0.05)
# try zooming out heaps
view.scaleSafe(0.000000001)
# assume we have hit the limit
scale = view.transform().m11()
view.scaleSafe(0.5)
self.assertAlmostEqual(view.transform().m11(), scale)
if __name__ == '__main__':
unittest.main()