4 @brief Custom control that selects elements
24 (C) 2007-2011 by the GRASS Development Team This program is free
25 software under the GNU General Public License (>=v2). Read the file
26 COPYING that comes with GRASS for details.
28 @author Michael Barton
29 @author Martin Landa <landa.martin gmail.com>
30 @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
39 import wx.lib.filebrowsebutton
as filebrowse
40 from wx.lib.newevent
import NewEvent
44 sys.path.append(os.path.join(globalvar.ETCDIR,
"python"))
50 from preferences
import globalSettings
as UserSettings
51 from debug
import Debug
53 wxGdalSelect, EVT_GDALSELECT = NewEvent()
56 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
57 type =
None, multiple =
False, mapsets =
None,
58 updateOnPopup =
True, onPopup =
None):
59 """!Custom control to create a ComboBox with a tree control to
60 display and select GIS elements within acessible mapsets.
61 Elements can be selected with mouse. Can allow multiple
62 selections, when argument multiple=True. Multiple selections
63 are separated by commas.
65 @param type type of GIS elements ('raster, 'vector', ...)
66 @param multiple multiple input allowed?
67 @param mapsets force list of mapsets (otherwise search path)
68 @param updateOnPopup True for updating list of elements on popup
69 @param onPopup function to be called on Popup
71 wx.combo.ComboCtrl.__init__(self, parent=parent, id=id, size=size)
72 self.GetChildren()[0].SetName(
"Select")
73 self.GetChildren()[0].type = type
76 self.SetPopupControl(self.
tcp)
77 self.SetPopupExtents(0, 100)
79 self.tcp.SetData(type = type, mapsets = mapsets,
81 updateOnPopup = updateOnPopup, onPopup = onPopup)
82 self.GetChildren()[0].Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
85 """!Shows popupwindow if down arrow key is released"""
86 if event.GetKeyCode() == wx.WXK_DOWN:
94 @param type GIS element type
95 @param mapsets list of acceptable mapsets (None for all in search path)
97 self.tcp.SetData(type = type, mapsets = mapsets)
101 self.tcp.GetElementList()
103 def SetType(self, etype, multiple = False, mapsets = None,
104 updateOnPopup =
True, onPopup =
None):
105 """!Param set element type for widget
107 @param etype element type, see gselect.ElementSelect
109 self.tcp.SetData(type = etype, mapsets = mapsets,
111 updateOnPopup = updateOnPopup, onPopup = onPopup)
115 """!Custom to create a ComboBox with a tree control to display and
116 select vector maps. Control allows to filter vector maps. If you
117 don't need this feature use Select class instead
119 @ftype filter vector maps based on feature type
121 Select.__init__(self, parent = parent, id = wx.ID_ANY,
122 type =
'vector', **kwargs)
129 def _isElement(self, vectorName):
130 """!Check if element should be filtered out"""
132 if int(grass.vector_info_topo(vectorName)[self.
ftype]) < 1:
140 """!Create a tree ComboBox for selecting maps and other GIS elements
141 in accessible mapsets within the current location
156 self.
seltree = wx.TreeCtrl(parent, style=wx.TR_HIDE_ROOT
161 |wx.TR_FULL_ROW_HIGHLIGHT)
162 self.seltree.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
163 self.seltree.Bind(wx.EVT_MOTION, self.
OnMotion)
164 self.seltree.Bind(wx.EVT_LEFT_DOWN, self.
OnLeftDown)
165 self.seltree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.
mapsetExpanded)
169 self.seltree.Bind(wx.EVT_TREE_DELETE_ITEM,
lambda x:
None)
190 """!Get value as a string separated by commas"""
191 return ','.join(self.
value)
194 """!Set filter for GIS elements, see e.g. VectorSelect"""
198 """!Limited only for first selected"""
210 inputText = self.GetCombo().GetValue().strip()
212 root = self.seltree.GetRootItem()
213 match = self.
FindItem(root, inputText, startLetters =
True)
214 self.seltree.EnsureVisible(match)
215 self.seltree.SelectItem(match)
219 """!Get filtered list of GIS elements in accessible mapsets
220 and display as tree with all relevant elements displayed
221 beneath each mapset branch
224 self.seltree.DeleteAllItems()
227 if len(self.
value) > 0:
228 root = self.seltree.GetRootItem()
233 self.seltree.EnsureVisible(item)
234 self.seltree.SelectItem(item)
240 root = self.seltree.GetRootItem()
244 winValue = self.GetCombo().GetValue().strip(
',')
247 self.
value = winValue.split(
',')
250 self.value.append(found)
251 self.seltree.SelectItem(found)
254 """!Reads UserSettings to get height (which was 200 in old implementation).
256 height = UserSettings.Get(group =
'appearance', key =
'gSelectPopupHeight', subkey =
'value')
257 return wx.Size(minWidth,
min(height, maxHeight))
259 def _getElementList(self, element, mapsets = None, elements = None, exclude = False):
260 """!Get list of GIS elements in accessible mapsets and display as tree
261 with all relevant elements displayed beneath each mapset branch
263 @param element GIS element
264 @param mapsets list of acceptable mapsets (None for all mapsets in search path)
265 @param elements list of forced GIS elements
266 @param exclude True to exclude, False for forcing the list (elements)
269 curr_mapset = grass.gisenv()[
'MAPSET']
272 elementdict = {
'cell':
'rast',
275 'raster files':
'rast',
279 'raster3D files':
'rast3d',
282 'binary vector files':
'vect',
285 'old vector':
'oldvect',
286 'dig_ascii':
'asciivect',
287 'asciivect':
'asciivect',
288 'asciivector':
'asciivect',
289 'ascii vector files':
'asciivect',
292 'paint icon files':
'icon',
293 'paint/labels':
'labels',
296 'paint label files':
'labels',
297 'site_lists':
'sites',
300 'site list files':
'sites',
303 'region definition':
'region',
304 'region definition files':
'region',
305 'windows3d':
'region3d',
306 'region3d':
'region3d',
307 'region3D definition':
'region3d',
308 'region3D definition files':
'region3d',
310 'imagery group':
'group',
311 'imagery group files':
'group',
314 '3D viewing parameters':
'3dview',
315 '3D view parameters':
'3dview'}
317 if element
not in elementdict:
318 self.
AddItem(_(
'Not selectable element'))
321 if globalvar.have_mlist:
322 filesdict = grass.mlist_grouped(elementdict[element],
323 check_search_path =
False)
325 filesdict = grass.list_grouped(elementdict[element],
326 check_search_path =
False)
330 mapsets = grass.mapsets(search_path =
True)
333 if curr_mapset
in mapsets
and mapsets[0] != curr_mapset:
334 mapsets.remove(curr_mapset)
335 mapsets.insert(0, curr_mapset)
338 for mapset
in mapsets:
339 mapset_node = self.
AddItem(_(
'Mapset') +
': ' + mapset)
341 first_mapset = mapset_node
343 self.seltree.SetItemTextColour(mapset_node, wx.Colour(50, 50, 200))
344 if mapset
not in filesdict:
347 elem_list = filesdict[mapset]
349 for elem
in elem_list:
351 fullqElem = elem +
'@' + mapset
352 if elements
is not None:
353 if (exclude
and fullqElem
in elements)
or \
354 (
not exclude
and fullqElem
not in elements):
359 self.
AddItem(elem, parent = mapset_node)
361 self.
AddItem(elem, parent = mapset_node)
362 except StandardError, e:
363 sys.stderr.write(_(
"GSelect: invalid item: %s") % e)
366 if self.seltree.ItemHasChildren(mapset_node):
367 sel = UserSettings.Get(group=
'appearance', key=
'elementListExpand',
372 if mapset
in (
'PERMANENT', curr_mapset):
375 if mapset ==
'PERMANENT':
378 if mapset == curr_mapset:
386 self.seltree.Collapse(mapset_node)
388 self.seltree.Expand(mapset_node)
392 self.seltree.SelectItem(first_mapset)
395 def FindItem(self, parentItem, text, startLetters = False):
396 """!Finds item with given name or starting with given text"""
397 startletters = startLetters
398 item, cookie = self.seltree.GetFirstChild(parentItem)
399 while wx.TreeItemId.IsOk(item):
400 if self.seltree.GetItemText(item) == text:
402 if self.seltree.ItemHasChildren(item):
403 item = self.
FindItem(item, text, startLetters = startletters)
404 if wx.TreeItemId.IsOk(item):
406 elif startletters
and self.seltree.GetItemText(item).startswith(text.split(
'@', 1)[0]):
408 item, cookie = self.seltree.GetNextChild(parentItem, cookie)
409 return wx.TreeItemId()
413 root = self.seltree.GetRootItem()
415 root = self.seltree.AddRoot(
"<hidden root>")
418 item = self.seltree.AppendItem(parent, text=value)
423 """!Enables to select items using keyboard"""
425 item = self.seltree.GetSelection()
426 if event.GetKeyCode() == wx.WXK_DOWN:
427 self.seltree.SelectItem(self.seltree.GetNextVisible(item))
430 elif event.GetKeyCode() == wx.WXK_UP:
431 if self.seltree.ItemHasChildren(item)
and self.seltree.IsExpanded(self.seltree.GetPrevSibling(item)):
432 itemPrev = self.seltree.GetLastChild(self.seltree.GetPrevSibling(item))
434 itemPrev = self.seltree.GetPrevSibling(item)
435 if not wx.TreeItemId.IsOk(itemPrev):
436 itemPrev = self.seltree.GetItemParent(item)
437 if item == self.seltree.GetFirstChild(self.seltree.GetRootItem())[0]:
439 self.seltree.SelectItem(itemPrev)
442 elif event.GetKeyCode() == wx.WXK_TAB:
443 selected = self.seltree.GetSelection()
444 if self.seltree.ItemHasChildren(selected):
447 parent = self.seltree.GetItemParent(selected)
448 nextSibling = self.seltree.GetNextSibling(parent)
449 if wx.TreeItemId.IsOk(nextSibling):
450 match = self.
FindItem(nextSibling, self.GetCombo().GetValue().strip(),
True)
452 match = self.
FindItem(self.seltree.GetFirstChild(self.seltree.GetItemParent(parent))[0],
453 self.GetCombo().GetValue().strip(),
True)
454 self.seltree.SelectItem(match)
456 elif event.GetKeyCode() == wx.WXK_RIGHT:
457 if self.seltree.ItemHasChildren(item):
458 self.seltree.Expand(item)
460 elif event.GetKeyCode() == wx.WXK_LEFT:
461 if self.seltree.ItemHasChildren(item):
462 self.seltree.Collapse(item)
464 elif event.GetKeyCode() == wx.WXK_ESCAPE:
467 elif event.GetKeyCode() == wx.WXK_RETURN:
468 if self.seltree.GetRootItem() == self.seltree.GetItemParent(item):
471 mapsetItem = self.seltree.GetItemParent(item)
472 fullName = self.seltree.GetItemText(item) +
'@' + \
473 self.seltree.GetItemText(mapsetItem).
split(
':', -1)[1].strip()
477 self.value.append(fullName)
479 self.
value = [fullName]
484 """!Have the selection follow the mouse, like in a real combobox
486 item, flags = self.seltree.HitTest(evt.GetPosition())
487 if item
and flags & wx.TREE_HITTEST_ONITEMLABEL:
488 self.seltree.SelectItem(item)
493 """!Do the combobox selection
495 item, flags = self.seltree.HitTest(evt.GetPosition())
496 if item
and flags & wx.TREE_HITTEST_ONITEMLABEL:
499 if self.seltree.GetRootItem() == self.seltree.GetItemParent(item):
502 mapsetItem = self.seltree.GetItemParent(item)
503 fullName = self.seltree.GetItemText(item) +
'@' + \
504 self.seltree.GetItemText(mapsetItem).
split(
':', -1)[1].strip()
508 self.value.append(fullName)
510 self.
value = [fullName]
517 """!Set object properties"""
519 self.
type = kargs[
'type']
520 if 'mapsets' in kargs:
521 self.
mapsets = kargs[
'mapsets']
522 if 'multiple' in kargs:
524 if 'updateOnPopup' in kargs:
526 if 'onPopup' in kargs:
527 self.
onPopup = kargs[
'onPopup']
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")
668 """!Insert layers for a vector into the layer combobox
670 @param vector name of vector map
673 layers = utils.GetVectorNumberOfLayers(vector)
684 layers.insert(0, str(self.
default))
685 elif self.
default not in layers:
689 self.SetItems(layers)
693 items = self.GetItems()
696 self.SetStringSelection(
'-1')
703 """!Creates combo box for selecting database driver.
705 def __init__(self, parent, choices, value,
706 id=wx.ID_ANY, pos=wx.DefaultPosition,
707 size=globalvar.DIALOG_LAYER_SIZE, **kargs):
709 super(DriverSelect, self).
__init__(parent, id, value, pos, size,
710 choices, style=wx.CB_READONLY)
712 self.SetName(
"DriverSelect")
714 self.SetStringSelection(value)
717 """!Creates combo box for selecting database driver.
719 def __init__(self, parent, value='',
720 id=wx.ID_ANY, pos=wx.DefaultPosition,
721 size=globalvar.DIALOG_TEXTCTRL_SIZE, **kargs):
723 super(DatabaseSelect, self).
__init__(parent, id, value, pos, size)
725 self.SetName(
"DatabaseSelect")
728 """!Creates combo box for selecting attribute tables from the database
731 id=wx.ID_ANY, value=
'', pos=wx.DefaultPosition,
732 size=globalvar.DIALOG_COMBOBOX_SIZE,
735 super(TableSelect, self).
__init__(parent, id, value, pos, size, choices,
736 style=wx.CB_READONLY)
738 self.SetName(
"TableSelect")
744 """!Insert attribute tables into combobox"""
747 if not driver
or not database:
748 connect = grass.db_connection()
750 driver = connect[
'driver']
751 database = connect[
'database']
753 ret = gcmd.RunCommand(
'db.tables',
760 for table
in ret.splitlines():
767 """!Creates combo box for selecting columns in the attribute table
770 @param parent window parent
772 @param value default value
773 @param size window size
774 @param vector vector map name
775 @param layer layer number
776 @param param parameters list (see menuform.py)
777 @param **kwags wx.ComboBox parameters
779 def __init__(self, parent, id = wx.ID_ANY, value = '',
780 size=globalvar.DIALOG_COMBOBOX_SIZE,
781 vector =
None, layer = 1, param =
None, **kwargs):
785 super(ColumnSelect, self).
__init__(parent, id, value, size = size, **kwargs)
786 self.SetName(
"ColumnSelect")
791 def InsertColumns(self, vector, layer, excludeKey = False, type = None, dbInfo = None):
792 """!Insert columns for a vector attribute table into the columns combobox
794 @param vector vector name
795 @param layer vector layer number
796 @param excludeKey exclude key column from the list?
797 @param type only columns of given type (given as list)
803 table = dbInfo.GetTable(int(layer))
804 columnchoices = dbInfo.GetTableDesc(table)
805 keyColumn = dbInfo.GetKeyColumn(int(layer))
806 columns = len(columnchoices.keys()) * [
'']
807 for key, val
in columnchoices.iteritems():
808 columns[val[
'index']] = key
810 columns.remove(keyColumn)
812 for key, value
in columnchoices.iteritems():
813 if value[
'type']
not in type:
815 except (KeyError, ValueError):
818 self.SetItems(columns)
822 self.
param[
'value'] =
''
825 """!Insert table columns
827 @param table table name
828 @param driver driver name
829 @param database database name
833 ret = gcmd.RunCommand(
'db.columns',
840 columns = ret.splitlines()
842 self.SetItems(columns)
846 self.
param[
'value'] =
''
849 """!Widget for selecting GRASS Database"""
851 super(DbaseSelect, self).
__init__(parent, id = wx.ID_ANY,
852 size = globalvar.DIALOG_GSELECT_SIZE, labelText =
'',
853 dialogTitle = _(
'Choose GIS Data Directory'),
854 buttonText = _(
'Browse'),
855 startDirectory = grass.gisenv()[
'GISDBASE'],
859 """!Widget for selecting GRASS location"""
860 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
861 gisdbase =
None, **kwargs):
862 super(LocationSelect, self).
__init__(parent, id, size = size,
863 style = wx.CB_READONLY, **kwargs)
864 self.SetName(
"LocationSelect")
871 self.SetItems(utils.GetListOfLocations(self.
gisdbase))
874 """!Update list of locations
876 @param dbase path to GIS database
880 self.SetItems(utils.GetListOfLocations(self.
gisdbase))
885 """!Widget for selecting GRASS mapset"""
886 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
887 gisdbase =
None, location =
None, setItems =
True, **kwargs):
888 super(MapsetSelect, self).
__init__(parent, id, size = size,
889 style = wx.CB_READONLY, **kwargs)
891 self.SetName(
"MapsetSelect")
903 self.SetItems(utils.GetListOfMapsets(self.
gisdbase, self.
location, selectable =
False))
906 """!Update list of mapsets for given location
908 @param dbase path to GIS database (None to use currently selected)
909 @param location name of location
915 self.SetItems(utils.GetListOfMapsets(self.
gisdbase, self.
location, selectable =
False))
920 """!Widget for selecting subgroups"""
921 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
923 super(SubGroupSelect, self).
__init__(parent, id, size = size,
924 style = wx.CB_READONLY, **kwargs)
925 self.SetName(
"SubGroupSelect")
928 """!Insert subgroups for defined group"""
931 gisenv = grass.gisenv()
933 name, mapset = group.split(
'@', 1)
936 mapset = gisenv[
'MAPSET']
938 path = os.path.join(gisenv[
'GISDBASE'], gisenv[
'LOCATION_NAME'], mapset,
939 'group', name,
'subgroup')
941 self.SetItems(os.listdir(path))
947 def __init__(self, parent, ogr = False,
948 sourceType =
None, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
950 """!Widget for selecting external (GDAL/OGR) format
952 @param parent parent window
953 @param sourceType source type ('file', 'directory', 'database', 'protocol') or None
954 @param ogr True for OGR otherwise GDAL
956 super(FormatSelect, self).
__init__(parent, id, size = size,
958 self.SetName(
"FormatSelect")
966 for f
in utils.GetFormats()[ftype].values():
968 self.SetItems(formats)
971 """!Get file extension by format name"""
975 'Erdas Imagine Images (.img)' :
'img',
976 'Ground-based SAR Applications Testbed File Format (.gff)' :
'gff',
977 'Arc/Info Binary Grid' :
'adf',
978 'Portable Network Graphics' :
'png',
980 'Japanese DEM (.mem)' :
'mem',
981 'Graphics Interchange Format (.gif)' :
'gif',
982 'X11 PixMap Format' :
'xpm',
983 'MS Windows Device Independent Bitmap' :
'bmp',
984 'SPOT DIMAP' :
'dim',
985 'RadarSat 2 XML Product' :
'xml',
986 'EarthWatch .TIL' :
'til',
987 'ERMapper .ers Labelled' :
'ers',
988 'ERMapper Compressed Wavelets' :
'ecw',
989 'GRIdded Binary (.grb)' :
'grb',
990 'EUMETSAT Archive native (.nat)' :
'nat',
991 'Idrisi Raster A.1' :
'rst',
992 'Golden Software ASCII Grid (.grd)' :
'grd',
993 'Golden Software Binary Grid (.grd)' :
'grd',
994 'Golden Software 7 Binary Grid (.grd)' :
'grd',
995 'R Object Data Store' :
'r',
996 'USGS DOQ (Old Style)' :
'doq',
997 'USGS DOQ (New Style)' :
'doq',
998 'ENVI .hdr Labelled' :
'hdr',
999 'ESRI .hdr Labelled' :
'hdr',
1000 'Generic Binary (.hdr Labelled)' :
'hdr',
1001 'PCI .aux Labelled' :
'aux',
1002 'EOSAT FAST Format' :
'fst',
1003 'VTP .bt (Binary Terrain) 1.3 Format' :
'bt',
1004 'FARSITE v.4 Landscape File (.lcp)' :
'lcp',
1005 'Swedish Grid RIK (.rik)' :
'rik',
1006 'USGS Optional ASCII DEM (and CDED)' :
'dem',
1007 'Northwood Numeric Grid Format .grd/.tab' :
'',
1008 'Northwood Classified Grid Format .grc/.tab' :
'',
1009 'ARC Digitized Raster Graphics' :
'arc',
1010 'Magellan topo (.blx)' :
'blx',
1011 'SAGA GIS Binary Grid (.sdat)' :
'sdat',
1013 'ESRI Shapefile' :
'shp',
1030 'Geoconcept' :
'gxt',
1032 'GPSTrackMaker' :
'gtm',
1037 return formatToExt[name]
1042 def __init__(self, parent, panel, ogr = False,
1046 """!Widget for selecting GDAL/OGR datasource, format
1048 @param parent parent window
1049 @param ogr use OGR selector instead of GDAL
1053 wx.Panel.__init__(self, parent = panel, id = wx.ID_ANY)
1056 label=
" %s " % _(
"Settings"))
1058 self.
inputBox = wx.StaticBox(parent = self, id=wx.ID_ANY,
1059 label=
" %s " % _(
"Source"))
1068 if 'file' not in exclude:
1069 sources.append(_(
"File"))
1072 if 'directory' not in exclude:
1073 sources.append(_(
"Directory"))
1076 if 'database' not in exclude:
1077 sources.append(_(
"Database"))
1080 if 'protocol' not in exclude:
1081 sources.append(_(
"Protocol"))
1087 self.
settingsFile = os.path.join(utils.GetSettingsPath(),
'wxGDAL')
1092 self.settingsChoice.SetItems(self._settings.keys())
1096 self.
source = wx.RadioBox(parent = self, id = wx.ID_ANY,
1097 label = _(
'Source type'),
1098 style = wx.RA_SPECIFY_COLS,
1100 self.source.SetSelection(0)
1101 self.source.Bind(wx.EVT_RADIOBOX, self.
OnSetType)
1105 filemask =
'GeoTIFF (%s)|%s|%s (*.*)|*.*' % \
1108 filemask =
'ESRI Shapefile (%s)|%s|%s (*.*)|*.*' % \
1111 dsnFile = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1112 size=globalvar.DIALOG_GSELECT_SIZE, labelText =
'',
1113 dialogTitle=_(
'Choose file to import'),
1114 buttonText=_(
'Browse'),
1115 startDirectory=os.getcwd(),
1120 dsnDir = filebrowse.DirBrowseButton(parent=self, id=wx.ID_ANY,
1121 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1122 dialogTitle=_(
'Choose input directory'),
1123 buttonText=_(
'Browse'),
1124 startDirectory=os.getcwd(),
1126 dsnDir.SetName(
'GdalSelect')
1129 dsnDbFile = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1130 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1131 dialogTitle=_(
'Choose file'),
1132 buttonText=_(
'Browse'),
1133 startDirectory=os.getcwd(),
1136 dsnDbFile.SetName(
'GdalSelect')
1138 dsnDbText = wx.TextCtrl(parent = self, id = wx.ID_ANY)
1140 dsnDbText.Bind(wx.EVT_TEXT, self.
OnSetDsn)
1141 dsnDbText.SetName(
'GdalSelect')
1143 dsnDbChoice = wx.Choice(parent = self, id = wx.ID_ANY)
1145 dsnDbChoice.Bind(wx.EVT_CHOICE, self.
OnSetDsn)
1146 dsnDbChoice.SetName(
'GdalSelect')
1148 dsnPro = wx.TextCtrl(parent = self, id = wx.ID_ANY)
1150 dsnPro.Bind(wx.EVT_TEXT, self.
OnSetDsn)
1151 dsnPro.SetName(
'GdalSelect')
1159 self.extension.Hide()
1167 utils.GetFormats()[fType][
'file']],
1168 'dir' : [_(
"Directory:"),
1170 utils.GetFormats()[fType][
'file']],
1171 'db' : [_(
"Database:"),
1173 utils.GetFormats()[fType][
'database']],
1174 'pro' : [_(
"Protocol:"),
1176 utils.GetFormats()[fType][
'protocol']],
1177 'db-win' : {
'file' : dsnDbFile,
1179 'choice' : dsnDbChoice },
1186 self.
dsnText = wx.StaticText(parent = self, id = wx.ID_ANY,
1190 label = _(
"Extension:"))
1191 self.extensionText.Hide()
1196 self.
OnSetFormat(event =
None, format =
'GeoTIFF')
1198 self.
OnSetFormat(event =
None, format =
'ESRI Shapefile')
1202 mainSizer = wx.BoxSizer(wx.VERTICAL)
1204 settingsSizer = wx.StaticBoxSizer(self.
settingsBox, wx.HORIZONTAL)
1205 settingsSizer.Add(item = wx.StaticText(parent = self,
1207 label = _(
"Load settings:")),
1208 flag = wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
1217 inputSizer = wx.StaticBoxSizer(self.
inputBox, wx.HORIZONTAL)
1220 self.dsnSizer.AddGrowableRow(1)
1221 self.dsnSizer.AddGrowableCol(3)
1223 self.dsnSizer.Add(item=self.
dsnText,
1224 flag=wx.ALIGN_CENTER_VERTICAL,
1227 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1228 pos = (0, 1), span = (1, 3))
1230 self.dsnSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
1231 label = _(
"Format:")),
1232 flag = wx.ALIGN_CENTER_VERTICAL,
1234 self.dsnSizer.Add(item=self.
format,
1235 flag = wx.ALIGN_CENTER_VERTICAL,
1238 flag=wx.ALIGN_CENTER_VERTICAL,
1241 flag = wx.ALIGN_CENTER_VERTICAL,
1244 inputSizer.Add(item=self.
dsnSizer, proportion=1,
1245 flag=wx.EXPAND | wx.ALL)
1247 mainSizer.Add(item=settingsSizer, proportion=0,
1248 flag=wx.ALL | wx.EXPAND, border=5)
1249 mainSizer.Add(item=self.
source, proportion=0,
1250 flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=5)
1251 mainSizer.Add(item=inputSizer, proportion=0,
1252 flag=wx.ALL | wx.EXPAND, border=5)
1254 self.SetSizer(mainSizer)
1257 def _getExtPatternGlob(self, ext):
1258 """!Get pattern for case-insensitive globing"""
1261 pattern +=
'[%s%s]' % (c.lower(), c.upper())
1264 def _getExtPattern(self, ext):
1265 """!Get pattern for case-insensitive file mask"""
1266 return '*.%s;*.%s' % (ext.lower(), ext.upper())
1269 """!Load named settings"""
1270 name = event.GetString()
1273 message = _(
"Settings named '%s' not found") % name)
1278 self.
OnSetDsn(event =
None, path = data[1])
1281 """!Save settings"""
1282 dlg = wx.TextEntryDialog(parent = self,
1283 message = _(
"Name:"),
1284 caption = _(
"Save settings"))
1285 if dlg.ShowModal() != wx.ID_OK:
1288 if not dlg.GetValue():
1290 message = _(
"Name not given, settings is not saved."))
1293 name = dlg.GetValue()
1296 fd.write(name +
';' + self.
dsnType +
';' +
1298 self.format.GetStringSelection())
1302 message = _(
"Unable to save settings"))
1307 self.settingsChoice.Append(name)
1308 self.settingsChoice.SetStringSelection(name)
1312 def _loadSettings(self):
1313 """!Load settings from the file
1315 The file is defined by self.SettingsFile.
1318 @return empty dict on error
1326 for line
in fd.readlines():
1328 name, ftype, dsn, format = line.rstrip(
'\n').
split(
';')
1329 data[name] = (ftype, dsn, format)
1340 """!Datasource type changed"""
1342 sel = event.GetSelection()
1344 self.source.SetSelection(sel)
1347 self.dsnSizer.Remove(win)
1353 ext = self.format.GetExtension(format)
1356 format +=
' (%s)|%s|%s (*.*)|*.*' % \
1359 format +=
'%s (*.*)|*.*' % _(
'All files')
1361 win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1362 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1363 dialogTitle=_(
'Choose file to import'),
1364 buttonText=_(
'Browse'),
1365 startDirectory=os.getcwd(),
1378 if self.parent.GetName() ==
'MultiImportDialog':
1379 self.parent.list.DeleteAllItems()
1386 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1392 self.
OnSetFormat(event =
None, format =
'GeoTIFF')
1394 self.
OnSetFormat(event =
None, format =
'ESRI Shapefile')
1399 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1405 if not self.extension.IsShown():
1406 self.extensionText.Show()
1407 self.extension.Show()
1409 if self.extension.IsShown():
1410 self.extensionText.Hide()
1411 self.extension.Hide()
1413 self.dsnSizer.Layout()
1416 """!Get datasource name"""
1417 if self.format.GetStringSelection() ==
'PostgreSQL':
1418 return 'PG:dbname=%s' % self.
input[self.
dsnType][1].GetStringSelection()
1423 """!Input DXF file/OGR dsn defined, update list of layer widget"""
1425 path = event.GetString()
1427 if self.format.GetStringSelection() ==
'PostgreSQL':
1428 for item
in path.split(
':', 1)[1].
split(
','):
1429 key, value = item.split(
'=', 1)
1444 def _reloadLayers(self):
1445 """!Reload list of layers"""
1456 baseName = os.path.basename(dsn)
1457 grassName = utils.GetValidLayerName(baseName.split(
'.', -1)[0])
1458 data.append((layerId, baseName, grassName))
1460 ext = self.extension.GetValue()
1462 baseName = os.path.basename(file)
1463 grassName = utils.GetValidLayerName(baseName.split(
'.', -1)[0])
1464 data.append((layerId, baseName, grassName))
1467 ret = gcmd.RunCommand(
'v.in.ogr',
1473 self.parent.list.LoadData()
1474 if hasattr(self,
"btn_run"):
1475 self.btn_run.Enable(
False)
1478 for line
in ret.split(
','):
1479 layerName = line.strip()
1480 grassName = utils.GetValidLayerName(layerName)
1481 data.append((layerId, layerName.strip(), grassName.strip()))
1484 evt = wxGdalSelect(dsn = dsn +
'@OGR')
1486 wx.PostEvent(self.
parent, evt)
1488 if self.parent.GetName() ==
'MultiImportDialog':
1489 self.parent.list.LoadData(data)
1491 self.parent.btn_run.Enable(
True)
1493 self.parent.btn_run.Enable(
False)
1496 """!Extension changed"""
1501 """!Format changed"""
1502 if self.
dsnType not in [
'file',
'dir',
'db']:
1506 self.dsnSizer.Remove(win)
1514 format = event.GetString()
1516 self.format.SetStringSelection(format)
1520 ext = self.format.GetExtension(format)
1523 format +=
' (%s)|%s|%s (*.*)|*.*' % \
1526 format +=
'%s (*.*)|*.*' % _(
'All files')
1528 win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY,
1529 size=globalvar.DIALOG_GSELECT_SIZE, labelText=
'',
1530 dialogTitle=_(
'Choose file'),
1531 buttonText=_(
'Browse'),
1532 startDirectory=os.getcwd(),
1540 if format ==
'SQLite' or format ==
'Rasterlite':
1541 win = self.
input[
'db-win'][
'file']
1542 elif format ==
'PostgreSQL' or format ==
'PostGIS WKT Raster driver':
1543 if grass.find_program(
'psql', [
'--help']):
1544 win = self.
input[
'db-win'][
'choice']
1545 if not win.GetItems():
1546 p = grass.Popen([
'psql',
'-ltA'], stdout = grass.PIPE)
1547 ret = p.communicate()[0]
1550 for line
in ret.splitlines():
1551 sline = line.split(
'|')
1559 win = self.
input[
'db-win'][
'text']
1561 win = self.
input[
'db-win'][
'text']
1564 if not win.IsShown():
1567 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1568 pos = (0, 1), span = (1, 3))
1569 self.dsnSizer.Layout()
1578 """!Get source type"""
1583 if self.format.GetStringSelection() ==
'PostgreSQL':
1584 return 'PG:dbname=%s' % self.
input[self.
dsnType][1].GetStringSelection()
1589 """!Get list of DSN windows"""
1591 for stype
in (
'file',
'dir',
'pro'):
1592 win.append(self.
input[stype][1])
1593 for stype
in (
'file',
'text',
'choice'):
1594 win.append(self.
input[
'db-win'][stype])
1599 """!Get format extension"""
1600 return self.format.GetExtension(self.format.GetStringSelection())
1603 """!Widget for selecting input raster/vector map used by
1604 r.proj/v.proj modules."""
1605 def __init__(self, parent, isRaster, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
1607 super(ProjSelect, self).
__init__(parent, id, size = size,
1608 style = wx.CB_READONLY, **kwargs)
1609 self.SetName(
"ProjSelect")
1613 """!Update list of maps
1617 dbase = grass.gisenv()[
'GISDBASE']
1619 mapset = grass.gisenv()[
'MAPSET']
1621 ret = gcmd.RunCommand(
'r.proj',
1626 location = location,
1629 ret = gcmd.RunCommand(
'v.proj',
1634 location = location,
1638 for line
in ret.splitlines():
1639 listMaps.append(line.strip())
1640 utils.ListSortLower(listMaps)
1642 self.SetItems(listMaps)
1646 def __init__(self, parent, id = wx.ID_ANY, size = globalvar.DIALOG_COMBOBOX_SIZE,
1648 """!Widget for selecting GIS element
1650 @param parent parent window
1652 super(ElementSelect, self).
__init__(parent, id, size = size,
1654 self.SetName(
"ElementSelect")
1656 task = gtask.parse_interface(
'g.list')
1657 p = task.get_param(value =
'type')
1660 self.SetItems(self.
values)
1665 @param name element name