gselect.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. """!
  2. @package gselect
  3. @brief Custom control that selects elements
  4. Classes:
  5. - Select
  6. - VectorSelect
  7. - TreeCrtlComboPopup
  8. - VectorDBInfo
  9. - LayerSelect
  10. - LayerNameSelect
  11. - DriverSelect
  12. - DatabaseSelect
  13. - ColumnSelect
  14. - LocationSelect
  15. - MapsetSelect
  16. (C) 2007-2009 by the GRASS Development Team This program is free
  17. software under the GNU General Public License (>=v2). Read the file
  18. COPYING that comes with GRASS for details.
  19. @author Michael Barton
  20. @author Martin Landa <landa.martin gmail.com>
  21. """
  22. import os
  23. import sys
  24. import wx
  25. import wx.combo
  26. import grass.script as grass
  27. import globalvar
  28. import gcmd
  29. import utils
  30. from preferences import globalSettings as UserSettings
  31. class Select(wx.combo.ComboCtrl):
  32. def __init__(self, parent, id, size = globalvar.DIALOG_GSELECT_SIZE,
  33. type = None, multiple = False, mapsets = None, exclude = [],
  34. updateOnPopup = True):
  35. """!Custom control to create a ComboBox with a tree control
  36. to display and select GIS elements within acessible mapsets.
  37. Elements can be selected with mouse. Can allow multiple selections, when
  38. argument multiple=True. Multiple selections are separated by commas.
  39. """
  40. wx.combo.ComboCtrl.__init__(self, parent=parent, id=id, size=size)
  41. self.GetChildren()[0].SetName("Select")
  42. self.GetChildren()[0].type = type
  43. self.tcp = TreeCtrlComboPopup()
  44. self.SetPopupControl(self.tcp)
  45. self.SetPopupExtents(0,100)
  46. if type:
  47. self.tcp.SetData(type = type, mapsets = mapsets,
  48. exclude = exclude, multiple = multiple,
  49. updateOnPopup = updateOnPopup)
  50. def SetElementList(self, type, mapsets = None, exclude = []):
  51. """!Set element list
  52. @param type GIS element type
  53. @param mapsets list of acceptable mapsets (None for all in search path)
  54. @param exclude list of GIS elements to be excluded
  55. """
  56. self.tcp.SetData(type = type, mapsets = mapsets,
  57. exclude = exclude)
  58. def GetElementList(self):
  59. """!Load elements"""
  60. self.tcp.GetElementList()
  61. class VectorSelect(Select):
  62. def __init__(self, parent, ftype, **kwargs):
  63. """!Custom to create a ComboBox with a tree control to display and
  64. select vector maps. Control allows to filter vector maps. If you
  65. don't need this feature use Select class instead
  66. @ftype filter vector maps based on feature type
  67. """
  68. Select.__init__(self, parent = parent, id = wx.ID_ANY,
  69. type = 'vector', **kwargs)
  70. self.ftype = ftype
  71. # remove vector maps which do not contain given feature type
  72. self.tcp.SetFilter(self.__isElement)
  73. def __isElement(self, vectorName):
  74. """!Check if element should be filtered out"""
  75. try:
  76. if int(grass.vector_info_topo(vectorName)[self.ftype]) < 1:
  77. return False
  78. except KeyError:
  79. return False
  80. return True
  81. class TreeCtrlComboPopup(wx.combo.ComboPopup):
  82. """!Create a tree ComboBox for selecting maps and other GIS elements
  83. in accessible mapsets within the current location
  84. """
  85. # overridden ComboPopup methods
  86. def Init(self):
  87. self.value = [] # for multiple is False -> len(self.value) in [0,1]
  88. self.curitem = None
  89. self.multiple = False
  90. self.type = None
  91. self.mapsets = []
  92. self.exclude = []
  93. self.SetFilter(None)
  94. def Create(self, parent):
  95. self.seltree = wx.TreeCtrl(parent, style=wx.TR_HIDE_ROOT
  96. |wx.TR_HAS_BUTTONS
  97. |wx.TR_SINGLE
  98. |wx.TR_LINES_AT_ROOT
  99. |wx.SIMPLE_BORDER
  100. |wx.TR_FULL_ROW_HIGHLIGHT)
  101. self.seltree.Bind(wx.EVT_MOTION, self.OnMotion)
  102. self.seltree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  103. self.seltree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.mapsetExpanded)
  104. self.seltree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.mapsetCollapsed)
  105. self.seltree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.mapsetActivated)
  106. self.seltree.Bind(wx.EVT_TREE_SEL_CHANGED, self.mapsetSelected)
  107. self.seltree.Bind(wx.EVT_TREE_DELETE_ITEM, lambda x: None)
  108. # the following dummy handler are needed to keep tree events from propagating up to
  109. # the parent GIS Manager layer tree
  110. def mapsetExpanded(self, event):
  111. pass
  112. def mapsetCollapsed(self, event):
  113. pass
  114. def mapsetActivated(self, event):
  115. pass
  116. def mapsetSelected(self, event):
  117. pass
  118. # end of dummy events
  119. def GetControl(self):
  120. return self.seltree
  121. def GetStringValue(self):
  122. str = ""
  123. for value in self.value:
  124. str += value + ","
  125. str = str.rstrip(',')
  126. return str
  127. def SetFilter(self, filter):
  128. """!Set filter for GIS elements, see e.g. VectorSelect"""
  129. self.filterElements = filter
  130. def OnPopup(self, force = False):
  131. """!Limited only for first selected"""
  132. if not force and not self.updateOnPopup:
  133. return
  134. self.GetElementList()
  135. def GetElementList(self):
  136. """!Get filtered list of GIS elements in accessible mapsets
  137. and display as tree with all relevant elements displayed
  138. beneath each mapset branch
  139. """
  140. # update list
  141. self.seltree.DeleteAllItems()
  142. self._getElementList(self.type, self.mapsets, self.exclude)
  143. if len(self.value) > 0:
  144. root = self.seltree.GetRootItem()
  145. if not root:
  146. return
  147. item = self.FindItem(root, self.value[0])
  148. try:
  149. self.seltree.EnsureVisible(item)
  150. self.seltree.SelectItem(item)
  151. except:
  152. pass
  153. def SetStringValue(self, value):
  154. # this assumes that item strings are unique...
  155. root = self.seltree.GetRootItem()
  156. if not root:
  157. return
  158. found = self.FindItem(root, value)
  159. if found:
  160. self.value.append(found)
  161. self.seltree.SelectItem(found)
  162. def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
  163. return wx.Size(minWidth, min(200, maxHeight))
  164. def _getElementList(self, element, mapsets=None, exclude=[]):
  165. """!Get list of GIS elements in accessible mapsets and display as tree
  166. with all relevant elements displayed beneath each mapset branch
  167. @param element GIS element
  168. @param mapsets list of acceptable mapsets (None for all mapsets in search path)
  169. @param exclude list of GIS elements to be excluded
  170. """
  171. # get current mapset
  172. curr_mapset = grass.gisenv()['MAPSET']
  173. # list of mapsets in current location
  174. if mapsets is None:
  175. mapsets = utils.ListOfMapsets()
  176. # map element types to g.mlist types
  177. elementdict = {'cell':'rast',
  178. 'raster':'rast',
  179. 'rast':'rast',
  180. 'raster files':'rast',
  181. 'grid3':'rast3d',
  182. 'rast3d':'rast3d',
  183. 'raster3D':'rast3d',
  184. 'raster3D files':'rast3d',
  185. 'vector':'vect',
  186. 'vect':'vect',
  187. 'binary vector files':'vect',
  188. 'dig':'oldvect',
  189. 'oldvect':'oldvect',
  190. 'old vector':'oldvect',
  191. 'dig_ascii':'asciivect',
  192. 'asciivect':'asciivect',
  193. 'asciivector':'asciivect',
  194. 'ascii vector files':'asciivect',
  195. 'icons':'icon',
  196. 'icon':'icon',
  197. 'paint icon files':'icon',
  198. 'paint/labels':'labels',
  199. 'labels':'labels',
  200. 'label':'labels',
  201. 'paint label files':'labels',
  202. 'site_lists':'sites',
  203. 'sites':'sites',
  204. 'site list':'sites',
  205. 'site list files':'sites',
  206. 'windows':'region',
  207. 'region':'region',
  208. 'region definition':'region',
  209. 'region definition files':'region',
  210. 'windows3d':'region3d',
  211. 'region3d':'region3d',
  212. 'region3D definition':'region3d',
  213. 'region3D definition files':'region3d',
  214. 'group':'group',
  215. 'imagery group':'group',
  216. 'imagery group files':'group',
  217. '3d.view':'3dview',
  218. '3dview':'3dview',
  219. '3D viewing parameters':'3dview',
  220. '3D view parameters':'3dview'}
  221. if element not in elementdict:
  222. self.AddItem(_('Not selectable element'))
  223. return
  224. # get directory tree nodes
  225. # reorder mapsets based on search path (TODO)
  226. for i in range(len(mapsets)):
  227. if i > 0 and mapsets[i] == curr_mapset:
  228. mapsets[i] = mapsets[0]
  229. mapsets[0] = curr_mapset
  230. if globalvar.have_mlist:
  231. filesdict = grass.mlist_grouped(elementdict[element])
  232. else:
  233. filesdict = grass.list_grouped(elementdict[element])
  234. first_dir = None
  235. for dir in mapsets:
  236. dir_node = self.AddItem('Mapset: ' + dir)
  237. if not first_dir:
  238. first_dir = dir_node
  239. self.seltree.SetItemTextColour(dir_node, wx.Colour(50, 50, 200))
  240. try:
  241. elem_list = filesdict[dir]
  242. elem_list.sort(key=str.lower)
  243. for elem in elem_list:
  244. if elem != '':
  245. fullqElem = elem + '@' + dir
  246. if len(exclude) > 0 and fullqElem in exclude:
  247. continue
  248. if self.filterElements:
  249. if self.filterElements(fullqElem):
  250. self.AddItem(fullqElem, parent=dir_node)
  251. else:
  252. self.AddItem(fullqElem, parent=dir_node)
  253. except:
  254. continue
  255. if self.seltree.ItemHasChildren(dir_node):
  256. sel = UserSettings.Get(group='general', key='elementListExpand',
  257. subkey='selection')
  258. collapse = True
  259. if sel == 0: # collapse all except PERMANENT and current
  260. if dir in ('PERMANENT', curr_mapset):
  261. collapse = False
  262. elif sel == 1: # collapse all except PERMANENT
  263. if dir == 'PERMANENT':
  264. collapse = False
  265. elif sel == 2: # collapse all except current
  266. if dir == curr_mapset:
  267. collapse = False
  268. elif sel == 3: # collapse all
  269. pass
  270. elif sel == 4: # expand all
  271. collapse = False
  272. if collapse:
  273. self.seltree.Collapse(dir_node)
  274. else:
  275. self.seltree.Expand(dir_node)
  276. if first_dir:
  277. # select first mapset (MSW hack)
  278. self.seltree.SelectItem(first_dir)
  279. # helpers
  280. def FindItem(self, parentItem, text):
  281. item, cookie = self.seltree.GetFirstChild(parentItem)
  282. while item:
  283. if self.seltree.GetItemText(item) == text:
  284. return item
  285. if self.seltree.ItemHasChildren(item):
  286. item = self.FindItem(item, text)
  287. item, cookie = self.seltree.GetNextChild(parentItem, cookie)
  288. return wx.TreeItemId()
  289. def AddItem(self, value, parent=None):
  290. if not parent:
  291. root = self.seltree.GetRootItem()
  292. if not root:
  293. root = self.seltree.AddRoot("<hidden root>")
  294. parent = root
  295. item = self.seltree.AppendItem(parent, text=value)
  296. return item
  297. def OnMotion(self, evt):
  298. # have the selection follow the mouse, like in a real combobox
  299. item, flags = self.seltree.HitTest(evt.GetPosition())
  300. if item and flags & wx.TREE_HITTEST_ONITEMLABEL:
  301. self.seltree.SelectItem(item)
  302. self.curitem = item
  303. evt.Skip()
  304. def OnLeftDown(self, evt):
  305. # do the combobox selection
  306. item, flags = self.seltree.HitTest(evt.GetPosition())
  307. if item and flags & wx.TREE_HITTEST_ONITEMLABEL:
  308. self.curitem = item
  309. if self.seltree.GetRootItem() == self.seltree.GetItemParent(item):
  310. self.value = [] # cannot select mapset item
  311. else:
  312. if self.multiple is True:
  313. # text item should be unique
  314. self.value.append(self.seltree.GetItemText(item))
  315. else:
  316. self.value = [self.seltree.GetItemText(item), ]
  317. self.Dismiss()
  318. evt.Skip()
  319. def SetData(self, **kargs):
  320. """!Set object properties"""
  321. if kargs.has_key('type'):
  322. self.type = kargs['type']
  323. if kargs.has_key('mapsets'):
  324. self.mapsets = kargs['mapsets']
  325. if kargs.has_key('exclude'):
  326. self.exclude = kargs['exclude']
  327. if kargs.has_key('multiple'):
  328. self.multiple = kargs['multiple']
  329. if kargs.has_key('updateOnPopup'):
  330. self.updateOnPopup = kargs['updateOnPopup']
  331. class VectorDBInfo:
  332. """!Class providing information about attribute tables
  333. linked to a vector map"""
  334. def __init__(self, map):
  335. self.map = map
  336. # dictionary of layer number and associated (driver, database, table)
  337. self.layers = {}
  338. # dictionary of table and associated columns (type, length, values, ids)
  339. self.tables = {}
  340. if not self.__CheckDBConnection(): # -> self.layers
  341. return
  342. self.__DescribeTables() # -> self.tables
  343. def __CheckDBConnection(self):
  344. """!Check DB connection"""
  345. nuldev = file(os.devnull, 'w+')
  346. self.layers = grass.vector_db(map=self.map, stderr=nuldev)
  347. nuldev.close()
  348. if (len(self.layers.keys()) == 0):
  349. return False
  350. return True
  351. def __DescribeTables(self):
  352. """!Describe linked tables"""
  353. for layer in self.layers.keys():
  354. # determine column names and types
  355. table = self.layers[layer]["table"]
  356. columns = {} # {name: {type, length, [values], [ids]}}
  357. i = 0
  358. for item in grass.db_describe(table = self.layers[layer]["table"],
  359. driver = self.layers[layer]["driver"],
  360. database = self.layers[layer]["database"])['cols']:
  361. name, type, length = item
  362. # FIXME: support more datatypes
  363. if type.lower() == "integer":
  364. ctype = int
  365. elif type.lower() == "double precision":
  366. ctype = float
  367. else:
  368. ctype = str
  369. columns[name.strip()] = { 'index' : i,
  370. 'type' : type.lower(),
  371. 'ctype' : ctype,
  372. 'length' : int(length),
  373. 'values' : [],
  374. 'ids' : []}
  375. i += 1
  376. # check for key column
  377. # v.db.connect -g/p returns always key column name lowercase
  378. if self.layers[layer]["key"] not in columns.keys():
  379. for col in columns.keys():
  380. if col.lower() == self.layers[layer]["key"]:
  381. self.layers[layer]["key"] = col.upper()
  382. break
  383. self.tables[table] = columns
  384. return True
  385. def Reset(self):
  386. """!Reset"""
  387. for layer in self.layers:
  388. table = self.layers[layer]["table"] # get table desc
  389. columns = self.tables[table]
  390. for name in self.tables[table].keys():
  391. self.tables[table][name]['values'] = []
  392. self.tables[table][name]['ids'] = []
  393. def GetName(self):
  394. """!Get vector name"""
  395. return self.map
  396. def GetKeyColumn(self, layer):
  397. """!Get key column of given layer
  398. @param layer vector layer number
  399. """
  400. return self.layers[layer]['key']
  401. def GetTable(self, layer):
  402. """!Get table name of given layer
  403. @param layer vector layer number
  404. """
  405. return self.layers[layer]['table']
  406. def GetDbSettings(self, layer):
  407. """!Get database settins
  408. @param layer layer number
  409. @return (driver, database)
  410. """
  411. return self.layers[layer]['driver'], self.layers[layer]['database']
  412. def GetTableDesc(self, table):
  413. """!Get table columns
  414. @param table table name
  415. """
  416. return self.tables[table]
  417. class LayerSelect(wx.Choice):
  418. def __init__(self, parent, id = wx.ID_ANY,
  419. size=globalvar.DIALOG_LAYER_SIZE,
  420. vector = None, choices = [], all = False, default = None):
  421. """!Creates widget for selecting vector map layer numbers
  422. @param vector vector map name or None
  423. @param choices list of predefined choices
  424. @param all adds layer '-1' (e.g., for d.vect)
  425. @param default default layer number
  426. """
  427. super(LayerSelect, self).__init__(parent, id, size = size,
  428. choices = choices)
  429. self.all = all
  430. self.SetName("LayerSelect")
  431. # default value
  432. self.default = default
  433. if len(choices) > 1:
  434. return
  435. if vector:
  436. self.InsertLayers(vector)
  437. else:
  438. if all:
  439. self.SetItems(['-1', '1'])
  440. else:
  441. self.SetItems(['1'])
  442. self.SetStringSelection('1')
  443. def InsertLayers(self, vector):
  444. """!Insert layers for a vector into the layer combobox"""
  445. layerchoices = utils.GetVectorNumberOfLayers(vector)
  446. if self.all:
  447. layerchoices.insert(0, '-1')
  448. if len(layerchoices) > 1:
  449. self.SetItems(layerchoices)
  450. self.SetStringSelection('1')
  451. else:
  452. self.SetItems(['1'])
  453. self.SetStringSelection('1')
  454. if self.default:
  455. self.SetStringSelection(str(self.default))
  456. class LayerNameSelect(wx.ComboBox):
  457. def __init__(self, parent, id = wx.ID_ANY,
  458. size = globalvar.DIALOG_COMBOBOX_SIZE,
  459. vector = None, dsn = None):
  460. """!Creates combo box for selecting vector map layer names
  461. @param vector vector map name (native or connected via v.external)
  462. @param dsn OGR data source name
  463. """
  464. super(LayerNameSelect, self).__init__(parent, id, size = size)
  465. self.SetName("LayerNameSelect")
  466. if vector:
  467. # -> native
  468. self.InsertLayers(vector = vector)
  469. elif dsn:
  470. self.InsertLayers(dsn = dsn)
  471. def InsertLayers(self, vector = None, dsn = None):
  472. """!Insert layers for a vector into the layer combobox
  473. @todo Implement native format
  474. @param vector vector map name (native or connected via v.external)
  475. @param dsn OGR data source name
  476. """
  477. layers = list()
  478. if vector:
  479. # TODO
  480. pass
  481. elif dsn:
  482. ret = gcmd.RunCommand('v.in.ogr',
  483. read = True,
  484. quiet = True,
  485. flags = 'l',
  486. dsn = dsn)
  487. if ret:
  488. layers = ret.splitlines()
  489. self.SetItems(layers)
  490. class DriverSelect(wx.ComboBox):
  491. """!Creates combo box for selecting database driver.
  492. """
  493. def __init__(self, parent, choices, value,
  494. id=wx.ID_ANY, pos=wx.DefaultPosition,
  495. size=globalvar.DIALOG_LAYER_SIZE, **kargs):
  496. super(DriverSelect, self).__init__(parent, id, value, pos, size,
  497. choices, style=wx.CB_READONLY)
  498. self.SetName("DriverSelect")
  499. self.SetStringSelection(value)
  500. class DatabaseSelect(wx.TextCtrl):
  501. """!Creates combo box for selecting database driver.
  502. """
  503. def __init__(self, parent, value='',
  504. id=wx.ID_ANY, pos=wx.DefaultPosition,
  505. size=globalvar.DIALOG_TEXTCTRL_SIZE, **kargs):
  506. super(DatabaseSelect, self).__init__(parent, id, value, pos, size)
  507. self.SetName("DatabaseSelect")
  508. class TableSelect(wx.ComboBox):
  509. """!Creates combo box for selecting attribute tables from the database
  510. """
  511. def __init__(self, parent,
  512. id=wx.ID_ANY, value='', pos=wx.DefaultPosition,
  513. size=globalvar.DIALOG_COMBOBOX_SIZE,
  514. choices=[]):
  515. super(TableSelect, self).__init__(parent, id, value, pos, size, choices,
  516. style=wx.CB_READONLY)
  517. self.SetName("TableSelect")
  518. if not choices:
  519. self.InsertTables()
  520. def InsertTables(self, driver=None, database=None):
  521. """!Insert attribute tables into combobox"""
  522. items = []
  523. if not driver or not database:
  524. connect = grass.db_connection()
  525. driver = connect['driver']
  526. database = connect['database']
  527. ret = gcmd.RunCommand('db.tables',
  528. flags = 'p',
  529. read = True,
  530. driver = driver,
  531. database = database)
  532. if ret:
  533. for table in ret.splitlines():
  534. items.append(table)
  535. self.SetItems(items)
  536. self.SetValue('')
  537. class ColumnSelect(wx.ComboBox):
  538. """
  539. Creates combo box for selecting columns in the attribute table for a vector.
  540. The 'layer' terminology is likely to change for GRASS 7
  541. """
  542. def __init__(self, parent,
  543. id=wx.ID_ANY, value='', pos=wx.DefaultPosition,
  544. size=globalvar.DIALOG_COMBOBOX_SIZE, vector=None,
  545. layer=1, choices=[]):
  546. super(ColumnSelect, self).__init__(parent, id, value, pos, size, choices,
  547. style=wx.CB_READONLY)
  548. self.SetName("ColumnSelect")
  549. if vector:
  550. self.InsertColumns(vector, layer)
  551. def InsertColumns(self, vector, layer, excludeKey = False, type = None):
  552. """!Insert columns for a vector attribute table into the columns combobox
  553. @param vector vector name
  554. @param layer vector layer number
  555. @param excludeKey exclude key column from the list?
  556. @param type only columns of given type (given as list)
  557. """
  558. dbInfo = VectorDBInfo(vector)
  559. try:
  560. table = dbInfo.GetTable(int(layer))
  561. columnchoices = dbInfo.GetTableDesc(table)
  562. keyColumn = dbInfo.GetKeyColumn(int(layer))
  563. columns = len(columnchoices.keys()) * ['']
  564. for key, val in columnchoices.iteritems():
  565. columns[val['index']] = key
  566. if excludeKey: # exclude key column
  567. columns.remove(keyColumn)
  568. if type: # only selected column types
  569. for key, value in columnchoices.iteritems():
  570. if value['type'] not in type:
  571. columns.remove(key)
  572. except (KeyError, ValueError):
  573. columns = []
  574. self.SetItems(columns)
  575. self.SetValue('')
  576. def InsertTableColumns(self, table, driver=None, database=None):
  577. """!Insert table columns"""
  578. columns = []
  579. ret = gcmd.RunCommand('db.columns',
  580. read = True,
  581. driver = driver,
  582. database = database,
  583. table = table)
  584. if ret:
  585. columns = ret.splitlines()
  586. self.SetItems(columns)
  587. class LocationSelect(wx.ComboBox):
  588. """!Widget for selecting GRASS location"""
  589. def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
  590. gisdbase = None, **kwargs):
  591. super(LocationSelect, self).__init__(parent, id, size = size,
  592. style = wx.CB_READONLY, **kwargs)
  593. self.SetName("LocationSelect")
  594. if not gisdbase:
  595. self.gisdbase = grass.gisenv()['GISDBASE']
  596. else:
  597. self.gisdbase = gisdbase
  598. self.SetItems(utils.GetListOfLocations(self.gisdbase))
  599. class MapsetSelect(wx.ComboBox):
  600. """!Widget for selecting GRASS mapset"""
  601. def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
  602. gisdbase = None, location = None, setItems = True, **kwargs):
  603. super(MapsetSelect, self).__init__(parent, id, size = size,
  604. style = wx.CB_READONLY, **kwargs)
  605. self.SetName("MapsetSelect")
  606. if not gisdbase:
  607. self.gisdbase = grass.gisenv()['GISDBASE']
  608. else:
  609. self.gisdbase = gisdbase
  610. if not location:
  611. self.location = grass.gisenv()['LOCATION_NAME']
  612. else:
  613. self.location = location
  614. if setItems:
  615. self.SetItems(utils.GetListOfMapsets(self.gisdbase, self.location, selectable = True)) # selectable