Skip to content

Commit 7113224

Browse files
committed
[composer] Prevent zooming out/in too far
Would cause issues when scale became 0 and it was impossible to further interact with the composer. (cherry-picked from aa53cfe)
1 parent 0cc424d commit 7113224

File tree

6 files changed

+96
-5
lines changed

6 files changed

+96
-5
lines changed

python/gui/qgscomposerview.sip

+7
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ class QgsComposerView : QGraphicsView
112112
/** Set zoom level, where a zoom level of 1.0 corresponds to 100%*/
113113
void setZoomLevel( double zoomLevel );
114114

115+
/** Scales the view in a safe way, by limiting the acceptable range
116+
* of the scale applied.
117+
* @param scale factor to scale view by
118+
* @note added in QGIS 2.16
119+
*/
120+
void scaleSafe( double scale );
121+
115122
/** Sets whether a preview effect should be used to alter the view's appearance
116123
* @param enabled Set to true to enable the preview effect on the view
117124
* @note added in 2.3

src/app/composer/qgscomposer.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1227,15 +1227,15 @@ void QgsComposer::on_mActionZoomAll_triggered()
12271227

12281228
void QgsComposer::on_mActionZoomIn_triggered()
12291229
{
1230-
mView->scale( 2, 2 );
1230+
mView->scaleSafe( 2 );
12311231
mView->updateRulers();
12321232
mView->update();
12331233
emit zoomLevelChanged();
12341234
}
12351235

12361236
void QgsComposer::on_mActionZoomOut_triggered()
12371237
{
1238-
mView->scale( .5, .5 );
1238+
mView->scaleSafe( 0.5 );
12391239
mView->updateRulers();
12401240
mView->update();
12411241
emit zoomLevelChanged();

src/gui/qgscomposerview.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include "qgscursors.h"
4848
#include "qgscomposerutils.h"
4949

50+
#define MIN_VIEW_SCALE 0.05
51+
#define MAX_VIEW_SCALE 1000.0
52+
5053
QgsComposerView::QgsComposerView( QWidget* parent, const char* name, const Qt::WindowFlags& f )
5154
: QGraphicsView( parent )
5255
, mCurrentTool( Select )
@@ -1651,11 +1654,11 @@ void QgsComposerView::wheelZoom( QWheelEvent * event )
16511654
//zoom composition
16521655
if ( zoomIn )
16531656
{
1654-
scale( zoomFactor, zoomFactor );
1657+
scaleSafe( zoomFactor );
16551658
}
16561659
else
16571660
{
1658-
scale( 1 / zoomFactor, 1 / zoomFactor );
1661+
scaleSafe( 1 / zoomFactor );
16591662
}
16601663

16611664
//update composition for new zoom
@@ -1683,14 +1686,22 @@ void QgsComposerView::setZoomLevel( double zoomLevel )
16831686
dpi = 72;
16841687

16851688
//desired pixel width for 1mm on screen
1686-
double scale = zoomLevel * dpi / 25.4;
1689+
double scale = qBound( MIN_VIEW_SCALE, zoomLevel * dpi / 25.4, MAX_VIEW_SCALE );
16871690
setTransform( QTransform::fromScale( scale, scale ) );
16881691

16891692
updateRulers();
16901693
update();
16911694
emit zoomLevelChanged();
16921695
}
16931696

1697+
void QgsComposerView::scaleSafe( double scale )
1698+
{
1699+
double currentScale = transform().m11();
1700+
scale *= currentScale;
1701+
scale = qBound( MIN_VIEW_SCALE, scale, MAX_VIEW_SCALE );
1702+
setTransform( QTransform::fromScale( scale, scale ) );
1703+
}
1704+
16941705
void QgsComposerView::setPreviewModeEnabled( bool enabled )
16951706
{
16961707
if ( !mPreviewEffect )

src/gui/qgscomposerview.h

+7
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
143143
/** Set zoom level, where a zoom level of 1.0 corresponds to 100%*/
144144
void setZoomLevel( double zoomLevel );
145145

146+
/** Scales the view in a safe way, by limiting the acceptable range
147+
* of the scale applied.
148+
* @param scale factor to scale view by
149+
* @note added in QGIS 2.16
150+
*/
151+
void scaleSafe( double scale );
152+
146153
/** Sets whether a preview effect should be used to alter the view's appearance
147154
* @param enabled Set to true to enable the preview effect on the view
148155
* @note added in 2.3

tests/src/python/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ ADD_PYTHON_TEST(PyQgsComposerMap test_qgscomposermap.py)
2424
ADD_PYTHON_TEST(PyQgsComposerMapGrid test_qgscomposermapgrid.py)
2525
ADD_PYTHON_TEST(PyQgsComposerPicture test_qgscomposerpicture.py)
2626
ADD_PYTHON_TEST(PyQgsComposerShapes test_qgscomposershapes.py)
27+
ADD_PYTHON_TEST(PyQgsComposerView test_qgscomposerview.py)
2728
ADD_PYTHON_TEST(PyQgsComposition test_qgscomposition.py)
2829
ADD_PYTHON_TEST(PyQgsConditionalStyle test_qgsconditionalstyle.py)
2930
ADD_PYTHON_TEST(PyQgsCoordinateTransform test_qgscoordinatetransform.py)
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for QgsComposerView.
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = 'Nyall Dawson'
10+
__date__ = '29/05/2016'
11+
__copyright__ = 'Copyright 2016, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import qgis # NOQA
16+
17+
import os
18+
19+
from qgis.gui import (QgsComposerView)
20+
from qgis.PyQt.QtCore import QRectF
21+
from qgis.PyQt.QtGui import QTransform
22+
23+
from qgis.testing import start_app, unittest
24+
25+
start_app()
26+
27+
28+
class TestQgsComposerView(unittest.TestCase):
29+
30+
def testScaleSafe(self):
31+
""" test scaleSafe method """
32+
33+
view = QgsComposerView()
34+
view.fitInView(QRectF(0, 0, 10, 10))
35+
scale = view.transform().m11()
36+
view.scaleSafe(2)
37+
self.assertAlmostEqual(view.transform().m11(), 2)
38+
view.scaleSafe(4)
39+
self.assertAlmostEqual(view.transform().m11(), 8)
40+
41+
# try to zoom in heaps
42+
view.scaleSafe(99999999)
43+
# assume we have hit the limit
44+
scale = view.transform().m11()
45+
view.scaleSafe(2)
46+
self.assertAlmostEqual(view.transform().m11(), scale)
47+
48+
view.setTransform(QTransform.fromScale(1, 1))
49+
self.assertAlmostEqual(view.transform().m11(), 1)
50+
# test zooming out
51+
view.scaleSafe(0.5)
52+
self.assertAlmostEqual(view.transform().m11(), 0.5)
53+
view.scaleSafe(0.1)
54+
self.assertAlmostEqual(view.transform().m11(), 0.05)
55+
56+
# try zooming out heaps
57+
view.scaleSafe(0.000000001)
58+
# assume we have hit the limit
59+
scale = view.transform().m11()
60+
view.scaleSafe(0.5)
61+
self.assertAlmostEqual(view.transform().m11(), scale)
62+
63+
64+
if __name__ == '__main__':
65+
unittest.main()

0 commit comments

Comments
 (0)