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)
1307 self.dsnSizer.AddGrowableCol(3)
1310 self.dsnSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
1311 label = _(
"Format:")),
1312 flag = wx.ALIGN_CENTER_VERTICAL,
1314 self.dsnSizer.Add(item=self.
format,
1315 flag = wx.ALIGN_CENTER_VERTICAL,
1318 flag=wx.ALIGN_CENTER_VERTICAL,
1321 flag = wx.ALIGN_CENTER_VERTICAL,
1324 self.dsnSizer.Add(item = self.
dsnText,
1325 flag = wx.ALIGN_CENTER_VERTICAL,
1328 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1329 pos = (row, 1), span = (1, 3))
1331 if self.creationOpt.IsShown():
1332 self.dsnSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
1333 label = _(
"Creation options:")),
1334 flag = wx.ALIGN_CENTER_VERTICAL,
1337 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1338 pos = (row, 1), span = (1, 3))
1341 inputSizer.Add(item=self.
dsnSizer, proportion = 1,
1342 flag=wx.EXPAND | wx.BOTTOM, border = 10)
1344 mainSizer.Add(item=settingsSizer, proportion=0,
1345 flag=wx.ALL | wx.EXPAND, border=5)
1346 mainSizer.Add(item=self.
source, proportion=0,
1347 flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=5)
1348 mainSizer.Add(item=inputSizer, proportion=0,
1349 flag=wx.ALL | wx.EXPAND, border=5)
1351 self.SetSizer(mainSizer)
1354 def _getExtPatternGlob(self, ext):
1355 """!Get pattern for case-insensitive globing"""
1358 pattern +=
'[%s%s]' % (c.lower(), c.upper())
1361 def _getExtPattern(self, ext):
1362 """!Get pattern for case-insensitive file mask"""
1363 return '*.%s;*.%s' % (ext.lower(), ext.upper())
1366 """!Load named settings"""
1367 name = event.GetString()
1369 GError(parent = self,
1370 message = _(
"Settings <%s> not found") % name)
1375 self.
OnSetDsn(event =
None, path = data[1])
1376 self.creationOpt.SetValue(data[3])
1379 """!Save settings"""
1380 dlg = wx.TextEntryDialog(parent = self,
1381 message = _(
"Name:"),
1382 caption = _(
"Save settings"))
1383 if dlg.ShowModal() != wx.ID_OK:
1387 if not dlg.GetValue():
1388 GMessage(parent = self,
1389 message = _(
"Name not given, settings is not saved."))
1393 GMessage(parent = self,
1394 message = _(
"No data source defined, settings is not saved."))
1397 name = dlg.GetValue()
1401 dlgOwt = wx.MessageDialog(self, message = _(
"Settings <%s> already exists. "
1402 "Do you want to overwrite the settings?") % name,
1403 caption = _(
"Save settings"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1404 if dlgOwt.ShowModal() != wx.ID_YES:
1409 self.format.GetStringSelection(),
1410 self.creationOpt.GetValue())
1414 self.settingsChoice.SetStringSelection(name)
1419 """!Save settings"""
1420 name = self.settingsChoice.GetStringSelection()
1422 GMessage(parent = self,
1423 message = _(
"No settings is defined. Operation canceled."))
1426 self._settings.pop(name)
1430 def _saveSettings(self):
1431 """!Save settings into the file
1433 @return 0 on success
1434 @return -1 on failure
1438 for key, value
in self._settings.iteritems():
1439 fd.write(
'%s;%s;%s;%s\n' % (key, value[0], value[1], value[2]))
1441 GError(parent = self,
1442 message = _(
"Unable to save settings"))
1449 def _loadSettings(self):
1450 """!Load settings from the file
1452 The file is defined by self.SettingsFile.
1455 @return empty dict on error
1463 for line
in fd.readlines():
1465 lineData = line.rstrip(
'\n').
split(
';')
1466 if len(lineData) > 4:
1468 data[lineData[0]] = (lineData[1], lineData[2], lineData[3], lineData[4])
1470 data[lineData[0]] = (lineData[1], lineData[2], lineData[3],
'')
1478 self.settingsChoice.SetItems(sorted(data.keys()))
1483 """!Datasource type changed"""
1485 sel = event.GetSelection()
1487 self.source.SetSelection(sel)
1490 self.dsnSizer.Remove(win)
1497 ext = self.format.GetExtension(format)
1500 format +=
' (%s)|%s|%s (*.*)|*.*' % \
1503 format +=
'%s (*.*)|*.*' % _(
'All files')
1505 win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1506 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1507 dialogTitle=_(
'Choose file to import'),
1508 buttonText=_(
'Browse'),
1509 startDirectory=os.getcwd(),
1528 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1529 pos = (1, 1), span = (1, 3))
1535 self.format.Enable(
False)
1536 self.creationOpt.Enable(
False)
1537 self.parent.btnOk.Enable(
True)
1539 if not win.IsEnabled():
1541 if not self.format.IsEnabled():
1542 self.format.Enable(
True)
1543 self.creationOpt.Enable(
True)
1546 if self.parent.GetName() ==
'MultiImportDialog':
1547 self.parent.list.DeleteAllItems()
1551 self.
OnSetFormat(event =
None, format =
'GeoTIFF')
1553 self.
OnSetFormat(event =
None, format =
'ESRI Shapefile')
1556 if not self.extension.IsShown():
1557 self.extensionText.Show()
1558 self.extension.Show()
1560 if self.extension.IsShown():
1561 self.extensionText.Hide()
1562 self.extension.Hide()
1564 self.dsnSizer.Layout()
1567 """!Get datasource name
1569 if self.format.GetStringSelection() ==
'PostgreSQL':
1570 dsn =
'PG:dbname=%s' % self.
input[self.
dsnType][1].GetStringSelection()
1577 """!Input DXF file/OGR dsn defined, update list of layer
1580 path = event.GetString()
1582 if self.format.GetStringSelection() ==
'PostgreSQL':
1583 for item
in path.split(
':', 1)[1].
split(
','):
1584 key, value = item.split(
'=', 1)
1586 if not self.
input[self.
dsnType][1].SetStringSelection(value):
1587 GMessage(_(
"Database <%s> not accessible.") % value,
1595 self.parent.btnOk.Enable(
False)
1599 self.parent.btnOk.Enable(
True)
1606 def _reloadLayers(self):
1607 """!Reload list of layers"""
1622 self.parent.list.LoadData()
1623 if hasattr(self,
"btn_run"):
1624 self.btn_run.Enable(
False)
1628 for line
in ret.split(
','):
1629 layerName = line.strip()
1631 data.append((layerId, layerName, grassName))
1635 baseName = os.path.basename(dsn)
1637 data.append((layerId, baseName, grassName))
1639 ext = self.extension.GetValue()
1641 baseName = os.path.basename(filename)
1643 data.append((layerId, baseName, grassName))
1648 evt = wxGdalSelect(dsn = dsn)
1650 wx.PostEvent(self.
parent, evt)
1652 if self.parent.GetName() ==
'MultiImportDialog':
1653 self.parent.list.LoadData(data)
1655 self.parent.btn_run.Enable(
True)
1657 self.parent.btn_run.Enable(
False)
1660 """!Extension changed"""
1666 """!Format changed"""
1667 if self.
dsnType not in [
'file',
'dir',
'db']:
1671 self.dsnSizer.Remove(win)
1679 format = event.GetString()
1681 self.format.SetStringSelection(format)
1685 ext = self.format.GetExtension(format)
1688 format +=
' (%s)|%s|%s (*.*)|*.*' % \
1691 format +=
'%s (*.*)|*.*' % _(
'All files')
1693 win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1694 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1695 dialogTitle=_(
'Choose file'),
1696 buttonText=_(
'Browse'),
1697 startDirectory=os.getcwd(),
1705 if format ==
'SQLite' or format ==
'Rasterlite':
1706 win = self.
input[
'db-win'][
'file']
1707 elif format ==
'PostgreSQL' or format ==
'PostGIS WKT Raster driver':
1708 if grass.find_program(
'psql', [
'--help']):
1709 win = self.
input[
'db-win'][
'choice']
1710 if not win.GetItems():
1711 p = grass.Popen([
'psql',
'-ltA'], stdout = grass.PIPE)
1712 ret = p.communicate()[0]
1715 for line
in ret.splitlines():
1716 sline = line.split(
'|')
1723 if self.
dest and win.GetStringSelection():
1724 self.parent.btnOk.Enable(
True)
1726 win = self.
input[
'db-win'][
'text']
1728 win = self.
input[
'db-win'][
'text']
1731 if not win.IsShown():
1734 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1735 pos = (1, 1), span = (1, 3))
1736 self.dsnSizer.Layout()
1746 """!Get source type"""
1750 """!Get list of DSN windows"""
1752 for stype
in (
'file',
'dir',
'pro'):
1753 win.append(self.
input[stype][1])
1754 for stype
in (
'file',
'text',
'choice'):
1755 win.append(self.
input[
'db-win'][stype])
1760 """!Get format as string"""
1761 return self.format.GetStringSelection().replace(
' ',
'_')
1764 """!Get format extension"""
1765 return self.format.GetExtension(self.format.GetStringSelection())
1768 """!Get creation options"""
1769 if not self.creationOpt.IsShown():
1772 return self.creationOpt.GetValue()
1775 """!Widget for selecting input raster/vector map used by
1776 r.proj/v.proj modules."""
1777 def __init__(self, parent, isRaster, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
1779 super(ProjSelect, self).
__init__(parent, id, size = size,
1780 style = wx.CB_READONLY, **kwargs)
1781 self.SetName(
"ProjSelect")
1785 """!Update list of maps
1789 dbase = grass.gisenv()[
'GISDBASE']
1791 mapset = grass.gisenv()[
'MAPSET']
1798 location = location,
1806 location = location,
1810 for line
in ret.splitlines():
1811 listMaps.append(line.strip())
1814 self.SetItems(listMaps)
1818 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
1820 """!Widget for selecting GIS element
1822 @param parent parent window
1824 super(ElementSelect, self).
__init__(parent, id, size = size,
1826 self.SetName(
"ElementSelect")
1828 task = gtask.parse_interface(
'g.list')
1829 p = task.get_param(value =
'type')
1832 self.SetItems(self.
values)
1837 @param name element name
def InsertTableColumns
Insert table columns.
def GetListOfLocations
Get list of GRASS locations in given dbase.
def SetElementList
Set element list.
def __init__
Custom to create a ComboBox with a tree control to display and select vector maps.
def GetFormat
Get format as string.
def GetDbSettings
Get database settins.
def GetSettingsPath
Get full path to the settings directory.
def _selectionChanged
Selection changed, store value.
def __init__
Custom control to create a ComboBox with a tree control to display and select GIS elements within ace...
def UpdateItems
Update list of locations.
def GetDsnWin
Get list of DSN windows.
Creates combo box for selecting data layers defined for vector.
def _saveSettings
Save settings into the file.
def _reloadLayers
Reload list of layers.
def GetDsn
Get datasource name.
def GetElementList
Load elements.
def GetListOfMapsets
Get list of mapsets in given GRASS location.
def _CheckDBConnection
Check DB connection.
def GetTableDesc
Get table columns.
def OnSetDsn
Input DXF file/OGR dsn defined, update list of layer widget.
def Select
Select value (currently selected or default)
def __init__
Widget for selecting GDAL/OGR datasource, format.
def OnSettingsDelete
Save settings.
def SetType
Param set element type for widget.
def _DescribeTables
Describe linked tables.
def _loadSettings
Load settings from the file.
def Insert
Insert subgroups for defined group.
def split
Platform spefic shlex.split.
def GetFormats
Get GDAL/OGR formats.
def OnSetFormat
Format changed.
Widget for selecting input raster/vector map used by r.proj/v.proj modules.
def UpdateItems
Update list of mapsets for given location.
Creates combo box for selecting attribute tables from the database.
Widget for selecting GRASS Database.
Creates combo box for selecting database driver.
def OnSetExtension
Extension changed.
def InsertTables
Insert attribute tables into combobox.
def GetKeyColumn
Get key column of given layer.
def _isElement
Check if element should be filtered out.
def GetTable
Get table name of given layer.
def GetValue
Translate value.
def _getExtPatternGlob
Get pattern for case-insensitive globing.
Widget for selecting GRASS location.
def ListSortLower
Sort list items (not case-sensitive)
def GetValidLayerName
Make layer name SQL compliant, based on G_str_to_sql()
def OnSettingsLoad
Load named settings.
def OnSetType
Datasource type changed.
def InsertLayers
Insert layers for a vector into the layer combobox.
def OnSettingsSave
Save settings.
Widget for selecting GRASS mapset.
Widget for selecting subgroups.
def _getExtPattern
Get pattern for case-insensitive file mask.
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 GetAllVectorLayers
Returns list of all vector layers as strings.
def GetOptions
Get creation options.
def InsertColumns
Insert columns for a vector attribute table into the columns combobox.
def __init__
Widget for selecting GIS element.
Class providing information about attribute tables linked to a vector map.
def GetName
Get vector name.
def UpdateItems
Update list of maps.
def GetFormatExt
Get format extension.
def OnKeyUp
Shows popupwindow if down arrow key is released.
def GetType
Get source type.
def RunCommand
Run GRASS command.