mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Port ability to wheel zoom into/out of layout designer
This commit is contained in:
parent
4065a7ff67
commit
20ca51b59c
@ -67,6 +67,12 @@ class QgsLayoutView: QGraphicsView
|
|||||||
You don't have to call it manually, QgsLayoutViewTool takes care of it.
|
You don't have to call it manually, QgsLayoutViewTool takes care of it.
|
||||||
%End
|
%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:
|
signals:
|
||||||
|
|
||||||
void layoutSet( QgsLayout *layout );
|
void layoutSet( QgsLayout *layout );
|
||||||
|
@ -19,8 +19,13 @@
|
|||||||
#include "qgslayout.h"
|
#include "qgslayout.h"
|
||||||
#include "qgslayoutviewtool.h"
|
#include "qgslayoutviewtool.h"
|
||||||
#include "qgslayoutviewmouseevent.h"
|
#include "qgslayoutviewmouseevent.h"
|
||||||
|
#include "qgssettings.h"
|
||||||
|
#include "qgsrectangle.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#define MIN_VIEW_SCALE 0.05
|
||||||
|
#define MAX_VIEW_SCALE 1000.0
|
||||||
|
|
||||||
QgsLayoutView::QgsLayoutView( QWidget *parent )
|
QgsLayoutView::QgsLayoutView( QWidget *parent )
|
||||||
: QGraphicsView( 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 )
|
void QgsLayoutView::mousePressEvent( QMouseEvent *event )
|
||||||
{
|
{
|
||||||
if ( mTool )
|
if ( mTool )
|
||||||
@ -134,7 +147,10 @@ void QgsLayoutView::wheelEvent( QWheelEvent *event )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( !mTool || !event->isAccepted() )
|
if ( !mTool || !event->isAccepted() )
|
||||||
QGraphicsView::wheelEvent( event );
|
{
|
||||||
|
event->accept();
|
||||||
|
wheelZoom( event );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLayoutView::keyPressEvent( QKeyEvent *event )
|
void QgsLayoutView::keyPressEvent( QKeyEvent *event )
|
||||||
@ -158,3 +174,53 @@ void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
|
|||||||
if ( !mTool || !event->isAccepted() )
|
if ( !mTool || !event->isAccepted() )
|
||||||
QGraphicsView::keyReleaseEvent( event );
|
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();
|
||||||
|
}
|
||||||
|
@ -85,6 +85,12 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
|
|||||||
*/
|
*/
|
||||||
void unsetTool( QgsLayoutViewTool *tool );
|
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:
|
signals:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,6 +117,9 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
//! Zoom layout from a mouse wheel event
|
||||||
|
void wheelZoom( QWheelEvent *event );
|
||||||
|
|
||||||
QPointer< QgsLayoutViewTool > mTool;
|
QPointer< QgsLayoutViewTool > mTool;
|
||||||
|
|
||||||
friend class TestQgsLayoutView;
|
friend class TestQgsLayoutView;
|
||||||
|
@ -73,6 +73,7 @@ ADD_PYTHON_TEST(PyQgsJsonUtils test_qgsjsonutils.py)
|
|||||||
ADD_PYTHON_TEST(PyQgsLayerTreeMapCanvasBridge test_qgslayertreemapcanvasbridge.py)
|
ADD_PYTHON_TEST(PyQgsLayerTreeMapCanvasBridge test_qgslayertreemapcanvasbridge.py)
|
||||||
ADD_PYTHON_TEST(PyQgsLayerTree test_qgslayertree.py)
|
ADD_PYTHON_TEST(PyQgsLayerTree test_qgslayertree.py)
|
||||||
ADD_PYTHON_TEST(PyQgsLayoutManager test_qgslayoutmanager.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(PyQgsLineSymbolLayers test_qgslinesymbollayers.py)
|
||||||
ADD_PYTHON_TEST(PyQgsLayerMetadata test_qgslayermetadata.py)
|
ADD_PYTHON_TEST(PyQgsLayerMetadata test_qgslayermetadata.py)
|
||||||
ADD_PYTHON_TEST(PyQgsLocator test_qgslocator.py)
|
ADD_PYTHON_TEST(PyQgsLocator test_qgslocator.py)
|
||||||
|
63
tests/src/python/test_qgslayoutview.py
Normal file
63
tests/src/python/test_qgslayoutview.py
Normal 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()
|
Loading…
x
Reference in New Issue
Block a user