1# -*- coding: utf-8 -*-
2"""QGIS Unit tests for QgsMapLayerComboBox
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__ = '14/06/2019'
11__copyright__ = 'Copyright 2019, The QGIS Project'
12
13import qgis  # NOQA
14
15from qgis.core import QgsVectorLayer, QgsMeshLayer, QgsProject, QgsMapLayerProxyModel
16from qgis.gui import QgsMapLayerComboBox
17from qgis.PyQt.QtCore import (
18    QCoreApplication,
19    QEvent
20)
21from qgis.PyQt.QtTest import QSignalSpy
22
23from qgis.testing import start_app, unittest
24
25start_app()
26
27
28def create_layer(name):
29    layer = QgsVectorLayer("Point?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
30                           name, "memory")
31    return layer
32
33
34def create_mesh_layer(name):
35    layer = QgsMeshLayer("1.0, 2.0\n2.0, 2.0\n3.0, 2.0\n---\n0, 1, 3", name, "mesh_memory")
36    return layer
37
38
39class TestQgsMapLayerComboBox(unittest.TestCase):
40
41    def testGettersSetters(self):
42        """ test combo getters/setters """
43        m = QgsMapLayerComboBox()
44        l1 = create_layer('l1')
45        QgsProject.instance().addMapLayer(l1)
46        l2 = create_layer('l2')
47        QgsProject.instance().addMapLayer(l2)
48
49        m.setFilters(QgsMapLayerProxyModel.LineLayer | QgsMapLayerProxyModel.WritableLayer)
50        self.assertEqual(m.filters(), QgsMapLayerProxyModel.LineLayer | QgsMapLayerProxyModel.WritableLayer)
51
52        m.setExceptedLayerList([l2])
53        self.assertEqual(m.exceptedLayerList(), [l2])
54
55        m.setExcludedProviders(['a', 'b'])
56        self.assertEqual(m.excludedProviders(), ['a', 'b'])
57
58    def testMeshLayer(self):
59        m = QgsMapLayerComboBox()
60        l1 = create_mesh_layer("l1")
61        QgsProject.instance().addMapLayer(l1)
62        l2 = create_layer('l2')
63        QgsProject.instance().addMapLayer(l2)
64
65        m.setFilters(QgsMapLayerProxyModel.MeshLayer)
66        self.assertEqual(m.filters(), QgsMapLayerProxyModel.MeshLayer)
67
68        self.assertEqual(m.count(), 1)
69        self.assertEqual(m.itemText(0), 'l1')
70
71    def testFilterGeometryType(self):
72        """ test filtering by geometry type """
73        QgsProject.instance().clear()
74        m = QgsMapLayerComboBox()
75        l1 = QgsVectorLayer("Point?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
76                            'layer 1', "memory")
77        QgsProject.instance().addMapLayer(l1)
78        l2 = QgsVectorLayer("Polygon?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
79                            'layer 2', "memory")
80        QgsProject.instance().addMapLayer(l2)
81        l3 = QgsVectorLayer("None?field=fldtxt:string&field=fldint:integer",
82                            'layer 3', "memory")
83        QgsProject.instance().addMapLayer(l3)
84        l4 = QgsVectorLayer("LineString?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
85                            'layer 4', "memory")
86        QgsProject.instance().addMapLayer(l4)
87
88        m.setFilters(QgsMapLayerProxyModel.PolygonLayer)
89        self.assertEqual(m.count(), 1)
90        self.assertEqual(m.itemText(0), 'layer 2')
91
92        m.setFilters(QgsMapLayerProxyModel.PointLayer)
93        self.assertEqual(m.count(), 1)
94        self.assertEqual(m.itemText(0), 'layer 1')
95
96        m.setFilters(QgsMapLayerProxyModel.LineLayer)
97        self.assertEqual(m.count(), 1)
98        self.assertEqual(m.itemText(0), 'layer 4')
99
100        m.setFilters(QgsMapLayerProxyModel.NoGeometry)
101        self.assertEqual(m.count(), 1)
102        self.assertEqual(m.itemText(0), 'layer 3')
103
104        m.setFilters(QgsMapLayerProxyModel.HasGeometry)
105        self.assertEqual(m.count(), 3)
106        self.assertEqual(m.itemText(0), 'layer 1')
107        self.assertEqual(m.itemText(1), 'layer 2')
108        self.assertEqual(m.itemText(2), 'layer 4')
109
110        m.setFilters(QgsMapLayerProxyModel.VectorLayer)
111        self.assertEqual(m.count(), 4)
112        self.assertEqual(m.itemText(0), 'layer 1')
113        self.assertEqual(m.itemText(1), 'layer 2')
114        self.assertEqual(m.itemText(2), 'layer 3')
115        self.assertEqual(m.itemText(3), 'layer 4')
116
117        m.setFilters(QgsMapLayerProxyModel.PluginLayer)
118        self.assertEqual(m.count(), 0)
119
120        m.setFilters(QgsMapLayerProxyModel.RasterLayer)
121        self.assertEqual(m.count(), 0)
122
123    def testFilterByLayer(self):
124        """ test filtering by layer"""
125        QgsProject.instance().clear()
126        m = QgsMapLayerComboBox()
127        l1 = QgsVectorLayer("Point?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
128                            'layer 1', "memory")
129        QgsProject.instance().addMapLayer(l1)
130        l2 = QgsVectorLayer("Polygon?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
131                            'lAyEr 2', "memory")
132        QgsProject.instance().addMapLayer(l2)
133        l3 = QgsVectorLayer("None?field=fldtxt:string&field=fldint:integer",
134                            'another', "memory")
135        QgsProject.instance().addMapLayer(l3)
136        l4 = QgsVectorLayer("LineString?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
137                            'final layer', "memory")
138        QgsProject.instance().addMapLayer(l4)
139
140        self.assertEqual(m.count(), 4)
141        self.assertEqual(m.itemText(0), 'another')
142        self.assertEqual(m.itemText(1), 'final layer')
143        self.assertEqual(m.itemText(2), 'layer 1')
144        self.assertEqual(m.itemText(3), 'lAyEr 2')
145
146        m.setExceptedLayerList([l1, l3])
147        self.assertEqual(m.count(), 2)
148        self.assertEqual(m.itemText(0), 'final layer')
149        self.assertEqual(m.itemText(1), 'lAyEr 2')
150
151        m.setExceptedLayerList([l2, l4])
152        self.assertEqual(m.count(), 2)
153        self.assertEqual(m.itemText(0), 'another')
154        self.assertEqual(m.itemText(1), 'layer 1')
155
156    def testSignals(self):
157        QgsProject.instance().clear()
158        m = QgsMapLayerComboBox()
159        l1 = QgsVectorLayer("Point?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
160                            'layer 1', "memory")
161        QgsProject.instance().addMapLayer(l1)
162        l2 = QgsVectorLayer("Polygon?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
163                            'lAyEr 2', "memory")
164        QgsProject.instance().addMapLayer(l2)
165        spy = QSignalSpy(m.layerChanged)
166
167        m.setLayer(l2)
168        self.assertEqual(len(spy), 1)
169        self.assertEqual(m.currentLayer(), l2)
170        m.setLayer(l1)
171        self.assertEqual(len(spy), 2)
172        self.assertEqual(m.currentLayer(), l1)
173        # no signal if same layer
174        m.setLayer(l1)
175        self.assertEqual(len(spy), 2)
176
177        m.setAllowEmptyLayer(True)
178        m.setLayer(None)
179        self.assertEqual(len(spy), 3)
180        self.assertIsNone(m.currentLayer())
181        self.assertFalse(m.currentText())
182        m.setLayer(None)
183        self.assertEqual(len(spy), 3)
184        self.assertIsNone(m.currentLayer())
185
186        m.setEditable(True)
187        m.setCurrentText('aaa')
188        self.assertIsNone(m.currentLayer())
189
190        m.setLayer(l1)
191        self.assertEqual(len(spy), 4)
192        self.assertEqual(m.currentLayer(), l1)
193
194    def testAdditionalLayers(self):
195        QgsProject.instance().clear()
196        l1 = create_layer('l1')
197        l2 = create_layer('l2')
198        QgsProject.instance().addMapLayers([l1, l2])
199        m = QgsMapLayerComboBox()
200        self.assertEqual(m.count(), 2)
201        l3 = create_layer('l3')
202        l4 = create_layer('l4')
203        m.setAdditionalLayers([l3, l4])
204        self.assertEqual(m.count(), 4)
205
206        m.setAdditionalItems(['a', 'b'])
207        self.assertEqual(m.count(), 6)
208        self.assertEqual(m.itemText(0), 'l1')
209        self.assertEqual(m.itemText(1), 'l2')
210        self.assertEqual(m.itemText(2), 'l3')
211        self.assertEqual(m.itemText(3), 'l4')
212        self.assertEqual(m.itemText(4), 'a')
213        self.assertEqual(m.itemText(5), 'b')
214
215        m.setAllowEmptyLayer(True)
216        self.assertEqual(m.count(), 7)
217        self.assertFalse(m.itemText(0))
218        self.assertEqual(m.itemText(1), 'l1')
219        self.assertEqual(m.itemText(2), 'l2')
220        self.assertEqual(m.itemText(3), 'l3')
221        self.assertEqual(m.itemText(4), 'l4')
222        self.assertEqual(m.itemText(5), 'a')
223        self.assertEqual(m.itemText(6), 'b')
224
225        l3.deleteLater()
226        QCoreApplication.sendPostedEvents(None, QEvent.DeferredDelete)
227        self.assertEqual(m.count(), 6)
228        self.assertFalse(m.itemText(0))
229        self.assertEqual(m.itemText(1), 'l1')
230        self.assertEqual(m.itemText(2), 'l2')
231        self.assertEqual(m.itemText(3), 'l4')
232        self.assertEqual(m.itemText(4), 'a')
233        self.assertEqual(m.itemText(5), 'b')
234
235        l5 = create_layer('l5')
236        l6 = create_layer('l6')
237        m.setAdditionalLayers([l5, l6, l4])
238        self.assertEqual(m.count(), 8)
239        self.assertFalse(m.itemText(0))
240        self.assertEqual(m.itemText(1), 'l1')
241        self.assertEqual(m.itemText(2), 'l2')
242        self.assertEqual(m.itemText(3), 'l4')
243        self.assertEqual(m.itemText(4), 'l5')
244        self.assertEqual(m.itemText(5), 'l6')
245        self.assertEqual(m.itemText(6), 'a')
246        self.assertEqual(m.itemText(7), 'b')
247
248        m.setAdditionalLayers([l5, l4])
249        self.assertEqual(m.count(), 7)
250        self.assertFalse(m.itemText(0))
251        self.assertEqual(m.itemText(1), 'l1')
252        self.assertEqual(m.itemText(2), 'l2')
253        self.assertEqual(m.itemText(3), 'l4')
254        self.assertEqual(m.itemText(4), 'l5')
255        self.assertEqual(m.itemText(5), 'a')
256        self.assertEqual(m.itemText(6), 'b')
257
258        QgsProject.instance().removeMapLayers([l1.id(), l2.id()])
259
260        self.assertEqual(m.count(), 5)
261        self.assertFalse(m.itemText(0))
262        self.assertEqual(m.itemText(1), 'l4')
263        self.assertEqual(m.itemText(2), 'l5')
264        self.assertEqual(m.itemText(3), 'a')
265        self.assertEqual(m.itemText(4), 'b')
266
267
268if __name__ == '__main__':
269    unittest.main()
270