2 @package gui_core.gselect
4 @brief Custom control that selects elements
8 - gselect::VectorSelect
9 - gselect::TreeCrtlComboPopup
10 - gselect::VectorDBInfo
11 - gselect::LayerSelect
12 - gselect::DriverSelect
13 - gselect::DatabaseSelect
14 - gselect::TableSelect
15 - gselect::ColumnSelect
16 - gselect::DbaseSelect
17 - gselect::LocationSelect
18 - gselect::MapsetSelect
19 - gselect::SubGroupSelect
20 - gselect::FormatSelect
23 - gselect::ElementSelect
25 (C) 2007-2011 by the GRASS Development Team
27 This program is free software under the GNU General Public License
28 (>=v2). Read the file COPYING that comes with GRASS for details.
30 @author Michael Barton
31 @author Martin Landa <landa.martin gmail.com>
32 @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
41 import wx.lib.filebrowsebutton
as filebrowse
42 from wx.lib.newevent
import NewEvent
44 from core
import globalvar
49 from core.gcmd import RunCommand, GError, GMessage
50 from core.utils import GetListOfLocations, GetListOfMapsets, GetFormats
51 from core.utils import GetSettingsPath, GetValidLayerName, ListSortLower, GetAllVectorLayers
55 wxGdalSelect, EVT_GDALSELECT = NewEvent()
58 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
59 type =
None, multiple =
False, mapsets =
None,
60 updateOnPopup =
True, onPopup =
None,
61 fullyQualified =
True):
62 """!Custom control to create a ComboBox with a tree control to
63 display and select GIS elements within acessible mapsets.
64 Elements can be selected with mouse. Can allow multiple
65 selections, when argument multiple=True. Multiple selections
66 are separated by commas.
68 @param type type of GIS elements ('raster, 'vector', ...)
69 @param multiple multiple input allowed?
70 @param mapsets force list of mapsets (otherwise search path)
71 @param updateOnPopup True for updating list of elements on popup
72 @param onPopup function to be called on Popup
73 @param fullyQualified True to provide fully qualified names (map@mapset)
75 wx.combo.ComboCtrl.__init__(self, parent=parent, id=id, size=size)
76 self.GetChildren()[0].SetName(
"Select")
77 self.GetChildren()[0].type = type
80 self.SetPopupControl(self.
tcp)
81 self.SetPopupExtents(0, 100)
83 self.tcp.SetData(type = type, mapsets = mapsets,
85 updateOnPopup = updateOnPopup, onPopup = onPopup,
86 fullyQualified = fullyQualified)
87 self.GetChildren()[0].Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
90 """!Shows popupwindow if down arrow key is released"""
91 if event.GetKeyCode() == wx.WXK_DOWN
and not self.IsPopupShown():
99 @param type GIS element type
100 @param mapsets list of acceptable mapsets (None for all in search path)
102 self.tcp.SetData(type = type, mapsets = mapsets)
106 self.tcp.GetElementList()
108 def SetType(self, etype, multiple = False, mapsets = None,
109 updateOnPopup =
True, onPopup =
None):
110 """!Param set element type for widget
112 @param etype element type, see gselect.ElementSelect
114 self.tcp.SetData(type = etype, mapsets = mapsets,
116 updateOnPopup = updateOnPopup, onPopup = onPopup)
120 """!Custom to create a ComboBox with a tree control to display and
121 select vector maps. You can filter the vector maps. If you
122 don't need this feature use Select class instead
124 @ftype filter vector maps based on feature type
126 Select.__init__(self, parent = parent, id = wx.ID_ANY,
127 type =
'vector', **kwargs)
134 def _isElement(self, vectorName):
135 """!Check if element should be filtered out"""
137 if int(grass.vector_info_topo(vectorName)[self.
ftype]) < 1:
145 """!Create a tree ComboBox for selecting maps and other GIS elements
146 in accessible mapsets within the current location
162 self.
seltree = wx.TreeCtrl(parent, style=wx.TR_HIDE_ROOT
167 |wx.TR_FULL_ROW_HIGHLIGHT)
168 self.seltree.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
169 self.seltree.Bind(wx.EVT_MOTION, self.
OnMotion)
170 self.seltree.Bind(wx.EVT_LEFT_DOWN, self.
OnLeftDown)
173 self.seltree.Bind(wx.EVT_TREE_ITEM_EXPANDING,
lambda x:
None)
174 self.seltree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
lambda x:
None)
175 self.seltree.Bind(wx.EVT_TREE_ITEM_ACTIVATED,
lambda x:
None)
176 self.seltree.Bind(wx.EVT_TREE_SEL_CHANGED,
lambda x:
None)
177 self.seltree.Bind(wx.EVT_TREE_DELETE_ITEM,
lambda x:
None)
178 self.seltree.Bind(wx.EVT_TREE_BEGIN_DRAG,
lambda x:
None)
179 self.seltree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,
lambda x:
None)
185 """!Get value as a string separated by commas"""
186 return ','.join(self.
value)
189 """!Set filter for GIS elements, see e.g. VectorSelect"""
193 """!Limited only for first selected"""
205 inputText = self.GetCombo().
GetValue().strip()
207 root = self.seltree.GetRootItem()
208 match = self.
FindItem(root, inputText, startLetters =
True)
209 self.seltree.EnsureVisible(match)
210 self.seltree.SelectItem(match)
214 """!Get filtered list of GIS elements in accessible mapsets
215 and display as tree with all relevant elements displayed
216 beneath each mapset branch
219 self.seltree.DeleteAllItems()
222 if len(self.
value) > 0:
223 root = self.seltree.GetRootItem()
228 self.seltree.EnsureVisible(item)
229 self.seltree.SelectItem(item)
235 root = self.seltree.GetRootItem()
239 winValue = self.GetCombo().
GetValue().strip(
',')
242 self.
value = winValue.split(
',')
245 self.value.append(found)
246 self.seltree.SelectItem(found)
249 """!Reads UserSettings to get height (which was 200 in old implementation).
251 height = UserSettings.Get(group =
'appearance', key =
'gSelectPopupHeight', subkey =
'value')
252 return wx.Size(minWidth,
min(height, maxHeight))
254 def _getElementList(self, element, mapsets = None, elements = None, exclude = False):
255 """!Get list of GIS elements in accessible mapsets and display as tree
256 with all relevant elements displayed beneath each mapset branch
258 @param element GIS element
259 @param mapsets list of acceptable mapsets (None for all mapsets in search path)
260 @param elements list of forced GIS elements
261 @param exclude True to exclude, False for forcing the list (elements)
264 curr_mapset = grass.gisenv()[
'MAPSET']
267 elementdict = {
'cell':
'rast',
270 'raster files':
'rast',
273 '3d-raster':
'rast3d',
275 'raster3D files':
'rast3d',
278 'binary vector files':
'vect',
281 'old vector':
'oldvect',
282 'dig_ascii':
'asciivect',
283 'asciivect':
'asciivect',
284 'asciivector':
'asciivect',
285 'ascii vector files':
'asciivect',
288 'paint icon files':
'icon',
289 'paint/labels':
'labels',
292 'paint label files':
'labels',
293 'site_lists':
'sites',
296 'site list files':
'sites',
299 'region definition':
'region',
300 'region definition files':
'region',
301 'windows3d':
'region3d',
302 'region3d':
'region3d',
303 'region3D definition':
'region3d',
304 'region3D definition files':
'region3d',
306 'imagery group':
'group',
307 'imagery group files':
'group',
310 '3D viewing parameters':
'3dview',
311 '3D view parameters':
'3dview'}
313 if element
not in elementdict:
314 self.
AddItem(_(
'Not selectable element'))
317 if globalvar.have_mlist:
318 filesdict = grass.mlist_grouped(elementdict[element],
319 check_search_path =
False)
321 filesdict = grass.list_grouped(elementdict[element],
322 check_search_path =
False)
326 mapsets = grass.mapsets(search_path =
True)
329 if curr_mapset
in mapsets
and mapsets[0] != curr_mapset:
330 mapsets.remove(curr_mapset)
331 mapsets.insert(0, curr_mapset)
334 for mapset
in mapsets:
335 mapset_node = self.
AddItem(_(
'Mapset') +
': ' + mapset)
337 first_mapset = mapset_node
339 self.seltree.SetItemTextColour(mapset_node, wx.Colour(50, 50, 200))
340 if mapset
not in filesdict:
343 elem_list = filesdict[mapset]
345 for elem
in elem_list:
347 fullqElem = elem +
'@' + mapset
348 if elements
is not None:
349 if (exclude
and fullqElem
in elements)
or \
350 (
not exclude
and fullqElem
not in elements):
355 self.
AddItem(elem, parent = mapset_node)
357 self.
AddItem(elem, parent = mapset_node)
358 except StandardError, e:
359 sys.stderr.write(_(
"GSelect: invalid item: %s") % e)
362 if self.seltree.ItemHasChildren(mapset_node):
363 sel = UserSettings.Get(group=
'appearance', key=
'elementListExpand',
368 if mapset
in (
'PERMANENT', curr_mapset):
371 if mapset ==
'PERMANENT':
374 if mapset == curr_mapset:
382 self.seltree.Collapse(mapset_node)
384 self.seltree.Expand(mapset_node)
388 self.seltree.SelectItem(first_mapset)
391 def FindItem(self, parentItem, text, startLetters = False):
392 """!Finds item with given name or starting with given text"""
393 startletters = startLetters
394 item, cookie = self.seltree.GetFirstChild(parentItem)
395 while wx.TreeItemId.IsOk(item):
396 if self.seltree.GetItemText(item) == text:
398 if self.seltree.ItemHasChildren(item):
399 item = self.
FindItem(item, text, startLetters = startletters)
400 if wx.TreeItemId.IsOk(item):
402 elif startletters
and self.seltree.GetItemText(item).startswith(text.split(
'@', 1)[0]):
404 item, cookie = self.seltree.GetNextChild(parentItem, cookie)
405 return wx.TreeItemId()
409 root = self.seltree.GetRootItem()
411 root = self.seltree.AddRoot(
"<hidden root>")
414 item = self.seltree.AppendItem(parent, text=value)
419 """!Enables to select items using keyboard"""
421 item = self.seltree.GetSelection()
422 if event.GetKeyCode() == wx.WXK_DOWN:
423 self.seltree.SelectItem(self.seltree.GetNextVisible(item))
426 elif event.GetKeyCode() == wx.WXK_UP:
427 if self.seltree.ItemHasChildren(item)
and self.seltree.IsExpanded(self.seltree.GetPrevSibling(item)):
428 itemPrev = self.seltree.GetLastChild(self.seltree.GetPrevSibling(item))
430 itemPrev = self.seltree.GetPrevSibling(item)
431 if not wx.TreeItemId.IsOk(itemPrev):
432 itemPrev = self.seltree.GetItemParent(item)
433 if item == self.seltree.GetFirstChild(self.seltree.GetRootItem())[0]:
435 self.seltree.SelectItem(itemPrev)
438 elif event.GetKeyCode() == wx.WXK_TAB:
439 selected = self.seltree.GetSelection()
440 if self.seltree.ItemHasChildren(selected):
443 parent = self.seltree.GetItemParent(selected)
444 nextSibling = self.seltree.GetNextSibling(parent)
445 if wx.TreeItemId.IsOk(nextSibling):
446 match = self.
FindItem(nextSibling, self.GetCombo().
GetValue().strip(),
True)
448 match = self.
FindItem(self.seltree.GetFirstChild(self.seltree.GetItemParent(parent))[0],
449 self.GetCombo().
GetValue().strip(),
True)
450 self.seltree.SelectItem(match)
452 elif event.GetKeyCode() == wx.WXK_RIGHT:
453 if self.seltree.ItemHasChildren(item):
454 self.seltree.Expand(item)
456 elif event.GetKeyCode() == wx.WXK_LEFT:
457 if self.seltree.ItemHasChildren(item):
458 self.seltree.Collapse(item)
460 elif event.GetKeyCode() == wx.WXK_ESCAPE:
463 elif event.GetKeyCode() == wx.WXK_RETURN:
464 if self.seltree.GetRootItem() == self.seltree.GetItemParent(item):
467 mapsetItem = self.seltree.GetItemParent(item)
468 fullName = self.seltree.GetItemText(item)
470 fullName +=
'@' + self.seltree.GetItemText(mapsetItem).
split(
':', -1)[1].strip()
474 self.value.append(fullName)
476 self.
value = [fullName]
481 """!Have the selection follow the mouse, like in a real combobox
483 item, flags = self.seltree.HitTest(evt.GetPosition())
484 if item
and flags & wx.TREE_HITTEST_ONITEMLABEL:
485 self.seltree.SelectItem(item)
490 """!Do the combobox selection
492 item, flags = self.seltree.HitTest(evt.GetPosition())
493 if item
and flags & wx.TREE_HITTEST_ONITEMLABEL:
496 if self.seltree.GetRootItem() == self.seltree.GetItemParent(item):
499 mapsetItem = self.seltree.GetItemParent(item)
500 fullName = self.seltree.GetItemText(item)
502 fullName +=
'@' + self.seltree.GetItemText(mapsetItem).
split(
':', -1)[1].strip()
506 self.value.append(fullName)
508 self.
value = [fullName]
515 """!Set object properties"""
517 self.
type = kargs[
'type']
518 if 'mapsets' in kargs:
519 self.
mapsets = kargs[
'mapsets']
520 if 'multiple' in kargs:
522 if 'updateOnPopup' in kargs:
524 if 'onPopup' in kargs:
525 self.
onPopup = kargs[
'onPopup']
526 if 'fullyQualified' in kargs:
535 """!Class providing information about attribute tables
536 linked to a vector map"""
550 def _CheckDBConnection(self):
551 """!Check DB connection"""
552 nuldev = file(os.devnull,
'w+')
553 self.
layers = grass.vector_db(map=self.
map, stderr=nuldev)
556 if (len(self.layers.keys()) == 0):
561 def _DescribeTables(self):
562 """!Describe linked tables"""
563 for layer
in self.layers.keys():
565 table = self.
layers[layer][
"table"]
568 Debug.msg(1,
"gselect.VectorDBInfo._DescribeTables(): table=%s driver=%s database=%s" % \
569 (self.
layers[layer][
"table"], self.
layers[layer][
"driver"],
570 self.
layers[layer][
"database"]))
571 for item
in grass.db_describe(table = self.
layers[layer][
"table"],
572 driver = self.
layers[layer][
"driver"],
573 database = self.
layers[layer][
"database"])[
'cols']:
574 name, type, length = item
576 if type.lower() ==
"integer":
578 elif type.lower() ==
"double precision":
583 columns[name.strip()] = {
'index' : i,
584 'type' : type.lower(),
586 'length' : int(length),
593 if self.
layers[layer][
"key"]
not in columns.keys():
594 for col
in columns.keys():
595 if col.lower() == self.
layers[layer][
"key"]:
596 self.
layers[layer][
"key"] = col.upper()
599 self.
tables[table] = columns
606 table = self.
layers[layer][
"table"]
607 columns = self.
tables[table]
608 for name
in self.
tables[table].keys():
609 self.
tables[table][name][
'values'] = []
610 self.
tables[table][name][
'ids'] = []
613 """!Get vector name"""
617 """!Get key column of given layer
619 @param layer vector layer number
621 return str(self.
layers[layer][
'key'])
624 """!Get table name of given layer
626 @param layer vector layer number
628 return self.
layers[layer][
'table']
631 """!Get database settins
633 @param layer layer number
635 @return (driver, database)
637 return self.
layers[layer][
'driver'], self.
layers[layer][
'database']
640 """!Get table columns
642 @param table table name
647 """!Creates combo box for selecting data layers defined for vector.
650 id = wx.ID_ANY, pos = wx.DefaultPosition,
651 size = globalvar.DIALOG_LAYER_SIZE,
652 vector =
None, choices = [], initial = [], default =
None):
654 super(LayerSelect, self).
__init__(parent, id, pos=pos, size=size,
660 self.SetName(
"LayerSelect")
670 """!Insert layers for a vector into the layer combobox
672 @param vector name of vector map
686 layers.insert(0, str(self.
default))
687 elif self.
default not in layers:
691 self.SetItems(layers)
695 def _selectionChanged(self, event):
696 """!Selection changed, store value."""
701 """!Select value (currently selected or default)"""
702 items = self.GetItems()
705 self.SetStringSelection(self.
current)
707 self.SetStringSelection(str(self.
default))
714 """!Creates combo box for selecting database driver.
716 def __init__(self, parent, choices, value,
717 id=wx.ID_ANY, pos=wx.DefaultPosition,
718 size=globalvar.DIALOG_LAYER_SIZE, **kargs):
720 super(DriverSelect, self).
__init__(parent, id, value, pos, size,
721 choices, style=wx.CB_READONLY)
723 self.SetName(
"DriverSelect")
725 self.SetStringSelection(value)
728 """!Creates combo box for selecting database driver.
730 def __init__(self, parent, value='',
731 id=wx.ID_ANY, pos=wx.DefaultPosition,
732 size=globalvar.DIALOG_TEXTCTRL_SIZE, **kargs):
734 super(DatabaseSelect, self).
__init__(parent, id, value, pos, size)
736 self.SetName(
"DatabaseSelect")
739 """!Creates combo box for selecting attribute tables from the database
742 id=wx.ID_ANY, value=
'', pos=wx.DefaultPosition,
743 size=globalvar.DIALOG_COMBOBOX_SIZE,
746 super(TableSelect, self).
__init__(parent, id, value, pos, size, choices,
747 style=wx.CB_READONLY)
749 self.SetName(
"TableSelect")
755 """!Insert attribute tables into combobox"""
758 if not driver
or not database:
759 connect = grass.db_connection()
761 driver = connect[
'driver']
762 database = connect[
'database']
771 for table
in ret.splitlines():
778 """!Creates combo box for selecting columns in the attribute table
781 @param parent window parent
783 @param value default value
784 @param size window size
785 @param vector vector map name
786 @param layer layer number
787 @param param parameters list (see menuform.py)
788 @param **kwags wx.ComboBox parameters
790 def __init__(self, parent, id = wx.ID_ANY, value = '',
791 size=globalvar.DIALOG_COMBOBOX_SIZE,
792 vector =
None, layer = 1, param =
None, **kwargs):
796 super(ColumnSelect, self).
__init__(parent, id, value, size = size, **kwargs)
797 self.SetName(
"ColumnSelect")
802 def InsertColumns(self, vector, layer, excludeKey = False, excludeCols = None, type = None, dbInfo = None):
803 """!Insert columns for a vector attribute table into the columns combobox
805 @param vector vector name
806 @param layer vector layer number
807 @param excludeKey exclude key column from the list?
808 @param excludeCols list of columns to be removed from the list
809 @param type only columns of given type (given as list)
815 table = dbInfo.GetTable(int(layer))
816 columnchoices = dbInfo.GetTableDesc(table)
817 keyColumn = dbInfo.GetKeyColumn(int(layer))
818 columns = len(columnchoices.keys()) * [
'']
819 for key, val
in columnchoices.iteritems():
820 columns[val[
'index']] = key
822 columns.remove(keyColumn)
824 for key
in columnchoices.iterkeys():
825 if key
in excludeCols:
828 for key, value
in columnchoices.iteritems():
829 if value[
'type']
not in type:
834 except (KeyError, ValueError):
837 self.SetItems(columns)
841 value = self.param.get(
'value',
'')
842 if value !=
'' and value
in columns:
846 """!Insert table columns
848 @param table table name
849 @param driver driver name
850 @param database database name
861 columns = ret.splitlines()
863 self.SetItems(columns)
867 value = self.param.get(
'value',
'')
868 if value !=
'' and value
in columns:
872 """!Widget for selecting GRASS Database"""
874 super(DbaseSelect, self).
__init__(parent, id = wx.ID_ANY,
875 size = globalvar.DIALOG_GSELECT_SIZE, labelText =
'',
876 dialogTitle = _(
'Choose GIS Data Directory'),
877 buttonText = _(
'Browse'),
878 startDirectory = grass.gisenv()[
'GISDBASE'],
882 """!Widget for selecting GRASS location"""
883 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
884 gisdbase =
None, **kwargs):
885 super(LocationSelect, self).
__init__(parent, id, size = size,
886 style = wx.CB_READONLY, **kwargs)
887 self.SetName(
"LocationSelect")
897 """!Update list of locations
899 @param dbase path to GIS database
908 """!Widget for selecting GRASS mapset"""
909 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
910 gisdbase =
None, location =
None, setItems =
True,
911 searchPath =
False, skipCurrent =
False, **kwargs):
912 super(MapsetSelect, self).
__init__(parent, id, size = size,
913 style = wx.CB_READONLY, **kwargs)
917 self.SetName(
"MapsetSelect")
932 """!Update list of mapsets for given location
934 @param dbase path to GIS database (None to use currently selected)
935 @param location name of location
945 def _getMapsets(self):
948 read =
True, flags =
'p',
949 fs =
'newline').splitlines()
954 gisenv = grass.gisenv()
956 gisenv[
'LOCATION_NAME'] == self.
location and \
957 gisenv[
'MAPSET']
in mlist:
958 mlist.remove(gisenv[
'MAPSET'])
963 """!Widget for selecting subgroups"""
964 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
966 super(SubGroupSelect, self).
__init__(parent, id, size = size,
968 self.SetName(
"SubGroupSelect")
971 """!Insert subgroups for defined group"""
974 gisenv = grass.gisenv()
976 name, mapset = group.split(
'@', 1)
979 mapset = gisenv[
'MAPSET']
981 path = os.path.join(gisenv[
'GISDBASE'], gisenv[
'LOCATION_NAME'], mapset,
982 'group', name,
'subgroup')
984 self.SetItems(os.listdir(path))
990 def __init__(self, parent, ogr = False,
991 sourceType =
None, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
993 """!Widget for selecting external (GDAL/OGR) format
995 @param parent parent window
996 @param sourceType source type ('file', 'directory', 'database', 'protocol') or None
997 @param ogr True for OGR otherwise GDAL
999 super(FormatSelect, self).
__init__(parent, id, size = size,
1001 self.SetName(
"FormatSelect")
1011 self.SetItems(formats)
1014 """!Get file extension by format name"""
1018 'Erdas Imagine Images (.img)' :
'img',
1019 'Ground-based SAR Applications Testbed File Format (.gff)' :
'gff',
1020 'Arc/Info Binary Grid' :
'adf',
1021 'Portable Network Graphics' :
'png',
1022 'JPEG JFIF' :
'jpg',
1023 'Japanese DEM (.mem)' :
'mem',
1024 'Graphics Interchange Format (.gif)' :
'gif',
1025 'X11 PixMap Format' :
'xpm',
1026 'MS Windows Device Independent Bitmap' :
'bmp',
1027 'SPOT DIMAP' :
'dim',
1028 'RadarSat 2 XML Product' :
'xml',
1029 'EarthWatch .TIL' :
'til',
1030 'ERMapper .ers Labelled' :
'ers',
1031 'ERMapper Compressed Wavelets' :
'ecw',
1032 'GRIdded Binary (.grb)' :
'grb',
1033 'EUMETSAT Archive native (.nat)' :
'nat',
1034 'Idrisi Raster A.1' :
'rst',
1035 'Golden Software ASCII Grid (.grd)' :
'grd',
1036 'Golden Software Binary Grid (.grd)' :
'grd',
1037 'Golden Software 7 Binary Grid (.grd)' :
'grd',
1038 'R Object Data Store' :
'r',
1039 'USGS DOQ (Old Style)' :
'doq',
1040 'USGS DOQ (New Style)' :
'doq',
1041 'ENVI .hdr Labelled' :
'hdr',
1042 'ESRI .hdr Labelled' :
'hdr',
1043 'Generic Binary (.hdr Labelled)' :
'hdr',
1044 'PCI .aux Labelled' :
'aux',
1045 'EOSAT FAST Format' :
'fst',
1046 'VTP .bt (Binary Terrain) 1.3 Format' :
'bt',
1047 'FARSITE v.4 Landscape File (.lcp)' :
'lcp',
1048 'Swedish Grid RIK (.rik)' :
'rik',
1049 'USGS Optional ASCII DEM (and CDED)' :
'dem',
1050 'Northwood Numeric Grid Format .grd/.tab' :
'',
1051 'Northwood Classified Grid Format .grc/.tab' :
'',
1052 'ARC Digitized Raster Graphics' :
'arc',
1053 'Magellan topo (.blx)' :
'blx',
1054 'SAGA GIS Binary Grid (.sdat)' :
'sdat',
1056 'ESRI Shapefile' :
'shp',
1073 'Geoconcept' :
'gxt',
1075 'GPSTrackMaker' :
'gtm',
1080 return formatToExt[name]
1085 def __init__(self, parent, panel, ogr = False, link = False, dest = False,
1086 default =
'file', exclude = [], envHandler =
None):
1087 """!Widget for selecting GDAL/OGR datasource, format
1089 @param parent parent window
1090 @param ogr use OGR selector instead of GDAL
1091 @param dest True for output (destination)
1092 @param default deafult type (ignored when dest == True)
1093 @param exclude list of types to be excluded
1098 wx.Panel.__init__(self, parent = panel, id = wx.ID_ANY)
1101 label =
" %s " % _(
"Settings"))
1103 self.
inputBox = wx.StaticBox(parent = self, id = wx.ID_ANY)
1105 self.inputBox.SetLabel(
" %s " % _(
"Output settings"))
1107 self.inputBox.SetLabel(
" %s " % _(
"Source settings"))
1118 sources.append(_(
"Native"))
1121 if 'file' not in exclude:
1122 sources.append(_(
"File"))
1125 if 'directory' not in exclude:
1126 sources.append(_(
"Directory"))
1129 if 'database' not in exclude:
1130 sources.append(_(
"Database"))
1133 if 'protocol' not in exclude:
1134 sources.append(_(
"Protocol"))
1148 self.btnSettingsSave.SetToolTipString(_(
"Save current settings"))
1151 self.btnSettingsSave.SetToolTipString(_(
"Delete currently selected settings"))
1153 self.
source = wx.RadioBox(parent = self, id = wx.ID_ANY,
1154 style = wx.RA_SPECIFY_COLS,
1157 self.source.SetLabel(
" %s " % _(
'Output type'))
1159 self.source.SetLabel(
" %s " % _(
'Source type'))
1161 self.source.SetSelection(0)
1162 self.source.Bind(wx.EVT_RADIOBOX, self.
OnSetType)
1166 filemask =
'GeoTIFF (%s)|%s|%s (*.*)|*.*' % \
1169 filemask =
'ESRI Shapefile (%s)|%s|%s (*.*)|*.*' % \
1172 dsnFile = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1173 size=globalvar.DIALOG_GSELECT_SIZE, labelText =
'',
1174 dialogTitle=_(
'Choose file to import'),
1175 buttonText=_(
'Browse'),
1176 startDirectory=os.getcwd(),
1181 dsnDir = filebrowse.DirBrowseButton(parent=self, id=wx.ID_ANY,
1182 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1183 dialogTitle=_(
'Choose input directory'),
1184 buttonText=_(
'Browse'),
1185 startDirectory=os.getcwd(),
1187 dsnDir.SetName(
'GdalSelect')
1190 dsnDbFile = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1191 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1192 dialogTitle=_(
'Choose file'),
1193 buttonText=_(
'Browse'),
1194 startDirectory=os.getcwd(),
1197 dsnDbFile.SetName(
'GdalSelect')
1199 dsnDbText = wx.TextCtrl(parent = self, id = wx.ID_ANY)
1201 dsnDbText.Bind(wx.EVT_TEXT, self.
OnSetDsn)
1202 dsnDbText.SetName(
'GdalSelect')
1204 dsnDbChoice = wx.Choice(parent = self, id = wx.ID_ANY)
1206 dsnDbChoice.Bind(wx.EVT_CHOICE, self.
OnSetDsn)
1207 dsnDbChoice.SetName(
'GdalSelect')
1209 dsnPro = wx.TextCtrl(parent = self, id = wx.ID_ANY)
1211 dsnPro.Bind(wx.EVT_TEXT, self.
OnSetDsn)
1212 dsnPro.SetName(
'GdalSelect')
1220 self.extension.Hide()
1229 'dir' : [_(
"Name:"),
1235 'pro' : [_(
"Protocol:"),
1238 'db-win' : {
'file' : dsnDbFile,
1240 'choice' : dsnDbChoice },
1241 'native' : [_(
"Name:"), dsnDir,
''],
1247 read =
True, parse = grass.parse_key_val,
1249 if current[
'format'] ==
'native':
1251 elif current[
'format']
in GetFormats()[
'ogr'][
'database']:
1258 self.
dsnText = wx.StaticText(parent = self, id = wx.ID_ANY,
1262 label = _(
"Extension:"))
1263 self.extensionText.Hide()
1267 self.creationOpt.Hide()
1273 if current[
'format'] !=
'native':
1274 self.
OnSetFormat(event =
None, format = current[
'format'])
1275 self.
OnSetDsn(event =
None, path = current[
'dsn'])
1276 self.creationOpt.SetValue(current[
'options'])
1279 self.
OnSetFormat(event =
None, format =
'GeoTIFF')
1281 self.
OnSetFormat(event =
None, format =
'ESRI Shapefile')
1285 mainSizer = wx.BoxSizer(wx.VERTICAL)
1287 settingsSizer = wx.StaticBoxSizer(self.
settingsBox, wx.HORIZONTAL)
1288 settingsSizer.Add(item = wx.StaticText(parent = self,
1290 label = _(
"Load settings:")),
1291 flag = wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
1297 flag = wx.LEFT | wx.RIGHT,
1303 inputSizer = wx.StaticBoxSizer(self.
inputBox, wx.HORIZONTAL)
1308 self.dsnSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
1309 label = _(
"Format:")),
1310 flag = wx.ALIGN_CENTER_VERTICAL,
1312 self.dsnSizer.Add(item=self.
format,
1313 flag = wx.ALIGN_CENTER_VERTICAL,
1316 flag=wx.ALIGN_CENTER_VERTICAL,
1319 flag = wx.ALIGN_CENTER_VERTICAL,
1322 self.dsnSizer.Add(item = self.
dsnText,
1323 flag = wx.ALIGN_CENTER_VERTICAL,
1326 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1327 pos = (row, 1), span = (1, 3))
1329 if self.creationOpt.IsShown():
1330 self.dsnSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
1331 label = _(
"Creation options:")),
1332 flag = wx.ALIGN_CENTER_VERTICAL,
1335 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1336 pos = (row, 1), span = (1, 3))
1338 self.dsnSizer.AddGrowableCol(3)
1340 inputSizer.Add(item=self.
dsnSizer, proportion = 1,
1341 flag=wx.EXPAND | wx.BOTTOM, border = 10)
1343 mainSizer.Add(item=settingsSizer, proportion=0,
1344 flag=wx.ALL | wx.EXPAND, border=5)
1345 mainSizer.Add(item=self.
source, proportion=0,
1346 flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=5)
1347 mainSizer.Add(item=inputSizer, proportion=0,
1348 flag=wx.ALL | wx.EXPAND, border=5)
1350 self.SetSizer(mainSizer)
1353 def _getExtPatternGlob(self, ext):
1354 """!Get pattern for case-insensitive globing"""
1357 pattern +=
'[%s%s]' % (c.lower(), c.upper())
1360 def _getExtPattern(self, ext):
1361 """!Get pattern for case-insensitive file mask"""
1362 return '*.%s;*.%s' % (ext.lower(), ext.upper())
1365 """!Load named settings"""
1366 name = event.GetString()
1368 GError(parent = self,
1369 message = _(
"Settings <%s> not found") % name)
1374 self.
OnSetDsn(event =
None, path = data[1])
1375 self.creationOpt.SetValue(data[3])
1378 """!Save settings"""
1379 dlg = wx.TextEntryDialog(parent = self,
1380 message = _(
"Name:"),
1381 caption = _(
"Save settings"))
1382 if dlg.ShowModal() != wx.ID_OK:
1386 if not dlg.GetValue():
1387 GMessage(parent = self,
1388 message = _(
"Name not given, settings is not saved."))
1392 GMessage(parent = self,
1393 message = _(
"No data source defined, settings is not saved."))
1396 name = dlg.GetValue()
1400 dlgOwt = wx.MessageDialog(self, message = _(
"Settings <%s> already exists. "
1401 "Do you want to overwrite the settings?") % name,
1402 caption = _(
"Save settings"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1403 if dlgOwt.ShowModal() != wx.ID_YES:
1408 self.format.GetStringSelection(),
1409 self.creationOpt.GetValue())
1413 self.settingsChoice.SetStringSelection(name)
1418 """!Save settings"""
1419 name = self.settingsChoice.GetStringSelection()
1421 GMessage(parent = self,
1422 message = _(
"No settings is defined. Operation canceled."))
1425 self._settings.pop(name)
1429 def _saveSettings(self):
1430 """!Save settings into the file
1432 @return 0 on success
1433 @return -1 on failure
1437 for key, value
in self._settings.iteritems():
1438 fd.write(
'%s;%s;%s;%s\n' % (key, value[0], value[1], value[2]))
1440 GError(parent = self,
1441 message = _(
"Unable to save settings"))
1448 def _loadSettings(self):
1449 """!Load settings from the file
1451 The file is defined by self.SettingsFile.
1454 @return empty dict on error
1462 for line
in fd.readlines():
1464 lineData = line.rstrip(
'\n').
split(
';')
1465 if len(lineData) > 4:
1467 data[lineData[0]] = (lineData[1], lineData[2], lineData[3], lineData[4])
1469 data[lineData[0]] = (lineData[1], lineData[2], lineData[3],
'')
1477 self.settingsChoice.SetItems(sorted(data.keys()))
1482 """!Datasource type changed.
1484 @todo improve showing/hiding widgets
1487 sel = event.GetSelection()
1489 self.source.SetSelection(sel)
1492 self.dsnSizer.Detach(win)
1499 ext = self.format.GetExtension(format)
1502 format +=
' (%s)|%s|%s (*.*)|*.*' % \
1505 format +=
'%s (*.*)|*.*' % _(
'All files')
1507 win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1508 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1509 dialogTitle=_(
'Choose file to import'),
1510 buttonText=_(
'Browse'),
1511 startDirectory=os.getcwd(),
1530 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1531 pos = (1, 1), span = (1, 3))
1537 self.format.Enable(
False)
1538 self.creationOpt.Enable(
False)
1539 self.parent.btnOk.Enable(
True)
1541 if not win.IsEnabled():
1543 if not self.format.IsEnabled():
1544 self.format.Enable(
True)
1545 self.creationOpt.Enable(
True)
1548 if self.parent.GetName() ==
'MultiImportDialog':
1549 self.parent.list.DeleteAllItems()
1553 self.
OnSetFormat(event =
None, format =
'GeoTIFF')
1555 self.
OnSetFormat(event =
None, format =
'ESRI Shapefile')
1558 if not self.extension.IsShown():
1559 self.extensionText.Show()
1560 self.extension.Show()
1562 if self.extension.IsShown():
1563 self.extensionText.Hide()
1564 self.extension.Hide()
1566 self.dsnSizer.Layout()
1569 """!Get datasource name
1571 if self.format.GetStringSelection() ==
'PostgreSQL':
1572 dsn =
'PG:dbname=%s' % self.
input[self.
dsnType][1].GetStringSelection()
1579 """!Input DXF file/OGR dsn defined, update list of layer
1582 path = event.GetString()
1584 if self.format.GetStringSelection() ==
'PostgreSQL':
1585 for item
in path.split(
':', 1)[1].
split(
','):
1586 key, value = item.split(
'=', 1)
1588 if not self.
input[self.
dsnType][1].SetStringSelection(value):
1589 GMessage(_(
"Database <%s> not accessible.") % value,
1597 self.parent.btnOk.Enable(
False)
1601 self.parent.btnOk.Enable(
True)
1608 def _reloadLayers(self):
1609 """!Reload list of layers"""
1624 self.parent.list.LoadData()
1625 if hasattr(self,
"btn_run"):
1626 self.btn_run.Enable(
False)
1630 for line
in ret.split(
','):
1631 layerName = line.strip()
1633 data.append((layerId, layerName, grassName))
1637 baseName = os.path.basename(dsn)
1639 data.append((layerId, baseName, grassName))
1641 ext = self.extension.GetValue()
1643 baseName = os.path.basename(filename)
1645 data.append((layerId, baseName, grassName))
1650 evt = wxGdalSelect(dsn = dsn)
1652 wx.PostEvent(self.
parent, evt)
1654 if self.parent.GetName() ==
'MultiImportDialog':
1655 self.parent.list.LoadData(data)
1657 self.parent.btn_run.Enable(
True)
1659 self.parent.btn_run.Enable(
False)
1662 """!Extension changed"""
1668 """!Format changed"""
1669 if self.
dsnType not in [
'file',
'dir',
'db']:
1673 self.dsnSizer.Detach(win)
1681 format = event.GetString()
1683 self.format.SetStringSelection(format)
1687 ext = self.format.GetExtension(format)
1690 format +=
' (%s)|%s|%s (*.*)|*.*' % \
1693 format +=
'%s (*.*)|*.*' % _(
'All files')
1695 win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1696 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1697 dialogTitle=_(
'Choose file'),
1698 buttonText=_(
'Browse'),
1699 startDirectory=os.getcwd(),
1707 if format ==
'SQLite' or format ==
'Rasterlite':
1708 win = self.
input[
'db-win'][
'file']
1709 elif format ==
'PostgreSQL' or format ==
'PostGIS WKT Raster driver':
1710 if grass.find_program(
'psql', [
'--help']):
1711 win = self.
input[
'db-win'][
'choice']
1712 if not win.GetItems():
1713 p = grass.Popen([
'psql',
'-ltA'], stdout = grass.PIPE)
1714 ret = p.communicate()[0]
1717 for line
in ret.splitlines():
1718 sline = line.split(
'|')
1725 if self.
dest and win.GetStringSelection():
1726 self.parent.btnOk.Enable(
True)
1728 win = self.
input[
'db-win'][
'text']
1730 win = self.
input[
'db-win'][
'text']
1733 if not win.IsShown():
1736 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1737 pos = (1, 1), span = (1, 3))
1738 self.dsnSizer.Layout()
1748 """!Get source type"""
1752 """!Get list of DSN windows"""
1754 for stype
in (
'file',
'dir',
'pro'):
1755 win.append(self.
input[stype][1])
1756 for stype
in (
'file',
'text',
'choice'):
1757 win.append(self.
input[
'db-win'][stype])
1762 """!Get format as string"""
1763 return self.format.GetStringSelection().replace(
' ',
'_')
1766 """!Get format extension"""
1767 return self.format.GetExtension(self.format.GetStringSelection())
1770 """!Get creation options"""
1771 if not self.creationOpt.IsShown():
1774 return self.creationOpt.GetValue()
1777 """!Widget for selecting input raster/vector map used by
1778 r.proj/v.proj modules."""
1779 def __init__(self, parent, isRaster, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
1781 super(ProjSelect, self).
__init__(parent, id, size = size,
1782 style = wx.CB_READONLY, **kwargs)
1783 self.SetName(
"ProjSelect")
1787 """!Update list of maps
1791 dbase = grass.gisenv()[
'GISDBASE']
1793 mapset = grass.gisenv()[
'MAPSET']
1800 location = location,
1808 location = location,
1812 for line
in ret.splitlines():
1813 listMaps.append(line.strip())
1816 self.SetItems(listMaps)
1820 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
1822 """!Widget for selecting GIS element
1824 @param parent parent window
1826 super(ElementSelect, self).
__init__(parent, id, size = size,
1828 self.SetName(
"ElementSelect")
1830 task = gtask.parse_interface(
'g.list')
1831 p = task.get_param(value =
'type')
1834 self.SetItems(self.
values)
1839 @param name element name
def __init__(self, parent, id=wx.ID_ANY, size=globalvar.DIALOG_COMBOBOX_SIZE, gisdbase=None, kwargs)
def InsertTableColumns
Insert table columns.
def SetElementList
Set element list.
def Select(self)
Select value (currently selected or default)
def GetName(self)
Get vector name.
def GetValidLayerName(name)
Make layer name SQL compliant, based on G_str_to_sql()
def __init__(self, parent, isRaster, id=wx.ID_ANY, size=globalvar.DIALOG_COMBOBOX_SIZE, kwargs)
def __init__(self, parent, id=wx.ID_ANY, size=globalvar.DIALOG_COMBOBOX_SIZE, kwargs)
Widget for selecting GIS element.
def GetOptions(self)
Get creation options.
def UpdateItems(self, dbase)
Update list of locations.
def GetKeyColumn(self, layer)
Get key column of given layer.
def __init__
Custom control to create a ComboBox with a tree control to display and select GIS elements within ace...
def GetFormats()
Get GDAL/OGR formats.
Creates combo box for selecting data layers defined for vector.
def GetListOfMapsets
Get list of mapsets in given GRASS location.
def OnSettingsSave(self, event)
Save settings.
def OnSetDsn
Input DXF file/OGR dsn defined, update list of layer widget.
def OnSettingsDelete(self, event)
Save settings.
def Insert(self, group)
Insert subgroups for defined group.
def __init__
Widget for selecting GDAL/OGR datasource, format.
def __init__(self, parent, id=wx.ID_ANY, size=globalvar.DIALOG_COMBOBOX_SIZE, gisdbase=None, location=None, setItems=True, searchPath=False, skipCurrent=False, kwargs)
def SetType
Param set element type for widget.
def GetFormatExt(self)
Get format extension.
def GetDsn(self)
Get datasource name.
def GetTable(self, layer)
Get table name of given layer.
def _reloadLayers(self)
Reload list of layers.
def _getExtPattern(self, ext)
Get pattern for case-insensitive file mask.
def GetType(self)
Get source type.
def __init__(self, parent, value='', id=wx.ID_ANY, pos=wx.DefaultPosition, size=globalvar.DIALOG_TEXTCTRL_SIZE, kargs)
def ListSortLower(list)
Sort list items (not case-sensitive)
def GetListOfLocations(dbase)
Get list of GRASS locations in given dbase.
def GetAllVectorLayers(vector)
Returns list of all vector layers as strings.
def OnSetFormat
Format changed.
Widget for selecting input raster/vector map used by r.proj/v.proj modules.
def GetFormat(self)
Get format as string.
def __init__(self, parent, choices, value, id=wx.ID_ANY, pos=wx.DefaultPosition, size=globalvar.DIALOG_LAYER_SIZE, kargs)
def UpdateItems
Update list of mapsets for given location.
def _DescribeTables(self)
Describe linked tables.
Creates combo box for selecting attribute tables from the database.
def split(s)
Platform spefic shlex.split.
Widget for selecting GRASS Database.
def GetElementList(self)
Load elements.
Creates combo box for selecting database driver.
def GetSettingsPath()
Get full path to the settings directory.
def OnSettingsLoad(self, event)
Load named settings.
def InsertTables
Insert attribute tables into combobox.
def __init__(self, parent, ftype, kwargs)
Custom to create a ComboBox with a tree control to display and select vector maps.
def _CheckDBConnection(self)
Check DB connection.
def _isElement(self, vectorName)
Check if element should be filtered out.
Widget for selecting GRASS location.
def __init__(self, parent, id=wx.ID_ANY, value='', size=globalvar.DIALOG_COMBOBOX_SIZE, vector=None, layer=1, param=None, kwargs)
def OnSetType
Datasource type changed.
Widget for selecting GRASS mapset.
Widget for selecting subgroups.
def OnKeyUp(self, event)
Shows popupwindow if down arrow key is released.
Creates combo box for selecting columns in the attribute table for a vector map.
Misc utilities for wxGUI.
Creates combo box for selecting database driver.
def __init__(self, parent, kwargs)
def _selectionChanged(self, event)
Selection changed, store value.
def _getExtPatternGlob(self, ext)
Get pattern for case-insensitive globing.
def GetValue(self, name)
Translate value.
def InsertColumns
Insert columns for a vector attribute table into the columns combobox.
def RunCommand(prog, flags="", overwrite=False, quiet=False, verbose=False, parent=None, read=False, stdin=None, getErrorMsg=False, kwargs)
Run GRASS command.
def __init__(self, parent, id=wx.ID_ANY, size=globalvar.DIALOG_GSELECT_SIZE, kwargs)
def _saveSettings(self)
Save settings into the file.
def UpdateItems(self, dbase, location, mapset)
Update list of maps.
Class providing information about attribute tables linked to a vector map.
def OnSetExtension(self, event)
Extension changed.
def _loadSettings(self)
Load settings from the file.
def InsertLayers(self, vector)
Insert layers for a vector into the layer combobox.
def GetDsnWin(self)
Get list of DSN windows.
def GetDbSettings(self, layer)
Get database settins.
def GetTableDesc(self, table)
Get table columns.