gselect.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. """
  2. MODULE: gselect
  3. CLASSES:
  4. * Select
  5. * TreeCrtlComboPopup
  6. PURPOSE: Custon control that selects GRASS GIS elements
  7. AUTHORS: The GRASS Development Team. Michael Barton & Martin Landa
  8. COPYRIGHT: (C) 2007 by the GRASS Development Team
  9. This program is free software under the GNU General Public
  10. License (>=v2). Read the file COPYING that comes with GRASS
  11. for details.
  12. """
  13. import os
  14. import sys
  15. import wx
  16. import wx.combo
  17. import globalvar
  18. import gcmd
  19. from preferences import globalSettings as UserSettings
  20. class Select(wx.combo.ComboCtrl):
  21. def __init__(self, parent, id, size,
  22. type, multiple=False, mapsets=None, exceptOf=[]):
  23. """
  24. Custom control to create a ComboBox with a tree control
  25. to display and select GIS elements within acessible mapsets.
  26. Elements can be selected with mouse. Can allow multiple selections, when
  27. argument multiple=True. Multiple selections are separated by commas.
  28. """
  29. wx.combo.ComboCtrl.__init__(self, parent=parent, id=id, size=size)
  30. self.tcp = TreeCtrlComboPopup()
  31. self.SetPopupControl(self.tcp)
  32. self.SetPopupExtents(0,100)
  33. self.tcp.GetElementList(type, mapsets, exceptOf)
  34. self.tcp.SetMultiple(multiple)
  35. def SetElementList(self, type):
  36. self.tcp.seltree.DeleteAllItems()
  37. self.tcp.GetElementList(type)
  38. class TreeCtrlComboPopup(wx.combo.ComboPopup):
  39. """
  40. Create a tree ComboBox for selecting maps and other GIS elements
  41. in accessible mapsets within the current location
  42. """
  43. # overridden ComboPopup methods
  44. def Init(self):
  45. self.value = [] # for multiple is False -> len(self.value) in [0,1]
  46. self.curitem = None
  47. self.multiple = False
  48. def Create(self, parent):
  49. self.seltree = wx.TreeCtrl(parent, style=wx.TR_HIDE_ROOT
  50. |wx.TR_HAS_BUTTONS
  51. |wx.TR_SINGLE
  52. |wx.TR_LINES_AT_ROOT
  53. |wx.SIMPLE_BORDER
  54. |wx.TR_FULL_ROW_HIGHLIGHT)
  55. self.seltree.Bind(wx.EVT_MOTION, self.OnMotion)
  56. self.seltree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  57. self.seltree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.mapsetExpanded)
  58. self.seltree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.mapsetCollapsed)
  59. self.seltree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.mapsetActivated)
  60. self.seltree.Bind(wx.EVT_TREE_SEL_CHANGED, self.mapsetSelected)
  61. # the following dummy handler are needed to keep tree events from propagating up to
  62. # the parent GIS Manager layer tree
  63. def mapsetExpanded(self, event):
  64. pass
  65. def mapsetCollapsed(self, event):
  66. pass
  67. def mapsetActivated(self, event):
  68. pass
  69. def mapsetSelected(self, event):
  70. pass
  71. # end of dummy events
  72. def GetControl(self):
  73. return self.seltree
  74. def GetStringValue(self):
  75. str = ""
  76. for value in self.value:
  77. str += self.seltree.GetItemText(value) + ","
  78. str = str.rstrip(',')
  79. return str
  80. def OnPopup(self):
  81. """Limited only for first selected"""
  82. if len(self.value) > 0:
  83. self.seltree.EnsureVisible(self.value[0])
  84. self.seltree.SelectItem(self.value[0])
  85. def SetStringValue(self, value):
  86. # this assumes that item strings are unique...
  87. root = self.seltree.GetRootItem()
  88. if not root:
  89. return
  90. found = self.FindItem(root, value)
  91. if found:
  92. self.value.append(found)
  93. self.seltree.SelectItem(found)
  94. def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
  95. return wx.Size(minWidth, min(200, maxHeight))
  96. def GetElementList(self, element, mapsets=None, exceptOf=[]):
  97. """
  98. Get list of GIS elements in accessible mapsets and display as tree
  99. with all relevant elements displayed beneath each mapset branch
  100. """
  101. # get current mapset
  102. cmdlist = ['g.gisenv', 'get=MAPSET']
  103. curr_mapset = gcmd.Command(cmdlist).ReadStdOutput()[0]
  104. # list of mapsets in current location
  105. if mapsets is None:
  106. mapsets = UserSettings.Get(group='general', key='mapsetPath', subkey='value', internal=True)
  107. # map element types to g.mlist types
  108. elementdict = {'cell':'rast',
  109. 'raster':'rast',
  110. 'rast':'rast',
  111. 'raster files':'rast',
  112. 'grid3':'rast3d',
  113. 'rast3d':'rast3d',
  114. 'raster3D':'rast3d',
  115. 'raster3D files':'rast3d',
  116. 'vector':'vect',
  117. 'vect':'vect',
  118. 'binary vector files':'vect',
  119. 'dig':'oldvect',
  120. 'oldvect':'oldvect',
  121. 'old vector':'oldvect',
  122. 'dig_ascii':'asciivect',
  123. 'asciivect':'asciivect',
  124. 'asciivector':'asciivect',
  125. 'ascii vector files':'asciivect',
  126. 'icons':'icon',
  127. 'icon':'icon',
  128. 'paint icon files':'icon',
  129. 'paint/labels':'labels',
  130. 'labels':'labels',
  131. 'label':'labels',
  132. 'paint label files':'labels',
  133. 'site_lists':'sites',
  134. 'sites':'sites',
  135. 'site list':'sites',
  136. 'site list files':'sites',
  137. 'windows':'region',
  138. 'region':'region',
  139. 'region definition':'region',
  140. 'region definition files':'region',
  141. 'windows3d':'region3d',
  142. 'region3d':'region3d',
  143. 'region3D definition':'region3d',
  144. 'region3D definition files':'region3d',
  145. 'group':'group',
  146. 'imagery group':'group',
  147. 'imagery group files':'group',
  148. '3d.view':'3dview',
  149. '3dview':'3dview',
  150. '3D viewing parameters':'3dview',
  151. '3D view parameters':'3dview'}
  152. if element not in elementdict:
  153. self.AddItem(_('Not selectable element'))
  154. return
  155. # get directory tree nodes
  156. # reorder mapsets based on search path (TODO)
  157. for i in range(len(mapsets)):
  158. if i > 0 and mapsets[i] == curr_mapset:
  159. mapsets[i] = mapsets[0]
  160. mapsets[0] = curr_mapset
  161. for dir in mapsets:
  162. dir_node = self.AddItem('Mapset: '+dir)
  163. self.seltree.SetItemTextColour(dir_node,wx.Colour(50,50,200))
  164. try:
  165. cmdlist = ['g.mlist', 'type=%s' % elementdict[element], 'mapset=%s' % dir]
  166. elem_list = gcmd.Command(cmdlist).ReadStdOutput()
  167. elem_list.sort()
  168. for elem in elem_list:
  169. if elem != '':
  170. fullqElem = elem + '@' + dir
  171. if len(exceptOf) > 0 and fullqElem in exceptOf:
  172. continue
  173. self.AddItem(fullqElem, parent=dir_node)
  174. except:
  175. continue
  176. if self.seltree.ItemHasChildren(dir_node):
  177. self.seltree.Expand(dir_node)
  178. # helpers
  179. def FindItem(self, parentItem, text):
  180. item, cookie = self.seltree.GetFirstChild(parentItem)
  181. while item:
  182. if self.seltree.GetItemText(item) == text:
  183. return item
  184. if self.seltree.ItemHasChildren(item):
  185. item = self.FindItem(item, text)
  186. item, cookie = self.seltree.GetNextChild(parentItem, cookie)
  187. return wx.TreeItemId();
  188. def AddItem(self, value, parent=None):
  189. if not parent:
  190. root = self.seltree.GetRootItem()
  191. if not root:
  192. root = self.seltree.AddRoot("<hidden root>")
  193. parent = root
  194. item = self.seltree.AppendItem(parent, text=value)
  195. return item
  196. def OnMotion(self, evt):
  197. # have the selection follow the mouse, like in a real combobox
  198. item, flags = self.seltree.HitTest(evt.GetPosition())
  199. if item and flags & wx.TREE_HITTEST_ONITEMLABEL:
  200. self.seltree.SelectItem(item)
  201. self.curitem = item
  202. evt.Skip()
  203. def OnLeftDown(self, evt):
  204. # do the combobox selection
  205. item, flags = self.seltree.HitTest(evt.GetPosition())
  206. if item and flags & wx.TREE_HITTEST_ONITEMLABEL:
  207. self.curitem = item
  208. if self.seltree.GetRootItem() == self.seltree.GetItemParent(item):
  209. self.value = [] # cannot select mapset item
  210. else:
  211. if self.multiple is True:
  212. self.value.append(item)
  213. else:
  214. self.value = [item, ]
  215. self.Dismiss()
  216. evt.Skip()
  217. def SetMultiple(self, value):
  218. """Select multiple items?"""
  219. self.multiple = value