1
# -*- coding: utf-8 -*-
3
@package core.layerlist
5
@brief Non GUI classes for layer management (so far used for class simplelmgr only)
10
- layerlist::LayerListToRendererConverter
12
(C) 2013 by the GRASS Development Team
14
This program is free software under the GNU General Public License
15
(>=v2). Read the file COPYING that comes with GRASS for details.
17
@author Anna Petrasova (kratochanna gmail.com)
20
from grass.script import core as gcore
23
class LayerList(object):
24
"""Non GUI class managing list of layers.
26
It provides API for handling layers. In the future,
27
a non GUI class (e.g. named LayerTree) which includes this API,
28
should be used for Layer Manager.
33
def GetSelectedLayers(self, activeOnly=True):
34
"""Returns list of selected layers.
36
:param bool activeOnly: return only active layers
39
for layer in self._list:
40
if layer.IsSelected():
41
if activeOnly and layer.IsActive():
47
def GetSelectedLayer(self, activeOnly=False):
48
"""Returns selected layer or None when there is no selected layer.
50
:param bool activeOnly: return only active layers
52
layers = self.GetSelectedLayers(activeOnly)
57
def GetActiveLayers(self):
58
"""Returns list of active layers."""
59
return [layer for layer in self._list if layer.IsActive()]
61
def GetLayersByTypes(self, mapTypes):
62
"""Returns layers by types.
64
:param mapTypes: list of types
67
for layer in self._list:
68
if layer.mapType in mapTypes:
72
def AddNewLayer(self, name, mapType, cmd, active=True, hidden=False,
73
opacity=1, label=None, pos=0):
74
"""Creates new layer and adds it to the list (insert to the first position).
76
:param ltype: layer type (raster, vector, 3d-raster, ...)
77
:param cmd: command (given as a list)
78
:param active: if True layer is active
79
:param hidden: if True layer is hidden
80
:param opacity: layer opacity level (0 - 100)
81
:param name: layer name (set automatically from cmd)
82
:param label: layer label (set automatically from name)
83
:param pos: add layer to position
87
layer.mapType = mapType
90
layer.opacity = opacity
95
self._list.insert(pos, layer)
98
def AddLayer(self, layer):
99
"""Adds a layer to the layer list.
101
self._list.insert(0, layer)
103
def InsertLayer(self, index, layer):
104
"""Adds a layer to the layer list.
106
self._list.insert(index, layer)
108
def RemoveLayer(self, layer):
110
self._list.remove(layer)
112
def GetLayerByData(self, key, value):
113
"""Returns layer with specified.
116
Returns only one layer. This might change.
119
Avoid using this method, it might be removed in the future.
121
raise NotImplementedError()
123
def GetLayerIndex(self, layer):
124
"""Get index of layer."""
125
return self._list.index(layer)
127
def MoveLayerUp(self, layer):
128
"""Moves layer up (1 step)."""
129
idx = self._list.index(layer)
131
lr = self._list.pop(idx)
132
self._list.insert(idx - 1, lr)
134
def MoveLayerDown(self, layer):
135
"""Moves layer down (1 step)."""
136
idx = self._list.index(layer)
137
if idx < len(self._list) - 1:
138
lr = self._list.pop(idx)
139
self._list.insert(idx + 1, lr)
142
for layer in self._list:
145
def __getitem__(self, index):
146
return self._list[index]
149
return len(self._list)
153
for layer in self._list:
154
text += str(layer.name) + '\n'
159
"""Object representing layer.
161
Properties of the object are checked during setting.
162
Map types can be extended if needed.
165
>>> layer.selected = True
166
>>> layer.IsSelected()
168
>>> layer.opacity = 0.1
169
Traceback (most recent call last):
171
ValueError: Opacity must be an integer between 0 and 100, not 0.1.
172
>>> layer.name = 'blablabla'
173
Traceback (most recent call last):
175
ValueError: To set layer name, the type of layer must be specified.
176
>>> layer.mapType = 'raster'
177
>>> layer.name = 'blablabla'
178
Traceback (most recent call last):
180
ValueError: Map <blablabla> not found.
189
self._selected = False
192
self._initialized = False
194
self._mapTypes = ['raster', 'vector', 'raster_3d', 'rgb']
195
self._internalTypes = {'raster': 'cell',
197
'raster_3d': 'grid3',
203
def SetName(self, name):
204
"""Sets name of the layer.
206
It checks the name of the layer by g.findfile
207
(raises ValueError if map does not exist).
208
Therefore map type has to be set first.
211
fullName = name.split('@')
212
if len(fullName) == 1 and self._mapType != 'rgb': # skip checking rgb maps for now
213
if self._mapType is None:
214
raise ValueError("To set layer name, the type of layer must be specified.")
216
res = gcore.find_file(name=fullName,
217
element=self._internalTypes[self._mapType])
218
if not res['mapset']:
219
raise ValueError("Map <{name}> not found.".format(name=name))
220
self._name = name + '@' + res['mapset']
225
name = property(fget=GetName, fset=SetName)
230
def SetLabel(self, label):
233
label = property(fget=GetLabel, fset=SetLabel)
238
def SetCmd(self, cmd):
241
cmd = property(fget=GetCmd, fset=SetCmd)
243
def GetMapType(self):
246
def SetMapType(self, mapType):
247
"""Sets map type of the layer.
249
:param mapType: can be 'raster', 'vector', 'raster_3d'
251
if mapType not in self._mapTypes:
252
raise ValueError("Wrong map type used: {mtype}".format(mtype=mapType))
254
self._mapType = mapType
256
mapType = property(fget=GetMapType, fset=SetMapType)
258
def GetOpacity(self):
259
"""Returns opacity value.
261
:return: opacity as float between 0 and 1
265
def SetOpacity(self, opacity):
266
"""Sets opacity of the layer.
268
:param float opacity: value between 0 and 1
270
if not (0 <= opacity <= 1):
271
raise ValueError("Opacity value must be between 0 and 1, not {op}.".format(op=opacity))
272
self._opacity = opacity
274
opacity = property(fget=GetOpacity, fset=SetOpacity)
276
def Select(self, select=True):
277
self._selected = select
279
def IsSelected(self):
280
return self._selected
282
selected = property(fget=IsSelected, fset=Select)
287
def Activate(self, active=True):
288
"""Sets if layer is active (checked)."""
289
self._active = active
291
active = property(fget=IsActive, fset=Activate)
296
def Hide(self, hide=True):
297
"""Sets if layer is hidden."""
300
hidden = property(fget=IsHidden, fset=Hide)
303
class LayerListToRendererConverter:
304
"""Help class for converting LayerList layers into renderer list (Map)"""
305
def __init__(self, renderer):
308
:param layerList: instance of LayerList
309
:param renderer: instance of Map
311
self._renderer = renderer
313
def _getRendererLayer(self, index):
314
"""Returns corresponding layer of renderer."""
315
rLayers = self._renderer.GetListOfLayers()
316
index = len(rLayers) - index - 1
317
return rLayers[index]
319
def ConvertAll(self, layerList):
320
"""Removes all layers in Map and adds new layers form layerList.
321
It's not meant for continuous update because everything is rerendered.
323
self._renderer.DeleteAllLayers()
324
for layer in reversed(layerList):
325
self.AddLayer(index=-1, layer=layer)
327
def ChangeLayerOpacity(self, index, layer):
328
"""Changes layer opacity in renderer."""
329
rLayer = self._getRendererLayer(index)
330
self._renderer.ChangeLayer(rLayer, opacity=layer.opacity)
332
def ChangeLayerCmd(self, index, layer):
333
"""Changes layer cmd in renderer."""
334
rLayer = self._getRendererLayer(index)
335
self._renderer.ChangeLayer(rLayer, command=layer.cmd)
337
def ChangeLayerActive(self, index, layer):
338
"""Changes layer active state in renderer."""
339
rLayer = self._getRendererLayer(index)
340
self._renderer.ChangeLayer(rLayer, active=layer.active)
342
def MoveLayerUp(self, index):
343
"""Moves layer up in renderer."""
344
rLayers = self._renderer.GetListOfLayers()
345
index = len(rLayers) - index - 1
346
rLayer = rLayers.pop(index)
347
rLayers.insert(index + 1, rLayer)
348
self._renderer.SetLayers(rLayers)
350
def MoveLayerDown(self, index):
351
"""Moves layer down in renderer."""
352
rLayers = self._renderer.GetListOfLayers()
353
index = len(rLayers) - index - 1
354
rLayer = rLayers.pop(index)
355
rLayers.insert(index - 1, rLayer)
356
self._renderer.SetLayers(rLayers)
358
def AddLayer(self, index, layer):
359
"""Adds layer to renderer (prepends)."""
361
if layer.mapType == 'raster':
363
elif layer.mapType == 'vector':
365
elif layer.mapType == 'raster_3d':
366
mapType = '3d-raster'
367
elif layer.mapType == 'rgb':
369
self._renderer.AddLayer(ltype=mapType, command=layer.cmd,
370
name=layer.name, active=layer.active,
371
hidden=False, opacity=layer.opacity,
374
def RemoveLayer(self, index):
375
"""Removes layer from renderer."""
376
self._renderer.DeleteLayer(self._getRendererLayer(index))