1# -*- coding: utf-8 -*-
2"""QGIS Unit tests for QgsExtentGroupBox
3
4.. note:: This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8"""
9__author__ = 'Nyall Dawson'
10__date__ = '31/05/2017'
11__copyright__ = 'Copyright 2017, The QGIS Project'
12
13import qgis  # NOQA
14import os
15
16from qgis.core import QgsRectangle, QgsCoordinateReferenceSystem, QgsVectorLayer, QgsProject, QgsFeature, QgsGeometry
17from qgis.gui import QgsExtentGroupBox
18
19from qgis.PyQt.QtTest import QSignalSpy
20from qgis.testing import start_app, unittest
21from utilities import unitTestDataPath
22
23start_app()
24TEST_DATA_DIR = unitTestDataPath()
25
26
27class TestQgsExtentGroupBox(unittest.TestCase):
28
29    def testGettersSetters(self):
30        """ test widget getters/setters """
31        w = qgis.gui.QgsExtentGroupBox()
32
33        w.setOriginalExtent(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem('epsg:3111'))
34        self.assertEqual(w.originalExtent(), QgsRectangle(1, 2, 3, 4))
35        self.assertEqual(w.originalCrs().authid(), 'EPSG:3111')
36
37        w.setCurrentExtent(QgsRectangle(11, 12, 13, 14), QgsCoordinateReferenceSystem('epsg:3113'))
38        self.assertEqual(w.currentExtent(), QgsRectangle(11, 12, 13, 14))
39        self.assertEqual(w.currentCrs().authid(), 'EPSG:3113')
40
41        w.setTitleBase('abc')
42        self.assertEqual(w.titleBase(), 'abc')
43
44    def test_checkstate(self):
45        w = QgsExtentGroupBox()
46        spy = QSignalSpy(w.extentChanged)
47        self.assertFalse(w.isCheckable())
48        self.assertFalse(w.isChecked())
49        self.assertTrue(w.outputExtent().isNull())
50
51        w.setCheckable(True)
52        self.assertTrue(w.isCheckable())
53        self.assertTrue(w.isChecked())
54        self.assertTrue(w.outputExtent().isNull())
55        self.assertEqual(len(spy), 0)
56
57        w.setCurrentExtent(QgsRectangle(11, 12, 13, 14), QgsCoordinateReferenceSystem('epsg:3113'))
58        w.setOutputExtentFromCurrent()
59        self.assertTrue(w.isCheckable())
60        self.assertTrue(w.isChecked())
61        self.assertEqual(w.outputExtent(), QgsRectangle(11, 12, 13, 14))
62        self.assertEqual(len(spy), 1)
63
64        w.setChecked(False)
65        self.assertTrue(w.isCheckable())
66        self.assertFalse(w.isChecked())
67        self.assertTrue(w.outputExtent().isNull())
68        self.assertEqual(len(spy), 2)
69
70        w.setChecked(True)
71        self.assertTrue(w.isCheckable())
72        self.assertTrue(w.isChecked())
73        self.assertEqual(w.outputExtent(), QgsRectangle(11, 12, 13, 14))
74        self.assertEqual(len(spy), 3)
75
76    def test_SettingExtent(self):
77        w = qgis.gui.QgsExtentGroupBox()
78
79        spy = QSignalSpy(w.extentChanged)
80
81        w.setOriginalExtent(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem('epsg:3111'))
82        w.setCurrentExtent(QgsRectangle(11, 12, 13, 14), QgsCoordinateReferenceSystem('epsg:3113'))
83
84        w.setOutputExtentFromOriginal()
85        self.assertEqual(w.outputExtent(), QgsRectangle(1, 2, 3, 4))
86        self.assertEqual(w.extentState(), QgsExtentGroupBox.OriginalExtent)
87        self.assertEqual(len(spy), 1)
88
89        w.setOutputExtentFromCurrent()
90        self.assertEqual(w.outputExtent(), QgsRectangle(11, 12, 13, 14))
91        self.assertEqual(w.extentState(), QgsExtentGroupBox.CurrentExtent)
92        self.assertEqual(len(spy), 2)
93
94        w.setOutputExtentFromUser(QgsRectangle(21, 22, 23, 24), QgsCoordinateReferenceSystem('epsg:3111'))
95        self.assertEqual(w.outputExtent(), QgsRectangle(21, 22, 23, 24))
96        self.assertEqual(w.extentState(), QgsExtentGroupBox.UserExtent)
97        self.assertEqual(len(spy), 3)
98
99        shapefile = os.path.join(TEST_DATA_DIR, 'polys.shp')
100        layer = QgsVectorLayer(shapefile, 'Polys', 'ogr')
101        QgsProject.instance().addMapLayer(layer)
102
103        w.setOutputExtentFromLayer(None)
104        # no layer - should be unchanged
105        self.assertEqual(len(spy), 3)
106        self.assertEqual(w.outputExtent(), QgsRectangle(21, 22, 23, 24))
107        self.assertEqual(w.extentState(), QgsExtentGroupBox.UserExtent)
108        self.assertEqual(len(spy), 3)
109
110        w.setOutputExtentFromLayer(layer)
111        self.assertEqual(w.outputExtent().toString(4), QgsRectangle(-118.9229, 24.5079, -83.7900, 46.7262).toString(4))
112        self.assertEqual(w.extentState(), QgsExtentGroupBox.ProjectLayerExtent)
113        self.assertEqual(len(spy), 4)
114
115        QgsProject.instance().removeAllMapLayers()
116
117    def testSetOutputCrs(self):
118        w = qgis.gui.QgsExtentGroupBox()
119        w.setCheckable(True)
120
121        # ensure setting output crs doesn't change state of group box
122        w.setChecked(False)
123        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
124        self.assertFalse(w.isChecked())
125        w.setChecked(True)
126        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
127        self.assertTrue(w.isChecked())
128
129        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
130        w.setCurrentExtent(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem('epsg:4326'))
131        w.setOutputExtentFromCurrent()
132        self.assertEqual(w.outputExtent(), QgsRectangle(1, 2, 3, 4))
133
134        # with reprojection
135        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:3785'))
136        self.assertEqual(w.outputExtent().toString(4), QgsRectangle(111319.4908, 222684.2085, 333958.4724, 445640.1097).toString(4))
137        # change CRS back
138        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
139        # extent should be back to current - not a reprojection of the reprojected bounds
140        self.assertEqual(w.outputExtent().toString(20), QgsRectangle(1, 2, 3, 4).toString(20))
141
142        # repeat, this time using original extents
143        w = qgis.gui.QgsExtentGroupBox()
144
145        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
146        w.setOriginalExtent(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem('epsg:4326'))
147        w.setOutputExtentFromOriginal()
148        self.assertEqual(w.outputExtent(), QgsRectangle(1, 2, 3, 4))
149
150        # with reprojection
151        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:3785'))
152        self.assertEqual(w.outputExtent().toString(4),
153                         QgsRectangle(111319.4908, 222684.2085, 333958.4724, 445640.1097).toString(4))
154        # change CRS back
155        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
156        # extent should be back to original - not a reprojection of the reprojected bounds
157        self.assertEqual(w.outputExtent().toString(20), QgsRectangle(1, 2, 3, 4).toString(20))
158
159        # repeat, this time using layer extent
160        layer = QgsVectorLayer("Polygon?crs=epsg:4326", 'memory', 'memory')
161        self.assertTrue(layer.isValid())
162        f = QgsFeature()
163        f.setGeometry(QgsGeometry.fromWkt('Polygon((1 2, 3 2, 3 4, 1 4, 1 2))'))
164        layer.dataProvider().addFeatures([f])
165        QgsProject.instance().addMapLayer(layer)
166        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
167        w.setOutputExtentFromLayer(layer)
168        self.assertEqual(w.outputExtent(), QgsRectangle(1, 2, 3, 4))
169
170        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:3785'))
171        self.assertEqual(w.outputExtent().toString(4),
172                         QgsRectangle(111319.4908, 222684.2085, 333958.4724, 445640.1097).toString(4))
173        # change CRS back
174        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
175        # extent should be back to original - not a reprojection of the reprojected bounds
176        self.assertEqual(w.outputExtent().toString(20), QgsRectangle(1, 2, 3, 4).toString(20))
177
178        # custom extent
179        w = qgis.gui.QgsExtentGroupBox()
180
181        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
182        w.setOutputExtentFromUser(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem('epsg:4326'))
183        self.assertEqual(w.outputExtent(), QgsRectangle(1, 2, 3, 4))
184
185        # with reprojection
186        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:3785'))
187        self.assertEqual(w.outputExtent().toString(4),
188                         QgsRectangle(111319.4908, 222684.2085, 333958.4724, 445640.1097).toString(4))
189        # change CRS back
190        w.setOutputCrs(QgsCoordinateReferenceSystem('epsg:4326'))
191        # in this case we can't retrieve the original user extent in 4326, so we have a reprojection of the reprojected bounds
192        # just test this by restricting the test to 4 decimals
193        self.assertEqual(w.outputExtent().toString(4), QgsRectangle(1, 2, 3, 4).toString(4))
194
195
196if __name__ == '__main__':
197    unittest.main()
198