[GRASS-SVN] r49348 - in grass/trunk/gui/wxpython: . core gmodeler
gui_core lmgr mapdisp modules nviz psmap
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Nov 24 08:56:12 EST 2011
Author: martinl
Date: 2011-11-24 05:56:11 -0800 (Thu, 24 Nov 2011)
New Revision: 49348
Added:
grass/trunk/gui/wxpython/gmodeler/menudata.py
grass/trunk/gui/wxpython/gui_core/task.py
grass/trunk/gui/wxpython/modules/extensions.py
Modified:
grass/trunk/gui/wxpython/core/menudata.py
grass/trunk/gui/wxpython/gis_set.py
grass/trunk/gui/wxpython/gmodeler/frame.py
grass/trunk/gui/wxpython/gmodeler/model_file.py
grass/trunk/gui/wxpython/gui_core/dialogs.py
grass/trunk/gui/wxpython/gui_core/forms.py
grass/trunk/gui/wxpython/gui_core/ghelp.py
grass/trunk/gui/wxpython/gui_core/goutput.py
grass/trunk/gui/wxpython/gui_core/widgets.py
grass/trunk/gui/wxpython/lmgr/layertree.py
grass/trunk/gui/wxpython/mapdisp/frame.py
grass/trunk/gui/wxpython/modules/colorrules.py
grass/trunk/gui/wxpython/modules/histogram.py
grass/trunk/gui/wxpython/modules/mcalc_builder.py
grass/trunk/gui/wxpython/nviz/mapwindow.py
grass/trunk/gui/wxpython/psmap/frame.py
grass/trunk/gui/wxpython/wxgui.py
Log:
wxGUI major code reorganization (part 2)
Modified: grass/trunk/gui/wxpython/core/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/core/menudata.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/core/menudata.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -35,7 +35,7 @@
except ImportError:
import elementtree.ElementTree as etree # Python <= 2.4
-from wx import ID_ANY
+import wx
if not os.getenv("GISBASE"):
sys.exit("GRASS is not running. Exiting...")
@@ -75,7 +75,7 @@
if wxId != None:
wxId = eval('wx.' + wxId.text)
else:
- wxId = ID_ANY
+ wxId = wx.ID_ANY
return (label, help, handler, gcmd, keywords, shortcut, wxId)
elif mi.tag == 'menu':
return self._getMenu(mi)
@@ -212,11 +212,12 @@
menu = arg
sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "gui", "wxpython"))
+
if menu == 'manager':
- from lmgr.menudata import ManagerData
+ from lmgr.menudata import ManagerData
data = ManagerData()
else:
- from gmodeler.frame import ModelerData
+ from gmodeler.menudata import ModelerData
data = ModelerData()
if action == 'strings':
Modified: grass/trunk/gui/wxpython/gis_set.py
===================================================================
--- grass/trunk/gui/wxpython/gis_set.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gis_set.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -22,7 +22,6 @@
import os
import sys
-import glob
import shutil
import copy
import platform
@@ -32,17 +31,13 @@
import gettext
gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
-from gui_modules import globalvar
+from core import globalvar
import wx
-import wx.html
-import wx.lib.rcsizer as rcs
-import wx.lib.filebrowsebutton as filebrowse
import wx.lib.mixins.listctrl as listmix
import wx.lib.scrolledpanel as scrolled
-from gui_modules import goutput
-from gui_modules.ghelp import HelpFrame
-from gui_modules.gcmd import GMessage, GError
+from gui_core.ghelp import HelpFrame
+from core.gcmd import GMessage, GError
sys.stderr = codecs.getwriter('utf8')(sys.stderr)
@@ -369,7 +364,7 @@
rc = open(gisrc, "r")
for line in rc.readlines():
key, val = line.split(":", 1)
- grassrc[key.strip()] = utils.DecodeString(val.strip())
+ grassrc[key.strip()] = DecodeString(val.strip())
finally:
rc.close()
@@ -385,9 +380,9 @@
def OnWizard(self, event):
"""!Location wizard started"""
- from gui_modules import location_wizard
- gWizard = location_wizard.LocationWizard(parent = self,
- grassdatabase = self.tgisdbase.GetValue())
+ from location_wizard.wizard import LocationWizard
+ gWizard = LocationWizard(parent = self,
+ grassdatabase = self.tgisdbase.GetValue())
if gWizard.location != None:
self.OnSetDatabase(event)
self.UpdateMapsets(os.path.join(self.gisdbase, gWizard.location))
@@ -544,7 +539,7 @@
def UpdateLocations(self, dbase):
"""!Update list of locations"""
try:
- self.listOfLocations = utils.GetListOfLocations(dbase)
+ self.listOfLocations = GetListOfLocations(dbase)
except UnicodeEncodeError:
wx.MessageBox(parent = self, caption = _("Error"),
message = _("Unable to set GRASS database. "
@@ -566,29 +561,29 @@
self.FormerMapsetSelection = wx.NOT_FOUND # for non-selectable item
self.listOfMapsetsSelectable = list()
- self.listOfMapsets = utils.GetListOfMapsets(self.gisdbase, location)
+ self.listOfMapsets = GetListOfMapsets(self.gisdbase, location)
self.lbmapsets.Clear()
# disable mapset with denied permission
locationName = os.path.basename(location)
- ret = gcmd.RunCommand('g.mapset',
- read = True,
- flags = 'l',
- location = locationName,
- gisdbase = self.gisdbase)
+ ret = RunCommand('g.mapset',
+ read = True,
+ flags = 'l',
+ location = locationName,
+ gisdbase = self.gisdbase)
if ret:
for line in ret.splitlines():
self.listOfMapsetsSelectable += line.split(' ')
else:
- gcmd.RunCommand("g.gisenv",
- set = "GISDBASE=%s" % self.gisdbase)
- gcmd.RunCommand("g.gisenv",
- set = "LOCATION_NAME=%s" % locationName)
- gcmd.RunCommand("g.gisenv",
- set = "MAPSET=PERMANENT")
+ RunCommand("g.gisenv",
+ set = "GISDBASE=%s" % self.gisdbase)
+ RunCommand("g.gisenv",
+ set = "LOCATION_NAME=%s" % locationName)
+ RunCommand("g.gisenv",
+ set = "MAPSET=PERMANENT")
# first run only
self.listOfMapsetsSelectable = copy.copy(self.listOfMapsets)
@@ -772,12 +767,12 @@
else:
return
- gcmd.RunCommand("g.gisenv",
- set = "GISDBASE=%s" % dbase)
- gcmd.RunCommand("g.gisenv",
- set = "LOCATION_NAME=%s" % location)
- gcmd.RunCommand("g.gisenv",
- set = "MAPSET=%s" % mapset)
+ RunCommand("g.gisenv",
+ set = "GISDBASE=%s" % dbase)
+ RunCommand("g.gisenv",
+ set = "LOCATION_NAME=%s" % location)
+ RunCommand("g.gisenv",
+ set = "MAPSET=%s" % mapset)
self.Destroy()
sys.exit(0)
@@ -885,8 +880,8 @@
import gettext
gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
- import gui_modules.gcmd as gcmd
- import gui_modules.utils as utils
+ from core.gcmd import RunCommand, DecodeString
+ from core.utils import GetListOfMapsets, GetListOfLocations
GRASSStartUp = StartUp(0)
GRASSStartUp.MainLoop()
Modified: grass/trunk/gui/wxpython/gmodeler/frame.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/frame.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gmodeler/frame.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -4,7 +4,6 @@
@brief wxGUI Graphical Modeler for creating, editing, and managing models
Classes:
- - ModelerData
- ModelToolbar
- ModelFrame
- ModelCanvas
@@ -57,15 +56,6 @@
from grass.script import core as grass
-class ModelerData(MenuData):
- def __init__(self, filename = None):
- if not filename:
- gisbase = os.getenv('GISBASE')
- global etcwxdir
- filename = os.path.join(globalvar.ETCWXDIR, 'xml', 'menudata_modeler.xml')
-
- MenuData.__init__(self, filename)
-
class ModelToolbar(BaseToolbar):
"""!Graphical modeler toolbaro (see gmodeler.py)
"""
Added: grass/trunk/gui/wxpython/gmodeler/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/menudata.py (rev 0)
+++ grass/trunk/gui/wxpython/gmodeler/menudata.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -0,0 +1,28 @@
+"""!
+ at package gmodeler.menudata
+
+ at brief wxGUI Graphical Modeler - menu data
+
+Classes:
+ - ModelerData
+
+(C) 2010-2011 by the GRASS Development Team
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+
+from core import globalvar
+from core.menudata import MenuData
+
+class ModelerData(MenuData):
+ def __init__(self, filename = None):
+ if not filename:
+ gisbase = os.getenv('GISBASE')
+ filename = os.path.join(globalvar.ETCWXDIR, 'xml', 'menudata_modeler.xml')
+
+ MenuData.__init__(self, filename)
+
Property changes on: grass/trunk/gui/wxpython/gmodeler/menudata.py
___________________________________________________________________
Added: svn:mime-type
+ text/x-python
Added: svn:eol-style
+ native
Modified: grass/trunk/gui/wxpython/gmodeler/model_file.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/model_file.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gmodeler/model_file.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -19,7 +19,7 @@
import time
import re
-from gui_core.forms import GUI
+from gui_core.task import GUI
from core.gcmd import GWarning, EncodeString
class ProcessModelFile:
Modified: grass/trunk/gui/wxpython/gui_core/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/dialogs.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gui_core/dialogs.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -48,7 +48,7 @@
from core import globalvar
from core.gcmd import GError, RunCommand, GMessage
from gui_core.gselect import ElementSelect, LocationSelect, MapsetSelect, Select, OgrTypeSelect, GdalSelect
-from core.forms import GUI
+from gui_core.task import GUI
from core.utils import GetListOfMapsets, GetLayerNameFromCmd, GetValidLayerName
from core.settings import UserSettings
from core.debug import Debug
@@ -2224,37 +2224,6 @@
return filetype, ltype
-class StaticWrapText(wx.StaticText):
- """!A Static Text field that wraps its text to fit its width,
- enlarging its height if necessary.
- """
- def __init__(self, parent, id = wx.ID_ANY, label = '', *args, **kwds):
- self.parent = parent
- self.originalLabel = label
-
- wx.StaticText.__init__(self, parent, id, label = '', *args, **kwds)
-
- self.SetLabel(label)
- self.Bind(wx.EVT_SIZE, self.OnResize)
-
- def SetLabel(self, label):
- self.originalLabel = label
- self.wrappedSize = None
- self.OnResize(None)
-
- def OnResize(self, event):
- if not getattr(self, "resizing", False):
- self.resizing = True
- newSize = wx.Size(self.parent.GetSize().width - 50,
- self.GetSize().height)
- if self.wrappedSize != newSize:
- wx.StaticText.SetLabel(self, self.originalLabel)
- self.Wrap(newSize.width)
- self.wrappedSize = newSize
-
- self.SetSize(self.wrappedSize)
- del self.resizing
-
class ImageSizeDialog(wx.Dialog):
"""!Set size for saved graphic file"""
def __init__(self, parent, id = wx.ID_ANY, title = _("Set image size"),
Modified: grass/trunk/gui/wxpython/gui_core/forms.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/forms.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gui_core/forms.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -11,7 +11,6 @@
- GrassGUIApp
- GUI
- FloatValidator
- - GNotebook
This program is just a coarse approach to automatically build a GUI
from a xml-based GRASS user interface description.
@@ -46,13 +45,11 @@
"""
import sys
-import re
import string
import textwrap
import os
import time
import copy
-import locale
from threading import Thread
import Queue
@@ -65,17 +62,8 @@
import wx.lib.colourselect as csel
import wx.lib.filebrowsebutton as filebrowse
import wx.lib.scrolledpanel as scrolled
-from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
from wx.lib.newevent import NewEvent
-try:
- import xml.etree.ElementTree as etree
-except ImportError:
- import elementtree.ElementTree as etree # Python <= 2.4
-
-from gui_core.dialogs import StaticWrapText
-from gui_core.ghelp import HelpPanel
-
gisbase = os.getenv("GISBASE")
if gisbase is None:
print >>sys.stderr, "We don't seem to be properly installed, or we are being run outside GRASS. Expect glitches."
@@ -89,15 +77,15 @@
from grass.script import core as grass
from grass.script import task as gtask
-from gui_core import gselect
-from core import cmd as gcmd
-from gui_core import goutput
-from core import utils
-from core.settings import UserSettings
-try:
- import subprocess
-except:
- from compat import subprocess
+from gui_core.widgets import StaticWrapText
+from gui_core.ghelp import HelpPanel
+from gui_core import gselect
+from core import gcmd
+from core import utils
+from gui_core.goutput import GMConsole
+from core.settings import UserSettings
+from gui_core.widgets import FloatValidator
+from gui_core.task import GUI
wxUpdateDialog, EVT_DIALOG_UPDATE = NewEvent()
@@ -834,7 +822,7 @@
# are we running from command line?
### add 'command output' tab regardless standalone dialog
if self.parent.GetName() == "MainFrame" and self.parent.get_dcmd is None:
- self.goutput = goutput.GMConsole(parent = self, margin = False)
+ self.goutput = GMConsole(parent = self, margin = False)
self.outpage = self.notebook.AddPage(page = self.goutput, text = _("Command output"), name = 'output')
else:
self.goutput = None
@@ -1943,223 +1931,6 @@
return True
-class GUI:
- def __init__(self, parent = None, show = True, modal = False,
- centreOnParent = False, checkError = False):
- """!Parses GRASS commands when module is imported and used from
- Layer Manager.
- """
- self.parent = parent
- self.show = show
- self.modal = modal
- self.centreOnParent = centreOnParent
- self.checkError = checkError
-
- self.grass_task = None
- self.cmd = list()
-
- global _blackList
- if self.parent:
- _blackList['enabled'] = True
- else:
- _blackList['enabled'] = False
-
- def GetCmd(self):
- """!Get validated command"""
- return self.cmd
-
- def ParseCommand(self, cmd, gmpath = None, completed = None):
- """!Parse command
-
- Note: cmd is given as list
-
- If command is given with options, return validated cmd list:
- - add key name for first parameter if not given
- - change mapname to mapname at mapset
- """
- start = time.time()
- dcmd_params = {}
- if completed == None:
- get_dcmd = None
- layer = None
- dcmd_params = None
- else:
- get_dcmd = completed[0]
- layer = completed[1]
- if completed[2]:
- dcmd_params.update(completed[2])
-
- # parse the interface decription
- try:
- global _blackList
- self.grass_task = gtask.parse_interface(cmd[0],
- blackList = _blackList)
- except ValueError, e: #grass.ScriptError, e:
- gcmd.GError(e.value)
- return
-
- # if layer parameters previously set, re-insert them into dialog
- if completed is not None:
- if 'params' in dcmd_params:
- self.grass_task.params = dcmd_params['params']
- if 'flags' in dcmd_params:
- self.grass_task.flags = dcmd_params['flags']
-
- err = list()
- # update parameters if needed && validate command
- if len(cmd) > 1:
- i = 0
- cmd_validated = [cmd[0]]
- for option in cmd[1:]:
- if option[0] == '-': # flag
- if option[1] == '-':
- self.grass_task.set_flag(option[2:], True)
- else:
- self.grass_task.set_flag(option[1], True)
- cmd_validated.append(option)
- else: # parameter
- try:
- key, value = option.split('=', 1)
- except:
- if self.grass_task.firstParam:
- if i == 0: # add key name of first parameter if not given
- key = self.grass_task.firstParam
- value = option
- else:
- raise gcmd.GException, _("Unable to parse command '%s'") % ' '.join(cmd)
- else:
- continue
-
- element = self.grass_task.get_param(key, raiseError = False)
- if not element:
- err.append(_("%(cmd)s: parameter '%(key)s' not available") % \
- { 'cmd' : cmd[0],
- 'key' : key })
- continue
- element = element['element']
-
- if element in ['cell', 'vector']:
- # mapname -> mapname at mapset
- try:
- name, mapset = value.split('@')
- except ValueError:
- mapset = grass.find_file(value, element)['mapset']
- curr_mapset = grass.gisenv()['MAPSET']
- if mapset and mapset != curr_mapset:
- value = value + '@' + mapset
-
- self.grass_task.set_param(key, value)
- cmd_validated.append(key + '=' + value)
- i += 1
-
- # update original command list
- cmd = cmd_validated
-
- if self.show is not None:
- self.mf = mainFrame(parent = self.parent, ID = wx.ID_ANY,
- task_description = self.grass_task,
- get_dcmd = get_dcmd, layer = layer)
- else:
- self.mf = None
-
- if get_dcmd is not None:
- # update only propwin reference
- get_dcmd(dcmd = None, layer = layer, params = None,
- propwin = self.mf)
-
- if self.show is not None:
- self.mf.notebookpanel.OnUpdateSelection(None)
- if self.show is True:
- if self.parent and self.centreOnParent:
- self.mf.CentreOnParent()
- else:
- self.mf.CenterOnScreen()
- self.mf.Show(self.show)
- self.mf.MakeModal(self.modal)
- else:
- self.mf.OnApply(None)
-
- self.cmd = cmd
-
- if self.checkError:
- return self.grass_task, err
- else:
- return self.grass_task
-
- def GetCommandInputMapParamKey(self, cmd):
- """!Get parameter key for input raster/vector map
-
- @param cmd module name
-
- @return parameter key
- @return None on failure
- """
- # parse the interface decription
- if not self.grass_task:
- enc = locale.getdefaultlocale()[1]
- if enc and enc.lower() == "cp932":
- p = re.compile('encoding="' + enc + '"', re.IGNORECASE)
- tree = etree.fromstring(p.sub('encoding="utf-8"',
- gtask.get_interface_description(cmd).decode(enc).encode('utf-8')))
- else:
- tree = etree.fromstring(gtask.get_interface_description(cmd))
- self.grass_task = gtask.processTask(tree).get_task()
-
- for p in self.grass_task.params:
- if p.get('name', '') in ('input', 'map'):
- age = p.get('age', '')
- prompt = p.get('prompt', '')
- element = p.get('element', '')
- if age == 'old' and \
- element in ('cell', 'grid3', 'vector') and \
- prompt in ('raster', '3d-raster', 'vector'):
- return p.get('name', None)
- return None
-
-class FloatValidator(wx.PyValidator):
- """!Validator for floating-point input"""
- def __init__(self):
- wx.PyValidator.__init__(self)
-
- self.Bind(wx.EVT_TEXT, self.OnText)
-
- def Clone(self):
- """!Clone validator"""
- return FloatValidator()
-
- def Validate(self):
- """Validate input"""
- textCtrl = self.GetWindow()
- text = textCtrl.GetValue()
-
- if text:
- try:
- float(text)
- except ValueError:
- textCtrl.SetBackgroundColour("grey")
- textCtrl.SetFocus()
- textCtrl.Refresh()
- return False
-
- sysColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
- textCtrl.SetBackgroundColour(sysColor)
-
- textCtrl.Refresh()
-
- return True
-
- def OnText(self, event):
- """!Do validation"""
- self.Validate()
-
- event.Skip()
-
- def TransferToWindow(self):
- return True # Prevent wxDialog from complaining.
-
- def TransferFromWindow(self):
- return True # Prevent wxDialog from complaining.
-
if __name__ == "__main__":
import gettext
gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
Modified: grass/trunk/gui/wxpython/gui_core/ghelp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/ghelp.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gui_core/ghelp.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -5,12 +5,9 @@
Classes:
- SearchModuleWindow
- - ItemTree
- MenuTreeWindow
- MenuTree
- AboutWindow
- - InstallExtensionWindow
- - ExtensionTree
- HelpFrame
- HelpWindow
- HelpPanel
@@ -26,6 +23,7 @@
import codecs
import wx
+from wx.html import HtmlWindow
try:
import wx.lib.agw.customtreectrl as CT
from wx.lib.agw.hyperlink import HyperLinkCtrl
@@ -33,18 +31,15 @@
import wx.lib.customtreectrl as CT
from wx.lib.hyperlink import HyperLinkCtrl
import wx.lib.flatnotebook as FN
-import wx.lib.scrolledpanel as scrolled
+import wx.lib.scrolledpanel as scrolled
import grass.script as grass
-from grass.script import task as gtask
from core import globalvar
from core import utils
from lmgr.menudata import ManagerData
-from core.gcmd import GError, RunCommand, DecodeString
-from gui_core.widgets import GNotebook
-from core.forms import GUI
-from gui_core.dialogs import StaticWrapText
+from core.gcmd import GError, DecodeString
+from gui_core.widgets import GNotebook, StaticWrapText, ItemTree
class HelpFrame(wx.Frame):
"""!GRASS Quickstart help window"""
@@ -350,85 +345,6 @@
event.Skip()
-class ItemTree(CT.CustomTreeCtrl):
- def __init__(self, parent, id = wx.ID_ANY,
- ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
- CT.TR_LINES_AT_ROOT | CT.TR_SINGLE, **kwargs):
- if globalvar.hasAgw:
- super(ItemTree, self).__init__(parent, id, agwStyle = ctstyle, **kwargs)
- else:
- super(ItemTree, self).__init__(parent, id, style = ctstyle, **kwargs)
-
- self.root = self.AddRoot(_("Menu tree"))
- self.itemsMarked = [] # list of marked items
- self.itemSelected = None
-
- def SearchItems(self, element, value):
- """!Search item
-
- @param element element index (see self.searchBy)
- @param value
-
- @return list of found tree items
- """
- items = list()
- if not value:
- return items
-
- item = self.GetFirstChild(self.root)[0]
- self._processItem(item, element, value, items)
-
- self.itemsMarked = items
- self.itemSelected = None
-
- return items
-
- def _processItem(self, item, element, value, listOfItems):
- """!Search items (used by SearchItems)
-
- @param item reference item
- @param listOfItems list of found items
- """
- while item and item.IsOk():
- subItem = self.GetFirstChild(item)[0]
- if subItem:
- self._processItem(subItem, element, value, listOfItems)
- data = self.GetPyData(item)
-
- if data and element in data and \
- value.lower() in data[element].lower():
- listOfItems.append(item)
-
- item = self.GetNextSibling(item)
-
- def GetSelected(self):
- """!Get selected item"""
- return self.itemSelected
-
- def OnShowItem(self, event):
- """!Highlight first found item in menu tree"""
- if len(self.itemsMarked) > 0:
- if self.GetSelected():
- self.ToggleItemSelection(self.GetSelected())
- idx = self.itemsMarked.index(self.GetSelected()) + 1
- else:
- idx = 0
- try:
- self.ToggleItemSelection(self.itemsMarked[idx])
- self.itemSelected = self.itemsMarked[idx]
- self.EnsureVisible(self.itemsMarked[idx])
- except IndexError:
- self.ToggleItemSelection(self.itemsMarked[0]) # reselect first item
- self.EnsureVisible(self.itemsMarked[0])
- self.itemSelected = self.itemsMarked[0]
- else:
- for item in self.root.GetChildren():
- self.Collapse(item)
- itemSelected = self.GetSelection()
- if itemSelected:
- self.ToggleItemSelection(itemSelected)
- self.itemSelected = None
-
class MenuTree(ItemTree):
"""!Menu tree class"""
def __init__(self, parent, data, **kwargs):
@@ -686,7 +602,7 @@
GError(parent = self,
message = _("Error when reading file '%s'.") % contribfile + \
"\n\n" + _("Lines:") + " %s" % \
- os.linesep.join(map(utils.DecodeString, errLines)))
+ os.linesep.join(map(DecodeString, errLines)))
else:
contribs = None
@@ -746,7 +662,7 @@
GError(parent = self,
message = _("Error when reading file '%s'.") % translatorsfile + \
"\n\n" + _("Lines:") + " %s" % \
- os.linesep.join(map(utils.DecodeString, errLines)))
+ os.linesep.join(map(DecodeString, errLines)))
else:
translators = None
@@ -793,335 +709,7 @@
"""!Close window"""
self.Close()
-class InstallExtensionWindow(wx.Frame):
- def __init__(self, parent, id = wx.ID_ANY,
- title = _("Fetch & install extension from GRASS Addons"), **kwargs):
- self.parent = parent
- self.options = dict() # list of options
-
- wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
-
- self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
-
- self.repoBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
- label = " %s " % _("Repository"))
- self.treeBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
- label = " %s " % _("List of extensions"))
-
- self.repo = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY)
- self.fullDesc = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
- label = _("Fetch full info including description and keywords (takes time)"))
- self.fullDesc.SetValue(True)
-
- self.search = SearchModuleWindow(parent = self.panel)
- self.search.SetSelection(0)
-
- self.tree = ExtensionTree(parent = self.panel, log = parent.GetLogWindow())
-
- self.optionBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
- label = " %s " % _("Options"))
- task = gtask.parse_interface('g.extension')
- for f in task.get_options()['flags']:
- name = f.get('name', '')
- desc = f.get('label', '')
- if not desc:
- desc = f.get('description', '')
- if not name and not desc:
- continue
- if name in ('l', 'c', 'g', 'quiet', 'verbose'):
- continue
- self.options[name] = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
- label = desc)
- self.repo.SetValue(task.get_param(value = 'svnurl').get('default',
- 'http://svn.osgeo.org/grass/grass-addons/grass7'))
-
- self.statusbar = self.CreateStatusBar(number = 1)
-
- self.btnFetch = wx.Button(parent = self.panel, id = wx.ID_ANY,
- label = _("&Fetch"))
- self.btnFetch.SetToolTipString(_("Fetch list of available modules from GRASS Addons SVN repository"))
- self.btnClose = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
- self.btnInstall = wx.Button(parent = self.panel, id = wx.ID_ANY,
- label = _("&Install"))
- self.btnInstall.SetToolTipString(_("Install selected add-ons GRASS module"))
- self.btnInstall.Enable(False)
- self.btnCmd = wx.Button(parent = self.panel, id = wx.ID_ANY,
- label = _("Command dialog"))
- self.btnCmd.SetToolTipString(_('Open %s dialog') % 'g.extension')
-
- self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
- self.btnFetch.Bind(wx.EVT_BUTTON, self.OnFetch)
- self.btnInstall.Bind(wx.EVT_BUTTON, self.OnInstall)
- self.btnCmd.Bind(wx.EVT_BUTTON, self.OnCmdDialog)
- self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
- self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnItemSelected)
- self.search.Bind(wx.EVT_TEXT_ENTER, self.OnShowItem)
- self.search.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
-
- self._layout()
-
- def _layout(self):
- """!Do layout"""
- sizer = wx.BoxSizer(wx.VERTICAL)
- repoSizer = wx.StaticBoxSizer(self.repoBox, wx.VERTICAL)
- repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
- repo1Sizer.Add(item = self.repo, proportion = 1,
- flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
- repo1Sizer.Add(item = self.btnFetch, proportion = 0,
- flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
- repoSizer.Add(item = repo1Sizer,
- flag = wx.EXPAND)
- repoSizer.Add(item = self.fullDesc)
-
- findSizer = wx.BoxSizer(wx.HORIZONTAL)
- findSizer.Add(item = self.search, proportion = 1)
-
- treeSizer = wx.StaticBoxSizer(self.treeBox, wx.HORIZONTAL)
- treeSizer.Add(item = self.tree, proportion = 1,
- flag = wx.ALL | wx.EXPAND, border = 1)
-
- # options
- optionSizer = wx.StaticBoxSizer(self.optionBox, wx.VERTICAL)
- for key in self.options.keys():
- optionSizer.Add(item = self.options[key], proportion = 0)
-
- btnSizer = wx.BoxSizer(wx.HORIZONTAL)
- btnSizer.Add(item = self.btnCmd, proportion = 0,
- flag = wx.RIGHT, border = 5)
- btnSizer.AddSpacer(10)
- btnSizer.Add(item = self.btnClose, proportion = 0,
- flag = wx.RIGHT, border = 5)
- btnSizer.Add(item = self.btnInstall, proportion = 0)
-
- sizer.Add(item = repoSizer, proportion = 0,
- flag = wx.ALL | wx.EXPAND, border = 3)
- sizer.Add(item = findSizer, proportion = 0,
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
- sizer.Add(item = treeSizer, proportion = 1,
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
- sizer.Add(item = optionSizer, proportion = 0,
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
- sizer.Add(item = btnSizer, proportion = 0,
- flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
-
- self.panel.SetSizer(sizer)
- sizer.Fit(self.panel)
-
- self.Layout()
-
- def _getCmd(self):
- item = self.tree.GetSelected()
- if not item or not item.IsOk():
- return ['g.extension']
-
- name = self.tree.GetItemText(item)
- if not name:
- GError(_("Extension not defined"), parent = self)
- return
-
- flags = list()
- for key in self.options.keys():
- if self.options[key].IsChecked():
- flags.append('-%s' % key)
-
- return ['g.extension'] + flags + ['extension=' + name,
- 'svnurl=' + self.repo.GetValue().strip()]
-
- def OnUpdateStatusBar(self, event):
- """!Update statusbar text"""
- element = self.search.GetSelection()
- if not self.tree.IsLoaded():
- self.SetStatusText(_("Fetch list of available extensions by clicking on 'Fetch' button"), 0)
- return
-
- self.tree.SearchItems(element = element,
- value = event.GetString())
-
- nItems = len(self.tree.itemsMarked)
- if event.GetString():
- self.SetStatusText(_("%d items match") % nItems, 0)
- else:
- self.SetStatusText("", 0)
-
- event.Skip()
-
- def OnCloseWindow(self, event):
- """!Close window"""
- self.Destroy()
-
- def OnFetch(self, event):
- """!Fetch list of available extensions"""
- wx.BeginBusyCursor()
- self.SetStatusText(_("Fetching list of modules from GRASS-Addons SVN (be patient)..."), 0)
- self.tree.Load(url = self.repo.GetValue().strip(), full = self.fullDesc.IsChecked())
- self.SetStatusText("", 0)
- wx.EndBusyCursor()
-
- def OnItemActivated(self, event):
- item = event.GetItem()
- data = self.tree.GetPyData(item)
- if data and 'command' in data:
- self.OnInstall(event = None)
-
- def OnInstall(self, event):
- """!Install selected extension"""
- log = self.parent.GetLogWindow()
- log.RunCmd(self._getCmd(), onDone = self.OnDone)
-
- def OnDone(self, cmd, returncode):
- item = self.tree.GetSelected()
- if not item or not item.IsOk() or \
- returncode != 0 or \
- not os.getenv('GRASS_ADDON_PATH'):
- return
-
- name = self.tree.GetItemText(item)
- globalvar.grassCmd['all'].append(name)
-
- def OnItemSelected(self, event):
- """!Item selected"""
- item = event.GetItem()
- self.tree.itemSelected = item
- data = self.tree.GetPyData(item)
- if not data:
- self.SetStatusText('', 0)
- self.btnInstall.Enable(False)
- else:
- self.SetStatusText(data.get('description', ''), 0)
- self.btnInstall.Enable(True)
-
- def OnShowItem(self, event):
- """!Show selected item"""
- self.tree.OnShowItem(event)
- if self.tree.GetSelected():
- self.btnInstall.Enable()
- else:
- self.btnInstall.Enable(False)
-
- def OnCmdDialog(self, event):
- """!Shows command dialog"""
- GUI(parent = self).ParseCommand(cmd = self._getCmd())
-
-class ExtensionTree(ItemTree):
- """!List of available extensions"""
- def __init__(self, parent, log, id = wx.ID_ANY,
- ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
- CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
- **kwargs):
- self.parent = parent # GMFrame
- self.log = log
-
- super(ExtensionTree, self).__init__(parent, id, ctstyle = ctstyle, **kwargs)
-
- self._initTree()
-
- def _initTree(self):
- for prefix in ('display', 'database',
- 'general', 'imagery',
- 'misc', 'postscript', 'paint',
- 'raster', 'raster3D', 'sites', 'vector', 'wxGUI', 'other'):
- self.AppendItem(parentId = self.root,
- text = prefix)
- self._loaded = False
-
- def _expandPrefix(self, c):
- name = { 'd' : 'display',
- 'db' : 'database',
- 'g' : 'general',
- 'i' : 'imagery',
- 'm' : 'misc',
- 'ps' : 'postscript',
- 'p' : 'paint',
- 'r' : 'raster',
- 'r3' : 'raster3D',
- 's' : 'sites',
- 'v' : 'vector',
- 'wx' : 'wxGUI',
- 'u' : 'other' }
-
- if c in name:
- return name[c]
-
- return c
-
- def _findItem(self, text):
- """!Find item"""
- item = self.GetFirstChild(self.root)[0]
- while item and item.IsOk():
- if text == self.GetItemText(item):
- return item
-
- item = self.GetNextSibling(item)
-
- return None
-
- def Load(self, url, full = False):
- """!Load list of extensions"""
- self.DeleteAllItems()
- self.root = self.AddRoot(_("Menu tree"))
- self._initTree()
-
- if full:
- flags = 'g'
- else:
- flags = 'l'
- ret = RunCommand('g.extension', read = True,
- svnurl = url,
- flags = flags, quiet = True)
- if not ret:
- return
-
- mdict = dict()
- for line in ret.splitlines():
- if full:
- key, value = line.split('=', 1)
- if key == 'name':
- try:
- prefix, name = value.split('.', 1)
- except ValueError:
- prefix = 'u'
- name = value
- if prefix not in mdict:
- mdict[prefix] = dict()
- mdict[prefix][name] = dict()
- else:
- mdict[prefix][name][key] = value
- else:
- try:
- prefix, name = line.strip().split('.', 1)
- except:
- prefix = 'unknown'
- name = line.strip()
-
- if self._expandPrefix(prefix) == prefix:
- prefix = 'unknown'
-
- if prefix not in mdict:
- mdict[prefix] = dict()
-
- mdict[prefix][name] = { 'command' : prefix + '.' + name }
-
- for prefix in mdict.keys():
- prefixName = self._expandPrefix(prefix)
- item = self._findItem(prefixName)
- names = mdict[prefix].keys()
- names.sort()
- for name in names:
- new = self.AppendItem(parentId = item,
- text = prefix + '.' + name)
- data = dict()
- for key in mdict[prefix][name].keys():
- data[key] = mdict[prefix][name][key]
-
- self.SetPyData(new, data)
-
- self._loaded = True
-
- def IsLoaded(self):
- """Check if items are loaded"""
- return self._loaded
-
-class HelpWindow(wx.html.HtmlWindow):
+class HelpWindow(HtmlWindow):
"""!This panel holds the text from GRASS docs.
GISBASE must be set in the environment to find the html docs dir.
@@ -1143,7 +731,7 @@
"""
self.parent = parent
wx.InitAllImageHandlers()
- wx.html.HtmlWindow.__init__(self, parent = parent, **kwargs)
+ HtmlWindow.__init__(self, parent = parent, **kwargs)
gisbase = os.getenv("GISBASE")
self.loaded = False
Modified: grass/trunk/gui/wxpython/gui_core/goutput.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/goutput.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gui_core/goutput.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -39,7 +39,7 @@
from core import globalvar
from core import utils
from core.gcmd import CommandThread, GMessage, GError, GException, EncodeString
-from gui_core.forms import GUI
+from gui_core.task import GUI
from gui_core.prompt import GPromptSTC
from core.debug import Debug
from core.settings import UserSettings, Settings
Added: grass/trunk/gui/wxpython/gui_core/task.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/task.py (rev 0)
+++ grass/trunk/gui/wxpython/gui_core/task.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -0,0 +1,210 @@
+"""
+ at package gui_core.task
+
+ at brief Construct simple wxPython GUI from a GRASS command interface
+description.
+
+Classes:
+ - GUI
+
+(C) 2000-2011 by the GRASS Development Team
+This program is free software under the GPL(>=v2) Read the file
+COPYING coming with GRASS for details.
+
+ at author Jan-Oliver Wagner <jan at intevation.de>
+ at author Bernhard Reiter <bernhard at intevation.de>
+ at author Michael Barton, Arizona State University
+ at author Daniel Calvelo <dca.gis at gmail.com>
+ at author Martin Landa <landa.martin at gmail.com>
+ at author Luca Delucchi <lucadeluge at gmail.com>
+"""
+
+import sys
+import re
+import os
+import time
+import locale
+try:
+ import xml.etree.ElementTree as etree
+except ImportError:
+ import elementtree.ElementTree as etree # Python <= 2.4
+
+from core import globalvar
+import wx
+
+from grass.script import core as grass
+from grass.script import task as gtask
+from core.gcmd import GException, GError
+
+class GUI:
+ def __init__(self, parent = None, show = True, modal = False,
+ centreOnParent = False, checkError = False):
+ """!Parses GRASS commands when module is imported and used from
+ Layer Manager.
+ """
+ self.parent = parent
+ self.show = show
+ self.modal = modal
+ self.centreOnParent = centreOnParent
+ self.checkError = checkError
+
+ self.grass_task = None
+ self.cmd = list()
+
+ global _blackList
+ if self.parent:
+ _blackList['enabled'] = True
+ else:
+ _blackList['enabled'] = False
+
+ def GetCmd(self):
+ """!Get validated command"""
+ return self.cmd
+
+ def ParseCommand(self, cmd, gmpath = None, completed = None):
+ """!Parse command
+
+ Note: cmd is given as list
+
+ If command is given with options, return validated cmd list:
+ - add key name for first parameter if not given
+ - change mapname to mapname at mapset
+ """
+ start = time.time()
+ dcmd_params = {}
+ if completed == None:
+ get_dcmd = None
+ layer = None
+ dcmd_params = None
+ else:
+ get_dcmd = completed[0]
+ layer = completed[1]
+ if completed[2]:
+ dcmd_params.update(completed[2])
+
+ # parse the interface decription
+ try:
+ global _blackList
+ self.grass_task = gtask.parse_interface(cmd[0],
+ blackList = _blackList)
+ except ValueError, e: #grass.ScriptError, e:
+ GError(e.value)
+ return
+
+ # if layer parameters previously set, re-insert them into dialog
+ if completed is not None:
+ if 'params' in dcmd_params:
+ self.grass_task.params = dcmd_params['params']
+ if 'flags' in dcmd_params:
+ self.grass_task.flags = dcmd_params['flags']
+
+ err = list()
+ # update parameters if needed && validate command
+ if len(cmd) > 1:
+ i = 0
+ cmd_validated = [cmd[0]]
+ for option in cmd[1:]:
+ if option[0] == '-': # flag
+ if option[1] == '-':
+ self.grass_task.set_flag(option[2:], True)
+ else:
+ self.grass_task.set_flag(option[1], True)
+ cmd_validated.append(option)
+ else: # parameter
+ try:
+ key, value = option.split('=', 1)
+ except:
+ if self.grass_task.firstParam:
+ if i == 0: # add key name of first parameter if not given
+ key = self.grass_task.firstParam
+ value = option
+ else:
+ raise GException, _("Unable to parse command '%s'") % ' '.join(cmd)
+ else:
+ continue
+
+ element = self.grass_task.get_param(key, raiseError = False)
+ if not element:
+ err.append(_("%(cmd)s: parameter '%(key)s' not available") % \
+ { 'cmd' : cmd[0],
+ 'key' : key })
+ continue
+ element = element['element']
+
+ if element in ['cell', 'vector']:
+ # mapname -> mapname at mapset
+ try:
+ name, mapset = value.split('@')
+ except ValueError:
+ mapset = grass.find_file(value, element)['mapset']
+ curr_mapset = grass.gisenv()['MAPSET']
+ if mapset and mapset != curr_mapset:
+ value = value + '@' + mapset
+
+ self.grass_task.set_param(key, value)
+ cmd_validated.append(key + '=' + value)
+ i += 1
+
+ # update original command list
+ cmd = cmd_validated
+
+ if self.show is not None:
+ self.mf = mainFrame(parent = self.parent, ID = wx.ID_ANY,
+ task_description = self.grass_task,
+ get_dcmd = get_dcmd, layer = layer)
+ else:
+ self.mf = None
+
+ if get_dcmd is not None:
+ # update only propwin reference
+ get_dcmd(dcmd = None, layer = layer, params = None,
+ propwin = self.mf)
+
+ if self.show is not None:
+ self.mf.notebookpanel.OnUpdateSelection(None)
+ if self.show is True:
+ if self.parent and self.centreOnParent:
+ self.mf.CentreOnParent()
+ else:
+ self.mf.CenterOnScreen()
+ self.mf.Show(self.show)
+ self.mf.MakeModal(self.modal)
+ else:
+ self.mf.OnApply(None)
+
+ self.cmd = cmd
+
+ if self.checkError:
+ return self.grass_task, err
+ else:
+ return self.grass_task
+
+ def GetCommandInputMapParamKey(self, cmd):
+ """!Get parameter key for input raster/vector map
+
+ @param cmd module name
+
+ @return parameter key
+ @return None on failure
+ """
+ # parse the interface decription
+ if not self.grass_task:
+ enc = locale.getdefaultlocale()[1]
+ if enc and enc.lower() == "cp932":
+ p = re.compile('encoding="' + enc + '"', re.IGNORECASE)
+ tree = etree.fromstring(p.sub('encoding="utf-8"',
+ gtask.get_interface_description(cmd).decode(enc).encode('utf-8')))
+ else:
+ tree = etree.fromstring(gtask.get_interface_description(cmd))
+ self.grass_task = gtask.processTask(tree).get_task()
+
+ for p in self.grass_task.params:
+ if p.get('name', '') in ('input', 'map'):
+ age = p.get('age', '')
+ prompt = p.get('prompt', '')
+ element = p.get('element', '')
+ if age == 'old' and \
+ element in ('cell', 'grid3', 'vector') and \
+ prompt in ('raster', '3d-raster', 'vector'):
+ return p.get('name', None)
+ return None
Property changes on: grass/trunk/gui/wxpython/gui_core/task.py
___________________________________________________________________
Added: svn:mime-type
+ text/x-python
Added: svn:eol-style
+ native
Modified: grass/trunk/gui/wxpython/gui_core/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/widgets.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/gui_core/widgets.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -9,6 +9,9 @@
- NumTextCtrl
- FloatSlider
- SymbolButton
+ - StaticWrapText
+ - FloatValidator
+ - ItemTree
(C) 2008-2011 by the GRASS Development Team
This program is free software under the GNU General Public License
@@ -31,6 +34,10 @@
from wx.lib.buttons import ThemedGenBitmapTextButton as BitmapTextButton
except ImportError: # not sure about TGBTButton version
from wx.lib.buttons import GenBitmapTextButton as BitmapTextButton
+try:
+ import wx.lib.agw.customtreectrl as CT
+except ImportError:
+ import wx.lib.customtreectrl as CT
from core import globalvar
@@ -229,3 +236,157 @@
dc.SetBrush(wx.Brush(wx.Color(50, 50, 50)))
dc.DrawRectangle(0, 0, 2 * size[0] / 5, size[1])
dc.DrawRectangle(3 * size[0] / 5, 0, 2 * size[0] / 5, size[1])
+
+class StaticWrapText(wx.StaticText):
+ """!A Static Text field that wraps its text to fit its width,
+ enlarging its height if necessary.
+ """
+ def __init__(self, parent, id = wx.ID_ANY, label = '', *args, **kwds):
+ self.parent = parent
+ self.originalLabel = label
+
+ wx.StaticText.__init__(self, parent, id, label = '', *args, **kwds)
+
+ self.SetLabel(label)
+ self.Bind(wx.EVT_SIZE, self.OnResize)
+
+ def SetLabel(self, label):
+ self.originalLabel = label
+ self.wrappedSize = None
+ self.OnResize(None)
+
+ def OnResize(self, event):
+ if not getattr(self, "resizing", False):
+ self.resizing = True
+ newSize = wx.Size(self.parent.GetSize().width - 50,
+ self.GetSize().height)
+ if self.wrappedSize != newSize:
+ wx.StaticText.SetLabel(self, self.originalLabel)
+ self.Wrap(newSize.width)
+ self.wrappedSize = newSize
+
+ self.SetSize(self.wrappedSize)
+ del self.resizing
+
+class FloatValidator(wx.PyValidator):
+ """!Validator for floating-point input"""
+ def __init__(self):
+ wx.PyValidator.__init__(self)
+
+ self.Bind(wx.EVT_TEXT, self.OnText)
+
+ def Clone(self):
+ """!Clone validator"""
+ return FloatValidator()
+
+ def Validate(self):
+ """Validate input"""
+ textCtrl = self.GetWindow()
+ text = textCtrl.GetValue()
+
+ if text:
+ try:
+ float(text)
+ except ValueError:
+ textCtrl.SetBackgroundColour("grey")
+ textCtrl.SetFocus()
+ textCtrl.Refresh()
+ return False
+
+ sysColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
+ textCtrl.SetBackgroundColour(sysColor)
+
+ textCtrl.Refresh()
+
+ return True
+
+ def OnText(self, event):
+ """!Do validation"""
+ self.Validate()
+
+ event.Skip()
+
+ def TransferToWindow(self):
+ return True # Prevent wxDialog from complaining.
+
+ def TransferFromWindow(self):
+ return True # Prevent wxDialog from complaining.
+
+class ItemTree(CT.CustomTreeCtrl):
+ def __init__(self, parent, id = wx.ID_ANY,
+ ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
+ CT.TR_LINES_AT_ROOT | CT.TR_SINGLE, **kwargs):
+ if globalvar.hasAgw:
+ super(ItemTree, self).__init__(parent, id, agwStyle = ctstyle, **kwargs)
+ else:
+ super(ItemTree, self).__init__(parent, id, style = ctstyle, **kwargs)
+
+ self.root = self.AddRoot(_("Menu tree"))
+ self.itemsMarked = [] # list of marked items
+ self.itemSelected = None
+
+ def SearchItems(self, element, value):
+ """!Search item
+
+ @param element element index (see self.searchBy)
+ @param value
+
+ @return list of found tree items
+ """
+ items = list()
+ if not value:
+ return items
+
+ item = self.GetFirstChild(self.root)[0]
+ self._processItem(item, element, value, items)
+
+ self.itemsMarked = items
+ self.itemSelected = None
+
+ return items
+
+ def _processItem(self, item, element, value, listOfItems):
+ """!Search items (used by SearchItems)
+
+ @param item reference item
+ @param listOfItems list of found items
+ """
+ while item and item.IsOk():
+ subItem = self.GetFirstChild(item)[0]
+ if subItem:
+ self._processItem(subItem, element, value, listOfItems)
+ data = self.GetPyData(item)
+
+ if data and element in data and \
+ value.lower() in data[element].lower():
+ listOfItems.append(item)
+
+ item = self.GetNextSibling(item)
+
+ def GetSelected(self):
+ """!Get selected item"""
+ return self.itemSelected
+
+ def OnShowItem(self, event):
+ """!Highlight first found item in menu tree"""
+ if len(self.itemsMarked) > 0:
+ if self.GetSelected():
+ self.ToggleItemSelection(self.GetSelected())
+ idx = self.itemsMarked.index(self.GetSelected()) + 1
+ else:
+ idx = 0
+ try:
+ self.ToggleItemSelection(self.itemsMarked[idx])
+ self.itemSelected = self.itemsMarked[idx]
+ self.EnsureVisible(self.itemsMarked[idx])
+ except IndexError:
+ self.ToggleItemSelection(self.itemsMarked[0]) # reselect first item
+ self.EnsureVisible(self.itemsMarked[0])
+ self.itemSelected = self.itemsMarked[0]
+ else:
+ for item in self.root.GetChildren():
+ self.Collapse(item)
+ itemSelected = self.GetSelection()
+ if itemSelected:
+ self.ToggleItemSelection(itemSelected)
+ self.itemSelected = None
Modified: grass/trunk/gui/wxpython/lmgr/layertree.py
===================================================================
--- grass/trunk/gui/wxpython/lmgr/layertree.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/lmgr/layertree.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -30,7 +30,7 @@
from core import globalvar
from gui_core.dialogs import SqlQueryFrame, SetOpacityDialog
-from core.forms import GUI
+from gui_core.task import GUI
from mapdisp.frame import MapFrame
from core.render import Map
from modules.histogram import HistogramFrame
Modified: grass/trunk/gui/wxpython/mapdisp/frame.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/frame.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/mapdisp/frame.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -50,9 +50,9 @@
from icon import Icons
from core.settings import UserSettings
from gui_core.mapdisp import MapFrameBase
-from mapdisp.window import BufferedWindow
-from modules.histogram import HistFrame
-from wxplot.histogram import HistFrame as HistFramePyPlot
+from mapdisp.mapwindow import BufferedWindow
+from modules.histogram import HistogramFrame
+from wxplot.histogram import Histogram2Frame
from wxplot.profile import ProfileFrame
from wxplot.scatter import ScatterFrame
@@ -1105,10 +1105,10 @@
continue
raster.append(self.tree.GetPyData(layer)[0]['maplayer'].GetName())
- self.histogramPyPlot = HistFramePyPlot(self, id = wx.ID_ANY,
- pos = wx.DefaultPosition, size = (700,300),
- style = wx.DEFAULT_FRAME_STYLE,
- rasterList = raster)
+ self.histogramPyPlot = Histogram2Frame(self, id = wx.ID_ANY,
+ pos = wx.DefaultPosition, size = (700,300),
+ style = wx.DEFAULT_FRAME_STYLE,
+ rasterList = raster)
self.histogramPyPlot.Show()
# Open raster select dialog to make sure that a raster (and the desired raster)
# is selected to be histogrammed
Modified: grass/trunk/gui/wxpython/modules/colorrules.py
===================================================================
--- grass/trunk/gui/wxpython/modules/colorrules.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/modules/colorrules.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -38,7 +38,7 @@
from core.gcmd import GMessage, RunCommand
from gui_core.gselect import Select, LayerSelect, ColumnSelect, VectorDBInfo
from core.render import Map
-from core.forms import GUI
+from gui_core.task import GUI
from core.debug import Debug as Debug
from core.settings import UserSettings
from nviz.mapwindow import wxUpdateProperties
Added: grass/trunk/gui/wxpython/modules/extensions.py
===================================================================
--- grass/trunk/gui/wxpython/modules/extensions.py (rev 0)
+++ grass/trunk/gui/wxpython/modules/extensions.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -0,0 +1,360 @@
+"""!
+ at package modules.extensions
+
+ at brief GRASS Addons extensions management classes
+
+Classes:
+ - InstallExtensionWindow
+ - ExtensionTree
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+
+import wx
+try:
+ import wx.lib.agw.customtreectrl as CT
+except ImportError:
+ import wx.lib.customtreectrl as CT
+import wx.lib.flatnotebook as FN
+
+import grass.script as grass
+from grass.script import task as gtask
+
+from core import globalvar
+from core.gcmd import GError, RunCommand
+from gui_core.task import GUI
+from gui_core.widgets import ItemTree
+
+class InstallExtensionWindow(wx.Frame):
+ def __init__(self, parent, id = wx.ID_ANY,
+ title = _("Fetch & install extension from GRASS Addons"), **kwargs):
+ self.parent = parent
+ self.options = dict() # list of options
+
+ wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
+
+ self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
+
+ self.repoBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+ label = " %s " % _("Repository"))
+ self.treeBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+ label = " %s " % _("List of extensions"))
+
+ self.repo = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY)
+ self.fullDesc = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
+ label = _("Fetch full info including description and keywords (takes time)"))
+ self.fullDesc.SetValue(True)
+
+ self.search = SearchModuleWindow(parent = self.panel)
+ self.search.SetSelection(0)
+
+ self.tree = ExtensionTree(parent = self.panel, log = parent.GetLogWindow())
+
+ self.optionBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+ label = " %s " % _("Options"))
+ task = gtask.parse_interface('g.extension')
+ for f in task.get_options()['flags']:
+ name = f.get('name', '')
+ desc = f.get('label', '')
+ if not desc:
+ desc = f.get('description', '')
+ if not name and not desc:
+ continue
+ if name in ('l', 'c', 'g', 'quiet', 'verbose'):
+ continue
+ self.options[name] = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
+ label = desc)
+ self.repo.SetValue(task.get_param(value = 'svnurl').get('default',
+ 'http://svn.osgeo.org/grass/grass-addons/grass7'))
+
+ self.statusbar = self.CreateStatusBar(number = 1)
+
+ self.btnFetch = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ label = _("&Fetch"))
+ self.btnFetch.SetToolTipString(_("Fetch list of available modules from GRASS Addons SVN repository"))
+ self.btnClose = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
+ self.btnInstall = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ label = _("&Install"))
+ self.btnInstall.SetToolTipString(_("Install selected add-ons GRASS module"))
+ self.btnInstall.Enable(False)
+ self.btnCmd = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ label = _("Command dialog"))
+ self.btnCmd.SetToolTipString(_('Open %s dialog') % 'g.extension')
+
+ self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
+ self.btnFetch.Bind(wx.EVT_BUTTON, self.OnFetch)
+ self.btnInstall.Bind(wx.EVT_BUTTON, self.OnInstall)
+ self.btnCmd.Bind(wx.EVT_BUTTON, self.OnCmdDialog)
+ self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
+ self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnItemSelected)
+ self.search.Bind(wx.EVT_TEXT_ENTER, self.OnShowItem)
+ self.search.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
+
+ self._layout()
+
+ def _layout(self):
+ """!Do layout"""
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ repoSizer = wx.StaticBoxSizer(self.repoBox, wx.VERTICAL)
+ repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
+ repo1Sizer.Add(item = self.repo, proportion = 1,
+ flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
+ repo1Sizer.Add(item = self.btnFetch, proportion = 0,
+ flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
+ repoSizer.Add(item = repo1Sizer,
+ flag = wx.EXPAND)
+ repoSizer.Add(item = self.fullDesc)
+
+ findSizer = wx.BoxSizer(wx.HORIZONTAL)
+ findSizer.Add(item = self.search, proportion = 1)
+
+ treeSizer = wx.StaticBoxSizer(self.treeBox, wx.HORIZONTAL)
+ treeSizer.Add(item = self.tree, proportion = 1,
+ flag = wx.ALL | wx.EXPAND, border = 1)
+
+ # options
+ optionSizer = wx.StaticBoxSizer(self.optionBox, wx.VERTICAL)
+ for key in self.options.keys():
+ optionSizer.Add(item = self.options[key], proportion = 0)
+
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add(item = self.btnCmd, proportion = 0,
+ flag = wx.RIGHT, border = 5)
+ btnSizer.AddSpacer(10)
+ btnSizer.Add(item = self.btnClose, proportion = 0,
+ flag = wx.RIGHT, border = 5)
+ btnSizer.Add(item = self.btnInstall, proportion = 0)
+
+ sizer.Add(item = repoSizer, proportion = 0,
+ flag = wx.ALL | wx.EXPAND, border = 3)
+ sizer.Add(item = findSizer, proportion = 0,
+ flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+ sizer.Add(item = treeSizer, proportion = 1,
+ flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+ sizer.Add(item = optionSizer, proportion = 0,
+ flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+ sizer.Add(item = btnSizer, proportion = 0,
+ flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+ self.panel.SetSizer(sizer)
+ sizer.Fit(self.panel)
+
+ self.Layout()
+
+ def _getCmd(self):
+ item = self.tree.GetSelected()
+ if not item or not item.IsOk():
+ return ['g.extension']
+
+ name = self.tree.GetItemText(item)
+ if not name:
+ GError(_("Extension not defined"), parent = self)
+ return
+
+ flags = list()
+ for key in self.options.keys():
+ if self.options[key].IsChecked():
+ flags.append('-%s' % key)
+
+ return ['g.extension'] + flags + ['extension=' + name,
+ 'svnurl=' + self.repo.GetValue().strip()]
+
+ def OnUpdateStatusBar(self, event):
+ """!Update statusbar text"""
+ element = self.search.GetSelection()
+ if not self.tree.IsLoaded():
+ self.SetStatusText(_("Fetch list of available extensions by clicking on 'Fetch' button"), 0)
+ return
+
+ self.tree.SearchItems(element = element,
+ value = event.GetString())
+
+ nItems = len(self.tree.itemsMarked)
+ if event.GetString():
+ self.SetStatusText(_("%d items match") % nItems, 0)
+ else:
+ self.SetStatusText("", 0)
+
+ event.Skip()
+
+ def OnCloseWindow(self, event):
+ """!Close window"""
+ self.Destroy()
+
+ def OnFetch(self, event):
+ """!Fetch list of available extensions"""
+ wx.BeginBusyCursor()
+ self.SetStatusText(_("Fetching list of modules from GRASS-Addons SVN (be patient)..."), 0)
+ self.tree.Load(url = self.repo.GetValue().strip(), full = self.fullDesc.IsChecked())
+ self.SetStatusText("", 0)
+ wx.EndBusyCursor()
+
+ def OnItemActivated(self, event):
+ item = event.GetItem()
+ data = self.tree.GetPyData(item)
+ if data and 'command' in data:
+ self.OnInstall(event = None)
+
+ def OnInstall(self, event):
+ """!Install selected extension"""
+ log = self.parent.GetLogWindow()
+ log.RunCmd(self._getCmd(), onDone = self.OnDone)
+
+ def OnDone(self, cmd, returncode):
+ item = self.tree.GetSelected()
+ if not item or not item.IsOk() or \
+ returncode != 0 or \
+ not os.getenv('GRASS_ADDON_PATH'):
+ return
+
+ name = self.tree.GetItemText(item)
+ globalvar.grassCmd['all'].append(name)
+
+ def OnItemSelected(self, event):
+ """!Item selected"""
+ item = event.GetItem()
+ self.tree.itemSelected = item
+ data = self.tree.GetPyData(item)
+ if not data:
+ self.SetStatusText('', 0)
+ self.btnInstall.Enable(False)
+ else:
+ self.SetStatusText(data.get('description', ''), 0)
+ self.btnInstall.Enable(True)
+
+ def OnShowItem(self, event):
+ """!Show selected item"""
+ self.tree.OnShowItem(event)
+ if self.tree.GetSelected():
+ self.btnInstall.Enable()
+ else:
+ self.btnInstall.Enable(False)
+
+ def OnCmdDialog(self, event):
+ """!Shows command dialog"""
+ GUI(parent = self).ParseCommand(cmd = self._getCmd())
+
+class ExtensionTree(ItemTree):
+ """!List of available extensions"""
+ def __init__(self, parent, log, id = wx.ID_ANY,
+ ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
+ CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
+ **kwargs):
+ self.parent = parent # GMFrame
+ self.log = log
+
+ super(ExtensionTree, self).__init__(parent, id, ctstyle = ctstyle, **kwargs)
+
+ self._initTree()
+
+ def _initTree(self):
+ for prefix in ('display', 'database',
+ 'general', 'imagery',
+ 'misc', 'postscript', 'paint',
+ 'raster', 'raster3D', 'sites', 'vector', 'wxGUI', 'other'):
+ self.AppendItem(parentId = self.root,
+ text = prefix)
+ self._loaded = False
+
+ def _expandPrefix(self, c):
+ name = { 'd' : 'display',
+ 'db' : 'database',
+ 'g' : 'general',
+ 'i' : 'imagery',
+ 'm' : 'misc',
+ 'ps' : 'postscript',
+ 'p' : 'paint',
+ 'r' : 'raster',
+ 'r3' : 'raster3D',
+ 's' : 'sites',
+ 'v' : 'vector',
+ 'wx' : 'wxGUI',
+ 'u' : 'other' }
+
+ if c in name:
+ return name[c]
+
+ return c
+
+ def _findItem(self, text):
+ """!Find item"""
+ item = self.GetFirstChild(self.root)[0]
+ while item and item.IsOk():
+ if text == self.GetItemText(item):
+ return item
+
+ item = self.GetNextSibling(item)
+
+ return None
+
+ def Load(self, url, full = False):
+ """!Load list of extensions"""
+ self.DeleteAllItems()
+ self.root = self.AddRoot(_("Menu tree"))
+ self._initTree()
+
+ if full:
+ flags = 'g'
+ else:
+ flags = 'l'
+ ret = RunCommand('g.extension', read = True,
+ svnurl = url,
+ flags = flags, quiet = True)
+ if not ret:
+ return
+
+ mdict = dict()
+ for line in ret.splitlines():
+ if full:
+ key, value = line.split('=', 1)
+ if key == 'name':
+ try:
+ prefix, name = value.split('.', 1)
+ except ValueError:
+ prefix = 'u'
+ name = value
+ if prefix not in mdict:
+ mdict[prefix] = dict()
+ mdict[prefix][name] = dict()
+ else:
+ mdict[prefix][name][key] = value
+ else:
+ try:
+ prefix, name = line.strip().split('.', 1)
+ except:
+ prefix = 'unknown'
+ name = line.strip()
+
+ if self._expandPrefix(prefix) == prefix:
+ prefix = 'unknown'
+
+ if prefix not in mdict:
+ mdict[prefix] = dict()
+
+ mdict[prefix][name] = { 'command' : prefix + '.' + name }
+
+ for prefix in mdict.keys():
+ prefixName = self._expandPrefix(prefix)
+ item = self._findItem(prefixName)
+ names = mdict[prefix].keys()
+ names.sort()
+ for name in names:
+ new = self.AppendItem(parentId = item,
+ text = prefix + '.' + name)
+ data = dict()
+ for key in mdict[prefix][name].keys():
+ data[key] = mdict[prefix][name][key]
+
+ self.SetPyData(new, data)
+
+ self._loaded = True
+
+ def IsLoaded(self):
+ """Check if items are loaded"""
+ return self._loaded
Property changes on: grass/trunk/gui/wxpython/modules/extensions.py
___________________________________________________________________
Added: svn:mime-type
+ text/x-python
Added: svn:eol-style
+ native
Modified: grass/trunk/gui/wxpython/modules/histogram.py
===================================================================
--- grass/trunk/gui/wxpython/modules/histogram.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/modules/histogram.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -22,7 +22,7 @@
from core import globalvar
from core.render import Map
-from core.forms import GUI
+from gui_core.task import GUI
from mapdisp.gprint import PrintOptions
from core.utils import GetLayerNameFromCmd
from gui_core.dialogs import GetImageHandlers, ImageSizeDialog
@@ -258,7 +258,7 @@
"""
self.Draw(self.pdc, pdctype = 'clear')
-class HistFrame(wx.Frame):
+class HistogramFrame(wx.Frame):
"""!Main frame for hisgram display window. Uses d.histogram
rendered onto canvas
"""
Modified: grass/trunk/gui/wxpython/modules/mcalc_builder.py
===================================================================
--- grass/trunk/gui/wxpython/modules/mcalc_builder.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/modules/mcalc_builder.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -24,7 +24,7 @@
from core.gcmd import GError, RunCommand
from gui_core.gselect import Select
-from core.forms import GUI
+from gui_core.task import GUI
from core.settings import UserSettings
class MapCalcFrame(wx.Frame):
Modified: grass/trunk/gui/wxpython/nviz/mapwindow.py
===================================================================
--- grass/trunk/gui/wxpython/nviz/mapwindow.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/nviz/mapwindow.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -34,16 +34,15 @@
import grass.script as grass
-from core.gcmd import GMessage, GException, GError
-from core.debug import Debug
-from mapdisp.window import MapWindow
-from gui_core.goutput import wxCmdOutput
-from core.settings import UserSettings
-from nviz.workspace import NvizSettings
-from nviz.animation import Animation
+from core.gcmd import GMessage, GException, GError
+from core.debug import Debug
+from gui_core.mapwindow import MapWindow
+from gui_core.goutput import wxCmdOutput
+from core.settings import UserSettings
+from nviz.workspace import NvizSettings
+from nviz.animation import Animation
+from nviz import wxnviz
-import nviz.wxcore as wxnviz
-
wxUpdateProperties, EVT_UPDATE_PROP = NewEvent()
wxUpdateView, EVT_UPDATE_VIEW = NewEvent()
wxUpdateLight, EVT_UPDATE_LIGHT = NewEvent()
Modified: grass/trunk/gui/wxpython/psmap/frame.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/frame.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/psmap/frame.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -41,7 +41,7 @@
from psmap.toolbars import PsMapToolbar
from icon import Icons, MetaIcon, iconSet
from core.gcmd import RunCommand, GError, GMessage
-from core.forms import GUI
+from gui_core.task import GUI
from psmap.dialogs import *
class PsMapFrame(wx.Frame):
Modified: grass/trunk/gui/wxpython/wxgui.py
===================================================================
--- grass/trunk/gui/wxpython/wxgui.py 2011-11-24 11:46:55 UTC (rev 49347)
+++ grass/trunk/gui/wxpython/wxgui.py 2011-11-24 13:56:11 UTC (rev 49348)
@@ -53,7 +53,7 @@
from lmgr.layertree import LayerTree
from lmgr.menudata import ManagerData
from gui_core.widgets import GNotebook
-from modules.histogram import HistFrame
+from modules.histogram import HistogramFrame
from modules.mcalc_builder import MapCalcFrame
from dbm.manager import AttributeManager
from core.workspace import ProcessWorkspaceFile, ProcessGrcFile, WriteWorkspaceFile
@@ -69,7 +69,8 @@
from nviz.tools import NvizToolWindow
from psmap.frame import PsMapFrame
from core.debug import Debug
-from gui_core.ghelp import MenuTreeWindow, AboutWindow, InstallExtensionWindow
+from gui_core.ghelp import MenuTreeWindow, AboutWindow
+from modules.extensions import InstallExtensionWindow
from lmgr.toolbars import LMWorkspaceToolbar, LMDataToolbar, LMToolsToolbar
from lmgr.toolbars import LMMiscToolbar, LMVectorToolbar, LMNvizToolbar
from lmgr.pyshell import PyShellWindow
More information about the grass-commit
mailing list