Skip to content

Commit aa53cfe

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.
1 parent f9a10e4 commit aa53cfe

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
@@ -1250,15 +1250,15 @@ void QgsComposer::on_mActionZoomAll_triggered()
12501250

12511251
void QgsComposer::on_mActionZoomIn_triggered()
12521252
{
1253-
mView->scale( 2, 2 );
1253+
mView->scaleSafe( 2 );
12541254
mView->updateRulers();
12551255
mView->update();
12561256
emit zoomLevelChanged();
12571257
}
12581258

12591259
void QgsComposer::on_mActionZoomOut_triggered()
12601260
{
1261-
mView->scale( .5, .5 );
1261+
mView->scaleSafe( 0.5 );
12621262
mView->updateRulers();
12631263
mView->update();
12641264
emit zoomLevelChanged();

src/gui/qgscomposerview.cpp

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

51+
#define MIN_VIEW_SCALE 0.05
52+
#define MAX_VIEW_SCALE 1000.0
53+
5154
QgsComposerView::QgsComposerView( QWidget* parent, const char* name, const Qt::WindowFlags& f )
5255
: QGraphicsView( parent )
5356
, mCurrentTool( Select )
@@ -2060,11 +2063,11 @@ void QgsComposerView::wheelZoom( QWheelEvent * event )
20602063
//zoom composition
20612064
if ( zoomIn )
20622065
{
2063-
scale( zoomFactor, zoomFactor );
2066+
scaleSafe( zoomFactor );
20642067
}
20652068
else
20662069
{
2067-
scale( 1 / zoomFactor, 1 / zoomFactor );
2070+
scaleSafe( 1 / zoomFactor );
20682071
}
20692072

20702073
//update composition for new zoom
@@ -2092,14 +2095,22 @@ void QgsComposerView::setZoomLevel( double zoomLevel )
20922095
dpi = 72;
20932096

20942097
//desired pixel width for 1mm on screen
2095-
double scale = zoomLevel * dpi / 25.4;
2098+
double scale = qBound( MIN_VIEW_SCALE, zoomLevel * dpi / 25.4, MAX_VIEW_SCALE );
20962099
setTransform( QTransform::fromScale( scale, scale ) );
20972100

20982101
updateRulers();
20992102
update();
21002103
emit zoomLevelChanged();
21012104
}
21022105

2106+
void QgsComposerView::scaleSafe( double scale )
2107+
{
2108+
double currentScale = transform().m11();
2109+
scale *= currentScale;
2110+
scale = qBound( MIN_VIEW_SCALE, scale, MAX_VIEW_SCALE );
2111+
setTransform( QTransform::fromScale( scale, scale ) );
2112+
}
2113+
21032114
void QgsComposerView::setPreviewModeEnabled( bool enabled )
21042115
{
21052116
if ( !mPreviewEffect )

src/gui/qgscomposerview.h

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

151+
/** Scales the view in a safe way, by limiting the acceptable range
152+
* of the scale applied.
153+
* @param scale factor to scale view by
154+
* @note added in QGIS 2.16
155+
*/
156+
void scaleSafe( double scale );
157+
151158
/** Sets whether a preview effect should be used to alter the view's appearance
152159
* @param enabled Set to true to enable the preview effect on the view
153160
* @note added in 2.3

tests/src/python/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ADD_PYTHON_TEST(PyQgsComposerPicture test_qgscomposerpicture.py)
2929
ADD_PYTHON_TEST(PyQgsComposerShapes test_qgscomposershapes.py)
3030
ADD_PYTHON_TEST(PyQgsComposerPolygon test_qgscomposerpolygon.py)
3131
ADD_PYTHON_TEST(PyQgsComposerPolyline test_qgscomposerpolyline.py)
32+
ADD_PYTHON_TEST(PyQgsComposerView test_qgscomposerview.py)
3233
ADD_PYTHON_TEST(PyQgsComposition test_qgscomposition.py)
3334
ADD_PYTHON_TEST(PyQgsConditionalStyle test_qgsconditionalstyle.py)
3435
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)