[GRASS-SVN] r55594 - in grass/trunk/gui/wxpython: . core gmodeler gui_core lmgr modules psmap scripts
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Apr 2 12:17:47 PDT 2013
Author: annakrat
Date: 2013-04-02 12:17:47 -0700 (Tue, 02 Apr 2013)
New Revision: 55594
Added:
grass/trunk/gui/wxpython/core/menutree.py
grass/trunk/gui/wxpython/core/treemodel.py
grass/trunk/gui/wxpython/gui_core/treeview.py
Removed:
grass/trunk/gui/wxpython/core/menudata.py
grass/trunk/gui/wxpython/core/modulesdata.py
Modified:
grass/trunk/gui/wxpython/Makefile
grass/trunk/gui/wxpython/gmodeler/dialogs.py
grass/trunk/gui/wxpython/gmodeler/frame.py
grass/trunk/gui/wxpython/gmodeler/menudata.py
grass/trunk/gui/wxpython/gui_core/goutput.py
grass/trunk/gui/wxpython/gui_core/menu.py
grass/trunk/gui/wxpython/gui_core/prompt.py
grass/trunk/gui/wxpython/gui_core/query.py
grass/trunk/gui/wxpython/gui_core/widgets.py
grass/trunk/gui/wxpython/lmgr/frame.py
grass/trunk/gui/wxpython/lmgr/menudata.py
grass/trunk/gui/wxpython/modules/extensions.py
grass/trunk/gui/wxpython/psmap/frame.py
grass/trunk/gui/wxpython/psmap/menudata.py
grass/trunk/gui/wxpython/scripts/vkrige.py
grass/trunk/gui/wxpython/wxpythonlib.dox
Log:
wxGUI: refactoring tree structures (menu, search tree, extensions, query)
Modified: grass/trunk/gui/wxpython/Makefile
===================================================================
--- grass/trunk/gui/wxpython/Makefile 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/Makefile 2013-04-02 19:17:47 UTC (rev 55594)
@@ -26,9 +26,10 @@
$(ETCDIR)/%: % | $(PYDSTDIRS) $(DSTDIRS)
$(INSTALL_DATA) $< $@
-menustrings.py: core/menudata.py $(ETCDIR)/xml/menudata.xml $(ETCDIR)/xml/menudata_modeler.xml
+menustrings.py: core/menutree.py $(ETCDIR)/xml/menudata.xml $(ETCDIR)/xml/menudata_modeler.xml $(ETCDIR)/xml/menudata_psmap.xml
$(call run_grass,$(PYTHON) $< > $@)
$(call run_grass,$(PYTHON) $< "modeler" >> $@)
+ $(call run_grass,$(PYTHON) $< "psmap" >> $@)
$(PYDSTDIRS): %: | $(ETCDIR)
$(MKDIR) $@
Deleted: grass/trunk/gui/wxpython/core/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/core/menudata.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/core/menudata.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -1,233 +0,0 @@
-"""!
- at package core.menudata
-
- at brief Complex list for menu entries for wxGUI
-
-Classes:
- - menudata::MenuData
-
-Usage:
- at code
-python menudata.py [action] [manager|modeler]
- at endcode
-
-where <i>action</i>:
- - strings (default)
- - tree
- - commands
- - dump
-
-(C) 2007-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 Michael Barton (Arizona State University)
- at author Yann Chemin <yann.chemin gmail.com>
- at author Martin Landa <landa.martin gmail.com>
- at author Glynn Clements
-"""
-
-import os
-import sys
-import pprint
-try:
- import xml.etree.ElementTree as etree
-except ImportError:
- import elementtree.ElementTree as etree # Python <= 2.4
-
-import wx
-
-if not os.getenv("GISBASE"):
- sys.exit("GRASS is not running. Exiting...")
-
-class MenuData:
- """!Abstract menu data class"""
- def __init__(self, filename):
- self.tree = etree.parse(filename)
-
- def _getMenuItem(self, mi):
- """!Get menu item
-
- @param mi menu item instance
- """
- if mi.tag == 'separator':
- return ('', '', '', '', '')
- elif mi.tag == 'menuitem':
- label = _(mi.find('label').text)
- help = _(mi.find('help').text)
- handler = mi.find('handler').text
- gcmd = mi.find('command') # optional
- keywords = mi.find('keywords') # optional
- shortcut = mi.find('shortcut') # optional
- wxId = mi.find('id') # optional
- if gcmd != None:
- gcmd = gcmd.text
- else:
- gcmd = ""
- if keywords != None:
- keywords = keywords.text
- else:
- keywords = ""
- if shortcut != None:
- shortcut = shortcut.text
- else:
- shortcut = ""
- if wxId != None:
- wxId = eval('wx.' + wxId.text)
- else:
- wxId = wx.ID_ANY
- return (label, help, handler, gcmd, keywords, shortcut, wxId)
- elif mi.tag == 'menu':
- return self._getMenu(mi)
- else:
- raise Exception(_("Unknow tag"))
-
- def _getMenu(self, m):
- """!Get menu
-
- @param m menu
-
- @return label, menu items
- """
- label = _(m.find('label').text)
- items = m.find('items')
- return (label, tuple(map(self._getMenuItem, items)))
-
- def _getMenuBar(self, mb):
- """!Get menu bar
-
- @param mb menu bar instance
-
- @return menu items
- """
- return tuple(map(self._getMenu, mb.findall('menu')))
-
- def _getMenuData(self, md):
- """!Get menu data
-
- @param md menu data instace
-
- @return menu data
- """
- return list(map(self._getMenuBar, md.findall('menubar')))
-
- def GetMenu(self):
- """!Get menu
-
- @return menu data
- """
- return self._getMenuData(self.tree.getroot())
-
- def PrintStrings(self, fh):
- """!Print menu strings to file (used for localization)
-
- @param fh file descriptor"""
- className = str(self.__class__).split('.', 1)[1]
- fh.write('menustrings_%s = [\n' % className)
- for node in self.tree.getiterator():
- if node.tag in ['label', 'help']:
- fh.write(' _(%r),\n' % node.text)
- fh.write(' \'\']\n')
-
- def PrintTree(self, fh):
- """!Print menu tree to file
-
- @param fh file descriptor"""
- level = 0
- for eachMenuData in self.GetMenu():
- for label, items in eachMenuData:
- fh.write('- %s\n' % label.replace('&', ''))
- self._PrintTreeItems(fh, level + 1, items)
-
- def _PrintTreeItems(self, fh, level, menuData):
- """!Print menu tree items to file (used by PrintTree)
-
- @param fh file descriptor
- @param level menu level
- @param menuData menu data to print out"""
- for eachItem in menuData:
- if len(eachItem) == 2:
- if eachItem[0]:
- fh.write('%s - %s\n' % (' ' * level, eachItem[0]))
- self._PrintTreeItems(fh, level + 1, eachItem[1])
- else:
- if eachItem[0]:
- fh.write('%s - %s\n' % (' ' * level, eachItem[0]))
-
- def PrintCommands(self, fh, itemSep = ' | ', menuSep = ' > '):
- """!Print commands list (command | menu item > menu item)
-
- @param fh file descriptor
- """
- level = 0
- for eachMenuData in self.GetMenu():
- for label, items in eachMenuData:
- menuItems = [label, ]
- self._PrintCommandsItems(fh, level + 1, items,
- menuItems, itemSep, menuSep)
-
- def _PrintCommandsItems(self, fh, level, menuData,
- menuItems, itemSep, menuSep):
- """!Print commands item (used by PrintCommands)
-
- @param fh file descriptor
- @param menuItems list of menu items
- """
- for eachItem in menuData:
- if len(eachItem) == 2:
- if eachItem[0]:
- try:
- menuItems[level] = eachItem[0]
- except IndexError:
- menuItems.append(eachItem[0])
- self._PrintCommandsItems(fh, level + 1, eachItem[1],
- menuItems, itemSep, menuSep)
- else:
- try:
- del menuItems[level]
- except IndexError:
- pass
-
- if eachItem[3]:
- fh.write('%s%s' % (eachItem[3], itemSep))
- fh.write(menuSep.join(map(lambda x: x.replace('&', ''), menuItems)))
- fh.write('%s%s' % (menuSep, eachItem[0]))
- fh.write('\n')
-
-if __name__ == "__main__":
- import os
- import sys
-
- # i18N
- import gettext
- gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
-
- action = 'strings'
- menu = 'manager'
-
- for arg in sys.argv:
- if arg in ('strings', 'tree', 'commands', 'dump'):
- action = arg
- elif arg in ('manager', 'modeler'):
- menu = arg
-
- sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "gui", "wxpython"))
-
- if menu == 'manager':
- from lmgr.menudata import LayerManagerMenuData
- data = LayerManagerMenuData()
- else:
- from gmodeler.menudata import ModelerMenuData
- data = ModelerMenuData()
-
- if action == 'strings':
- data.PrintStrings(sys.stdout)
- elif action == 'tree':
- data.PrintTree(sys.stdout)
- elif action == 'commands':
- data.PrintCommands(sys.stdout)
- elif action == 'dump':
- pprint.pprint(data.GetMenu(), stream = sys.stdout, indent = 2)
-
- sys.exit(0)
Added: grass/trunk/gui/wxpython/core/menutree.py
===================================================================
--- grass/trunk/gui/wxpython/core/menutree.py (rev 0)
+++ grass/trunk/gui/wxpython/core/menutree.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -0,0 +1,233 @@
+"""!
+ at package core.menutree
+
+ at brief Creates tree structure for wxGUI menus (former menudata.py)
+
+Classes:
+ - menutree::MenuTreeModelBuilder
+
+Usage:
+ at code
+python menutree.py [action] [menu]
+ at endcode
+
+where <i>action</i>:
+ - strings (default, used for translations)
+ - tree (simple tree structure)
+ - commands (command names and their place in tree)
+ - dump (tree structure with stored data)
+
+and <i>menu</i>:
+ - manager (Layer Manager)
+ - modeler (Graphical Modeler)
+ - psmap (Cartographic Composer)
+
+(C) 2013 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 Glynn Clements (menudata.py)
+ at author Martin Landa <landa.martin gmail.com> (menudata.py)
+ at author Anna Petrasova <kratochanna gmail.com>
+"""
+
+import os
+import sys
+import copy
+try:
+ import xml.etree.ElementTree as etree
+except ImportError:
+ import elementtree.ElementTree as etree # Python <= 2.4
+
+import wx
+
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+from core.treemodel import TreeModel, ModuleNode
+from core.settings import UserSettings
+
+if not os.getenv("GISBASE"):
+ sys.exit("GRASS is not running. Exiting...")
+
+class MenuTreeModelBuilder:
+ """!Abstract menu data class"""
+ def __init__(self, filename):
+
+ self.menustyle = UserSettings.Get(group = 'appearance',
+ key = 'menustyle',
+ subkey = 'selection')
+
+ xmlTree = etree.parse(filename)
+ self.model = TreeModel(ModuleNode)
+ self._createModel(xmlTree)
+
+ def _createModel(self, xmlTree):
+ root = xmlTree.getroot()
+ menubar = root.findall('menubar')[0]
+ menus = menubar.findall('menu')
+ for m in menus:
+ self._createMenu(m, self.model.root)
+
+ def _createMenu(self, menu, node):
+ label = _(menu.find('label').text)
+ items = menu.find('items')
+ node = self.model.AppendNode(parent=node, label=label)
+ for item in items:
+ self._createItem(item, node)
+
+ def _createItem(self, item, node):
+ if item.tag == 'separator':
+ data = dict(label='', description='', handler='',
+ command='', keywords='', shortcut='', wxId='')
+ self.model.AppendNode(parent=node, label='', data=data)
+ elif item.tag == 'menuitem':
+ label = _(item.find('label').text)
+ desc = _(item.find('help').text)
+ handler = item.find('handler').text
+ gcmd = item.find('command') # optional
+ keywords = item.find('keywords') # optional
+ shortcut = item.find('shortcut') # optional
+ wxId = item.find('id') # optional
+ if gcmd != None:
+ gcmd = gcmd.text
+ else:
+ gcmd = ""
+ if keywords != None:
+ keywords = keywords.text
+ else:
+ keywords = ""
+ if shortcut != None:
+ shortcut = shortcut.text
+ else:
+ shortcut = ""
+ if wxId != None:
+ wxId = eval('wx.' + wxId.text)
+ else:
+ wxId = wx.ID_ANY
+ if gcmd:
+ if self.menustyle == 1:
+ label += ' [' + gcmd + ']'
+ elif self.menustyle == 2:
+ label = ' [' + gcmd + ']'
+ data = dict(label=label, description=desc, handler=handler,
+ command=gcmd, keywords=keywords, shortcut=shortcut, wxId=wxId)
+ self.model.AppendNode(parent=node, label=label, data=data)
+ elif item.tag == 'menu':
+ self._createMenu(item, node)
+ else:
+ raise Exception(_("Unknow tag %s") % item.tag)
+
+ def GetModel(self, separators=False):
+ """Returns copy of model with or without separators
+ (for menu or for search tree).
+ """
+ if separators:
+ return copy.deepcopy(self.model)
+ else:
+ model = copy.deepcopy(self.model)
+ removeSeparators(model)
+ return model
+
+ def PrintTree(self, fh):
+ for child in self.model.root.children:
+ printTree(node=child, fh=fh)
+
+ def PrintStrings(self, fh):
+ """!Print menu strings to file (used for localization)
+
+ @param fh file descriptor
+ """
+ className = str(self.__class__).split('.', 1)[1]
+ fh.write('menustrings_%s = [\n' % className)
+ for child in self.model.root.children:
+ printStrings(child, fh)
+ fh.write(' \'\']\n')
+
+ def PrintCommands(self, fh):
+ printCommands(self.model.root, fh, itemSep=' | ', menuSep=' > ')
+
+def removeSeparators(model, node=None):
+ if not node:
+ node = model.root
+ if node.label:
+ for child in reversed(node.children):
+ removeSeparators(model, child)
+ else:
+ model.RemoveNode(node)
+
+def printTree(node, fh, indent=0):
+ if not node.label:
+ return
+ text = '%s- %s\n' % (' ' * indent, node.label.replace('&', ''))
+ fh.write(text)
+ for child in node.children:
+ printTree(node=child, fh=fh, indent=indent + 2)
+
+def printStrings(node, fh):
+ if node.label:
+ fh.write(' _(%r),\n' % str(node.label))
+ if node.data:
+ if 'description' in node.data and node.data['description']:
+ fh.write(' _(%r),\n' % str(node.data['description']))
+ for child in node.children:
+ printStrings(node=child, fh=fh)
+
+def printCommands(node, fh, itemSep, menuSep):
+
+ def collectParents(node, parents):
+ parent = node.parent
+ if parent.parent:
+ parents.insert(0, node.parent)
+ collectParents(node.parent, parents)
+
+ data = node.data
+ if data and 'command' in data and data['command']:
+ fh.write('%s%s' % (data['command'], itemSep))
+ parents = [node]
+ collectParents(node, parents)
+ labels = [parent.label.replace('&', '') for parent in parents]
+ fh.write(menuSep.join(labels))
+ fh.write('\n')
+
+ for child in node.children:
+ printCommands(child, fh, itemSep, menuSep)
+
+
+if __name__ == "__main__":
+ # i18N
+ import gettext
+ gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
+
+ action = 'strings'
+ menu = 'manager'
+
+ for arg in sys.argv:
+ if arg in ('strings', 'tree', 'commands', 'dump'):
+ action = arg
+ elif arg in ('manager', 'modeler', 'psmap'):
+ menu = arg
+
+ sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "gui", "wxpython"))
+
+
+ if menu == 'manager':
+ from lmgr.menudata import LayerManagerMenuData
+ menudata = LayerManagerMenuData()
+ elif menu == 'modeler':
+ from gmodeler.menudata import ModelerMenuData
+ menudata = ModelerMenuData()
+ elif menu == 'psmap':
+ from psmap.menudata import PsMapMenuData
+ menudata = PsMapMenuData()
+
+ if action == 'strings':
+ menudata.PrintStrings(sys.stdout)
+ elif action == 'tree':
+ menudata.PrintTree(sys.stdout)
+ elif action == 'commands':
+ menudata.PrintCommands(sys.stdout)
+ elif action == 'dump':
+ print menudata.model
+
+ sys.exit(0)
Deleted: grass/trunk/gui/wxpython/core/modulesdata.py
===================================================================
--- grass/trunk/gui/wxpython/core/modulesdata.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/core/modulesdata.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -1,189 +0,0 @@
-"""!
- at package core.modulesdata
-
- at brief Provides information about available modules
-
-Classes:
- - modules::modulesdata
-
-(C) 2009-2012 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>
- at author Vaclav Petras <wenzeslaus gmail.com>
- at author Anna Kratochvilova <kratochanna gmail.com>
-"""
-
-import sys
-import os
-
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
-
-from core import globalvar
-from lmgr.menudata import LayerManagerMenuData
-
-
-class ModulesData(object):
- """!Holds information about modules.
-
- @todo add doctest
- @todo analyze what exactly this class is doing
- @todo split this class into two classes
-
- @see modules::extensions::ExtensionModulesData
- """
- def __init__(self, modulesDesc = None):
-
- if modulesDesc is not None:
- self.moduleDesc = modulesDesc
- else:
- self.moduleDesc = LayerManagerMenuData().GetModules()
-
- self.moduleDict = self.GetDictOfModules()
-
- def GetCommandDesc(self, cmd):
- """!Gets the description for a given module (command).
-
- If the given module is not available, an empty string is returned.
-
- \code
- print data.GetCommandDesc('r.info')
- Outputs basic information about a raster map.
- \endcode
- """
- if cmd in self.moduleDesc:
- return self.moduleDesc[cmd]['description']
-
- return ''
-
- def GetCommandItems(self):
- """!Gets list of available modules (commands).
-
- The list contains available module names.
-
- \code
- print data.GetCommandItems()[0:4]
- ['d.barscale', 'd.colorlist', 'd.colortable', 'd.correlate']
- \endcode
- """
- items = list()
-
- mList = self.moduleDict
-
- prefixes = mList.keys()
- prefixes.sort()
-
- for prefix in prefixes:
- for command in mList[prefix]:
- name = prefix + '.' + command
- if name not in items:
- items.append(name)
-
- items.sort()
-
- return items
-
- def GetDictOfModules(self):
- """!Gets modules as a dictionary optimized for autocomplete.
-
- \code
- print data.GetDictOfModules()['r'][0:4]
- print data.GetDictOfModules()['r.li'][0:4]
- r: ['basins.fill', 'bitpattern', 'blend', 'buffer']
- r.li: ['cwed', 'dominance', 'edgedensity', 'mpa']
- \endcode
- """
- result = dict()
- for module in globalvar.grassCmd:
- try:
- group, name = module.split('.', 1)
- except ValueError:
- continue # TODO
-
- if group not in result:
- result[group] = list()
- result[group].append(name)
-
- # for better auto-completion:
- # not only result['r']={...,'colors.out',...}
- # but also result['r.colors']={'out',...}
- for i in range(len(name.split('.')) - 1):
- group = '.'.join([group, name.split('.', 1)[0]])
- name = name.split('.', 1)[1]
- if group not in result:
- result[group] = list()
- result[group].append(name)
-
- # sort list of names
- for group in result.keys():
- result[group].sort()
-
- return result
-
- def FindModules(self, text, findIn):
- """!Finds modules according to given text.
-
- @param text string to search
- @param findIn where to search for text
- (allowed values are 'description', 'keywords' and 'command')
- """
- modules = dict()
- iFound = 0
- for module, data in self.moduleDesc.iteritems():
- found = False
- if findIn == 'description':
- if text in data['description']:
- found = True
- elif findIn == 'keywords':
- if text in ','.join(data['keywords']):
- found = True
- elif findIn == 'command':
- if module[:len(text)] == text:
- found = True
- else:
- raise ValueError("Parameter findIn is not valid")
-
- if found:
- try:
- group, name = module.split('.')
- except ValueError:
- continue # TODO
- iFound += 1
- if group not in modules:
- modules[group] = list()
- modules[group].append(name)
- return modules, iFound
-
- def SetFilter(self, data = None):
- """!Sets filter modules
-
- If @p data is not specified, module dictionary is derived
- from an internal data structures.
-
- @todo Document this method.
-
- @param data data dict
- """
- if data:
- self.moduleDict = data
- else:
- self.moduleDict = self.GetDictOfModules()
-
-
-def test():
- data = ModulesData()
- module = 'r.info'
- print '%s:' % module, data.GetCommandDesc(module)
- print '[0:5]:', data.GetCommandItems()[0:5]
-
- modules = data.GetDictOfModules()
- print 'r:', modules['r'][0:4]
- print 'r.li:', modules['r.li'][0:4]
-
-
-
-if __name__ == '__main__':
- test()
\ No newline at end of file
Added: grass/trunk/gui/wxpython/core/treemodel.py
===================================================================
--- grass/trunk/gui/wxpython/core/treemodel.py (rev 0)
+++ grass/trunk/gui/wxpython/core/treemodel.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -0,0 +1,209 @@
+"""!
+ at package core.treemodel
+
+ at brief tree structure model (used for menu, search tree)
+
+Classes:
+ - treemodel::TreeModel
+ - treemodel::DictNode
+ - treemodel::ModuleNode
+
+(C) 2013 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 Anna Petrasova <kratochanna gmail.com>
+"""
+
+
+class TreeModel(object):
+ """!Class represents a tree structure with hidden root.
+
+ TreeModel is used together with TreeView class to display results in GUI.
+ The functionality is not complete, only needed methods are implemented.
+ If needed, the functionality can be extended.
+
+ >>> tree = TreeModel(DictNode)
+ >>> root = tree.root
+ >>> n1 = tree.AppendNode(parent=root, label='node1')
+ >>> n2 = tree.AppendNode(parent=root, label='node2')
+ >>> n11 = tree.AppendNode(parent=n1, label='node11', data={'xxx': 1})
+ >>> n111 = tree.AppendNode(parent=n11, label='node111', data={'xxx': 4})
+ >>> n12 = tree.AppendNode(parent=n1, label='node12', data={'xxx': 2})
+ >>> n21 = tree.AppendNode(parent=n2, label='node21', data={'xxx': 1})
+ >>> [node.label for node in tree.SearchNodes(key='xxx', value=1)]
+ ['node11', 'node21']
+ >>> [node.label for node in tree.SearchNodes(key='xxx', value=5)]
+ []
+ >>> tree.GetIndexOfNode(n111)
+ [0, 0, 0]
+ >>> tree.GetNodeByIndex((0,1)).label
+ 'node12'
+ >>> print tree
+ node1
+ node11
+ * xxx : 1
+ node111
+ * xxx : 4
+ node12
+ * xxx : 2
+ node2
+ node21
+ * xxx : 1
+ """
+ def __init__(self, nodeClass):
+ """!Constructor creates root node.
+
+ @param nodeClass class which is used for creating nodes
+ """
+ self._root = nodeClass('root')
+ self.nodeClass = nodeClass
+
+ @property
+ def root(self):
+ return self._root
+
+ def AppendNode(self, parent, label, data=None):
+ """!Create node and append it to parent node.
+
+ @param parent parent node of the new node
+ @param label node label
+ @param data optional node data
+
+ @return new node
+ """
+ node = self.nodeClass(label=label, data=data)
+ parent.children.append(node)
+ node.parent = parent
+ return node
+
+ def SearchNodes(self, **kwargs):
+ """!Search nodes according to specified attributes."""
+ nodes = []
+ self._searchNodes(node=self.root, foundNodes=nodes, **kwargs)
+ return nodes
+
+ def _searchNodes(self, node, foundNodes, **kwargs):
+ """!Helper method for searching nodes."""
+ if node.match(**kwargs):
+ foundNodes.append(node)
+ for child in node.children:
+ self._searchNodes(node=child, foundNodes=foundNodes, **kwargs)
+
+ def GetNodeByIndex(self, index):
+ """!Method used for communication between view (VirtualTree) and model.
+
+ @param index index of node, as defined in VirtualTree doc
+ (e.g. root ~ [], second node of a first node ~ [0, 1])
+ """
+ if len(index) == 0:
+ return self.root
+ return self._getNode(self.root, index)
+
+ def GetIndexOfNode(self, node):
+ """!Method used for communication between view (VirtualTree) and model."""
+ index = []
+ return self._getIndex(node, index)
+
+
+ def _getIndex(self, node, index):
+ if node.parent:
+ index.insert(0, node.parent.children.index(node))
+ return self._getIndex(node.parent, index)
+ return index
+
+
+ def GetChildrenByIndex(self, index):
+ """!Method used for communication between view (VirtualTree) and model."""
+ if len(index) == 0:
+ return self.root.children
+ node = self._getNode(self.root, index)
+ return node.children
+
+ def _getNode(self, node, index):
+ if len(index) == 1:
+ return node.children[index[0]]
+ else:
+ return self._getNode(node.children[index[0]], index[1:])
+
+ def RemoveNode(self, node):
+ """!Removes node."""
+ if node.parent:
+ node.parent.children.remove(node)
+
+ def __str__(self):
+ """!Print tree."""
+ text = []
+ for child in self.root.children:
+ child.nprint(text)
+ return "\n".join(text)
+
+
+class DictNode(object):
+ """!Node which has data in a form of dictionary."""
+ def __init__(self, label, data=None):
+ """!Create node.
+
+ @param label node label (displayed in GUI)
+ @param data data as dictionary or None
+ """
+
+ self.label = label
+ if data == None:
+ self.data = dict()
+ else:
+ self.data = data
+ self._children = []
+ self.parent = None
+
+ @property
+ def children(self):
+ return self._children
+
+ def nprint(self, text, indent=0):
+ text.append(indent * ' ' + self.label)
+ if self.data:
+ for key, value in self.data.iteritems():
+ text.append("%(indent)s* %(key)s : %(value)s" % {'indent': (indent + 2) * ' ',
+ 'key': key,
+ 'value': value})
+
+ if self.children:
+ for child in self.children:
+ child.nprint(text, indent + 2)
+
+ def match(self, key, value):
+ """!Method used for searching according to given parameters.
+
+ @param value dictionary value to be matched
+ @param key data dictionary key
+ """
+ if key in self.data and self.data[key] == value:
+ return True
+ return False
+
+
+class ModuleNode(DictNode):
+ """!Node representing module."""
+ def __init__(self, label, data=None):
+ super(ModuleNode, self).__init__(label=label, data=data)
+
+ def match(self, key, value):
+ """!Method used for searching according to command,
+ keywords or description."""
+ if not self.data:
+ return False
+ if key in ('command', 'keywords', 'description'):
+ return len(self.data[key]) and value in self.data[key]
+
+ return False
+
+
+def main():
+ import doctest
+ doctest.testmod()
+
+
+if __name__ == '__main__':
+ main()
Modified: grass/trunk/gui/wxpython/gmodeler/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/dialogs.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gmodeler/dialogs.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -31,7 +31,6 @@
from core import globalvar
from core import utils
-from core.modulesdata import ModulesData
from gui_core.widgets import SearchModuleWidget, SimpleValidator
from core.gcmd import GError, EncodeString
from gui_core.dialogs import SimpleDialog, MapLayersDialogForModeler
@@ -39,6 +38,7 @@
from gui_core.forms import CmdPanel
from gui_core.gselect import Select, ElementSelect
from gmodeler.model import *
+from lmgr.menudata import LayerManagerMenuData
from grass.script import task as gtask
@@ -138,7 +138,7 @@
self.Destroy()
class ModelSearchDialog(wx.Dialog):
- def __init__(self, parent, id = wx.ID_ANY, title = _("Add new GRASS module to the model"),
+ def __init__(self, parent, title = _("Add new GRASS module to the model"),
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
"""!Graphical modeler module search window
@@ -149,7 +149,7 @@
"""
self.parent = parent
- wx.Dialog.__init__(self, parent = parent, id = id, title = title, **kwargs)
+ wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, **kwargs)
self.SetName("ModelerDialog")
self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
@@ -158,12 +158,14 @@
self.cmdBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
label=" %s " % _("Command"))
-
- modulesData = ModulesData()
- self.cmd_prompt = GPromptSTC(parent = self, modulesData = modulesData, updateCmdHistory = False)
+
+ # menu data for search widget and prompt
+ menuModel = LayerManagerMenuData()
+
+ self.cmd_prompt = GPromptSTC(parent = self, menuModel = menuModel.GetModel(), updateCmdHistory = False)
self.cmd_prompt.promptRunCmd.connect(self.OnCommand)
self.search = SearchModuleWidget(parent = self.panel,
- modulesData = modulesData,
+ model = menuModel.GetModel(),
showTip = True)
self.search.moduleSelected.connect(lambda name:
self.cmd_prompt.SetTextAndFocus(name + ' '))
@@ -172,10 +174,7 @@
self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
self.btnOk = wx.Button(self.panel, wx.ID_OK)
self.btnOk.SetDefault()
- self.btnOk.Enable(False)
- self.cmd_prompt.Bind(wx.EVT_KEY_UP, self.OnText)
- self.search.searchChoice.Bind(wx.EVT_CHOICE, self.OnText)
self.Bind(wx.EVT_BUTTON, self.OnOk, self.btnOk)
self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)
@@ -256,31 +255,10 @@
"""Cancel pressed, close window"""
self.Hide()
- def OnText(self, event):
- """!Text in prompt changed"""
- if self.cmd_prompt.AutoCompActive():
- event.Skip()
- return
-
- if isinstance(event, wx.KeyEvent):
- entry = self.cmd_prompt.GetTextLeft()
- elif isinstance(event, wx.stc.StyledTextEvent):
- entry = event.GetText()
- else:
- entry = event.GetString()
-
- if entry:
- self.btnOk.Enable()
- else:
- self.btnOk.Enable(False)
-
- event.Skip()
-
def Reset(self):
"""!Reset dialog"""
self.search.Reset()
self.cmd_prompt.OnCmdErase(None)
- self.btnOk.Enable(False)
self.cmd_prompt.SetFocus()
class ModelRelationDialog(wx.Dialog):
Modified: grass/trunk/gui/wxpython/gmodeler/frame.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/frame.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gmodeler/frame.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -42,7 +42,6 @@
from gui_core.dialogs import GetImageHandlers
from gui_core.preferences import PreferencesBaseDialog
from core.settings import UserSettings
-from core.menudata import MenuData
from gui_core.menu import Menu
from gmodeler.menudata import ModelerMenuData
from gui_core.forms import GUI
@@ -82,8 +81,7 @@
self.SetName("Modeler")
self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
- self.menubar = Menu(parent = self, data = ModelerMenuData())
-
+ self.menubar = Menu(parent = self, model = ModelerMenuData().GetModel())
self.SetMenuBar(self.menubar)
self.toolbar = ModelerToolbar(parent = self)
Modified: grass/trunk/gui/wxpython/gmodeler/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/menudata.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gmodeler/menudata.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -16,14 +16,13 @@
import os
-from core import globalvar
-from core.menudata import MenuData
+from core import globalvar
+from core.menutree import MenuTreeModelBuilder
-class ModelerMenuData(MenuData):
+class ModelerMenuData(MenuTreeModelBuilder):
def __init__(self, filename = None):
if not filename:
- gisbase = os.getenv('GISBASE')
- filename = os.path.join(globalvar.ETCWXDIR, 'xml', 'menudata_modeler.xml')
+ filename = os.path.join(globalvar.ETCWXDIR, 'xml', 'menudata_modeler.xml')
- MenuData.__init__(self, filename)
+ MenuTreeModelBuilder.__init__(self, filename)
Modified: grass/trunk/gui/wxpython/gui_core/goutput.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/goutput.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gui_core/goutput.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -38,7 +38,6 @@
from gui_core.prompt import GPromptSTC
from core.settings import UserSettings
from gui_core.widgets import SearchModuleWidget
-from core.modulesdata import ModulesData
GC_EMPTY = 0
@@ -54,19 +53,19 @@
class GConsoleWindow(wx.SplitterWindow):
"""!Create and manage output console for commands run by GUI.
"""
- def __init__(self, parent, gconsole, margin = False,
+ def __init__(self, parent, gconsole, menuModel = None, margin = False,
style = wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
gcstyle = GC_EMPTY,
**kwargs):
"""!
@param parent gui parent
+ @param gconsole console logic
+ @param menuModel tree model of modules (from menu)
@param margin use margin in output pane (GStc)
@param style wx.SplitterWindow style
@param gcstyle GConsole style
(GC_EMPTY, GC_PROMPT to show command prompt,
GC_SEARCH to show search widget)
- @param ignoredCmdPattern regular expression specifying commads
- to be ignored (e.g. @c '^d\..*' for display commands)
"""
wx.SplitterWindow.__init__(self, parent, id = wx.ID_ANY, style = style, **kwargs)
self.SetName("GConsole")
@@ -77,6 +76,7 @@
# initialize variables
self.parent = parent # GMFrame | CmdPanel | ?
self._gconsole = gconsole
+ self._menuModel = menuModel
self._gcstyle = gcstyle
self.lineWidth = 80
@@ -115,13 +115,10 @@
wrap = None)
self.cmdOutput.Bind(stc.EVT_STC_CHANGE, self.OnStcChanged)
- # information about available modules
- modulesData = ModulesData()
-
# search & command prompt
# move to the if below
# search depends on cmd prompt
- self.cmdPrompt = GPromptSTC(parent = self, modulesData = modulesData)
+ self.cmdPrompt = GPromptSTC(parent=self, menuModel=self._menuModel)
self.cmdPrompt.promptRunCmd.connect(lambda cmd:
self._gconsole.RunCmd(command=cmd))
self.cmdPrompt.showNotification.connect(self.showNotification)
@@ -137,7 +134,7 @@
label = self.infoCollapseLabelExp,
style = wx.CP_DEFAULT_STYLE |
wx.CP_NO_TLW_RESIZE | wx.EXPAND)
- self.MakeSearchPaneContent(self.searchPane.GetPane(), modulesData)
+ self.MakeSearchPaneContent(self.searchPane.GetPane(), self._menuModel)
self.searchPane.Collapse(True)
self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnSearchPaneChanged, self.searchPane)
self.search.moduleSelected.connect(lambda name:
@@ -256,12 +253,12 @@
self.SetAutoLayout(True)
self.Layout()
- def MakeSearchPaneContent(self, pane, modulesData):
+ def MakeSearchPaneContent(self, pane, model):
"""!Create search pane"""
border = wx.BoxSizer(wx.VERTICAL)
self.search = SearchModuleWidget(parent = pane,
- modulesData = modulesData)
+ model = model)
self.search.showNotification.connect(self.showNotification)
@@ -722,8 +719,11 @@
panel = wx.Panel(self, id = wx.ID_ANY)
+ from lmgr.menudata import LayerManagerMenuData
+ menuTreeBuilder = LayerManagerMenuData()
self.gconsole = GConsole(guiparent=self)
self.goutput = GConsoleWindow(parent = panel, gconsole = self.gconsole,
+ menuModel=menuTreeBuilder.GetModel(),
gcstyle = GC_SEARCH | GC_PROMPT)
mainSizer = wx.BoxSizer(wx.VERTICAL)
Modified: grass/trunk/gui/wxpython/gui_core/menu.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/menu.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gui_core/menu.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -6,7 +6,6 @@
Classes:
- menu::Menu
- menu::SearchModuleWindow
- - menu::MenuTree
(C) 2010-2012 by the GRASS Development Team
@@ -24,44 +23,39 @@
from core import globalvar
from core import utils
-from core.modulesdata import ModulesData
from core.gcmd import EncodeString
-from core.settings import UserSettings
-from gui_core.widgets import ItemTree, SearchModuleWidget
-from lmgr.menudata import LayerManagerMenuData
+from gui_core.widgets import SearchModuleWidget
+from gui_core.treeview import CTreeView
+from grass.pydispatch.signal import Signal
+
class Menu(wx.MenuBar):
- def __init__(self, parent, data):
+ def __init__(self, parent, model):
"""!Creates menubar"""
wx.MenuBar.__init__(self)
- self.parent = parent
- self.menudata = data
- self.menucmd = dict()
+ self.parent = parent
+ self.model = model
+ self.menucmd = dict()
+
+ for child in self.model.root.children:
+ self.Append(self._createMenu(child), child.label)
- self.menustyle = UserSettings.Get(group = 'appearance', key = 'menustyle', subkey = 'selection')
-
- for eachMenuData in self.menudata.GetMenu():
- for eachHeading in eachMenuData:
- menuLabel = eachHeading[0]
- menuItems = eachHeading[1]
- self.Append(self._createMenu(menuItems), menuLabel)
-
- def _createMenu(self, menuData):
+ def _createMenu(self, node):
"""!Creates menu"""
menu = wx.Menu()
- for eachItem in menuData:
- if len(eachItem) == 2:
- label = eachItem[0]
- subMenu = self._createMenu(eachItem[1])
+ for child in node.children:
+ if child.children:
+ label = child.label
+ subMenu = self._createMenu(child)
menu.AppendMenu(wx.ID_ANY, label, subMenu)
else:
- self._createMenuItem(menu, self.menustyle, *eachItem)
+ self._createMenuItem(menu, **child.data)
self.parent.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
return menu
- def _createMenuItem(self, menu, menustyle, label, help, handler, gcmd, keywords,
+ def _createMenuItem(self, menu, label, description, handler, command, keywords,
shortcut = '', wxId = wx.ID_ANY, kind = wx.ITEM_NORMAL):
"""!Creates menu items
There are three menu styles (menu item text styles).
@@ -71,42 +65,37 @@
menu.AppendSeparator()
return
- if gcmd:
- helpString = gcmd + ' -- ' + help
- if menustyle == 1:
- label += ' [' + gcmd + ']'
- elif menustyle == 2:
- label = ' [' + gcmd + ']'
+ if command:
+ helpString = command + ' -- ' + description
else:
- helpString = help
+ helpString = description
if shortcut:
label += '\t' + shortcut
menuItem = menu.Append(wxId, label, helpString, kind)
- self.menucmd[menuItem.GetId()] = gcmd
+ self.menucmd[menuItem.GetId()] = command
- if gcmd:
+ if command:
try:
- cmd = utils.split(str(gcmd))
+ cmd = utils.split(str(command))
except UnicodeError:
- cmd = utils.split(EncodeString((gcmd)))
+ cmd = utils.split(EncodeString((command)))
if cmd and cmd[0] not in globalvar.grassCmd:
menuItem.Enable(False)
-
+
rhandler = eval('self.parent.' + handler)
-
self.parent.Bind(wx.EVT_MENU, rhandler, menuItem)
-
+
def GetData(self):
"""!Get menu data"""
- return self.menudata
+ return self.model
def GetCmd(self):
- """!Get list of commands
+ """!Get dictionary of commands (key is id)
- @return list of commands
+ @return dictionary of commands
"""
return self.menucmd
@@ -125,63 +114,62 @@
event.Skip()
class SearchModuleWindow(wx.Panel):
- """!Show menu tree"""
- def __init__(self, parent, id = wx.ID_ANY, **kwargs):
+ """!Menu tree and search widget for searching modules.
+
+ Signal:
+ showNotification - attribute 'message'
+ """
+ def __init__(self, parent, model, id = wx.ID_ANY, **kwargs):
self.parent = parent # LayerManager
+ self.showNotification = Signal('SearchModuleWindow.showNotification')
wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
- self.dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
- label = " %s " % _("Menu tree (double-click or Ctrl-Enter to run command)"))
# tree
- menuData = LayerManagerMenuData()
- self.tree = MenuTree(parent = self, data = menuData)
- self.tree.Load()
+ self._tree = CTreeView(model=model, parent=self)
+ self._dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
+ label = " %s " % _("Menu tree (double-click or Ctrl-Enter to run command)"))
+
# search widget
- self.search = SearchModuleWidget(parent = self,
- modulesData = ModulesData(menuData.GetModules()),
- showChoice = False)
+ self._search = SearchModuleWidget(parent=self,
+ model=model,
+ showChoice=False)
+ self._search.showSearchResult.connect(lambda result: self._tree.Select(result))
+ self._search.showNotification.connect(self.showNotification)
# buttons
- self.btnRun = wx.Button(self, id = wx.ID_OK, label = _("&Run"))
- self.btnRun.SetToolTipString(_("Run selected command from the menu tree"))
- self.btnRun.Enable(False)
+ self._btnRun = wx.Button(self, id=wx.ID_OK, label=_("&Run"))
+ self._btnRun.SetToolTipString(_("Run selected command from the menu tree"))
# bindings
- self.btnRun.Bind(wx.EVT_BUTTON, self.OnRun)
- self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
- self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnItemSelected)
- self.search.GetCtrl().Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
- self.search.GetCtrl().Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self._btnRun.Bind(wx.EVT_BUTTON, lambda evt: self.Run())
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+ self._tree.selectionChanged.connect(self.OnItemSelected)
+ self._tree.itemActivated.connect(lambda node: self.Run(node))
- # because number of matched items differs
- # from number of matched items in tree
- # TODO: find the reason for this difference
- # TODO: use this event for updating statusbar
- # TODO: some showNotification usage?
-
self._layout()
- self.search.SetFocus()
+ self._search.SetFocus()
def _layout(self):
"""!Do dialog layout"""
sizer = wx.BoxSizer(wx.VERTICAL)
# body
- dataSizer = wx.StaticBoxSizer(self.dataBox, wx.HORIZONTAL)
- dataSizer.Add(item = self.tree, proportion =1,
+ dataSizer = wx.StaticBoxSizer(self._dataBox, wx.HORIZONTAL)
+ dataSizer.Add(item = self._tree, proportion =1,
flag = wx.EXPAND)
# buttons
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
- btnSizer.Add(item = self.btnRun, proportion = 0)
+ btnSizer.Add(item = self._btnRun, proportion = 0)
sizer.Add(item = dataSizer, proportion = 1,
flag = wx.EXPAND | wx.ALL, border = 5)
- sizer.Add(item = self.search, proportion = 0,
+ sizer.Add(item = self._search, proportion = 0,
flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
sizer.Add(item = btnSizer, proportion = 0,
@@ -196,142 +184,41 @@
self.SetAutoLayout(True)
self.Layout()
- def OnCloseWindow(self, event):
- """!Close window"""
- self.Destroy()
+ def Run(self, module=None):
+ """!Run selected command.
- def OnRun(self, event):
- """!Run selected command"""
- if not self.tree.GetSelected():
- return # should not happen
-
- data = self.tree.GetPyData(self.tree.GetSelected())
+ @param module module (represented by tree node)
+ """
+ if module is None:
+ if not self._tree.GetSelected():
+ return
+
+ module = self._tree.GetSelected()[0]
+ data = module.data
if not data:
return
handler = 'self.parent.' + data['handler'].lstrip('self.')
- if data['handler'] == 'self.OnXTerm':
- wx.MessageBox(parent = self,
- message = _('You must run this command from the menu or command line',
- 'This command require an XTerm'),
- caption = _('Message'), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
- elif data['command']:
- eval(handler)(event = None, cmd = data['command'].split())
+
+ if data['command']:
+ eval(handler)(event=None, cmd=data['command'].split())
else:
- eval(handler)(None)
+ eval(handler)(event=None)
def OnKeyUp(self, event):
- if event.GetKeyCode() == wx.WXK_RETURN:
- if event.ControlDown():
- self.OnRun(event)
- else:
- self.OnShowItem(event)
+ """!Key or key combination pressed"""
+ if event.ControlDown() and event.GetKeyCode() == wx.WXK_RETURN:
+ self.Run()
- def OnShowItem(self, event):
- """!Show selected item"""
- self.tree.OnShowItem(event)
- if self.tree.GetSelected():
- self.btnRun.Enable()
- else:
- self.btnRun.Enable(False)
-
- def OnItemActivated(self, event):
- """!Item activated (double-click)"""
- item = event.GetItem()
- if not item or not item.IsOk():
- return
-
- data = self.tree.GetPyData(item)
+ def OnItemSelected(self, node):
+ """!Item selected"""
+ data = node.data
if not data or 'command' not in data:
return
- self.tree.itemSelected = item
-
- self.OnRun(None)
-
- def OnItemSelected(self, event):
- """!Item selected"""
- item = event.GetItem()
- if not item or not item.IsOk():
- return
-
- data = self.tree.GetPyData(item)
- if not data or 'command' not in data:
- return
-
if data['command']:
label = data['command'] + ' -- ' + data['description']
else:
label = data['description']
- self.parent.SetStatusText(label, 0)
-
- def OnUpdateStatusBar(self, event):
- """!Update statusbar text"""
- element = self.search.GetSelection()
- value = event.GetEventObject().GetValue()
- self.tree.SearchItems(element = element, value = value)
-
- nItems = len(self.tree.itemsMarked)
- if value:
- self.parent.SetStatusText(_("%d modules match") % nItems, 0)
- else:
- self.parent.SetStatusText("", 0)
-
- event.Skip()
-
-class MenuTree(ItemTree):
- """!Menu tree class"""
- def __init__(self, parent, data, **kwargs):
- self.parent = parent
- self.menudata = data
-
- super(MenuTree, self).__init__(parent, **kwargs)
-
- self.menustyle = UserSettings.Get(group = 'appearance', key = 'menustyle', subkey = 'selection')
-
- def Load(self, data = None):
- """!Load menu data tree
-
- @param data menu data (None to use self.menudata)
- """
- if not data:
- data = self.menudata
-
- self.itemsMarked = [] # list of marked items
- for eachMenuData in data.GetMenu():
- for label, items in eachMenuData:
- item = self.AppendItem(parentId = self.root,
- text = label.replace('&', ''))
- self.__AppendItems(item, items)
-
- def __AppendItems(self, item, data):
- """!Append items into tree (used by Load()
-
- @param item tree item (parent)
- @parent data menu data"""
- for eachItem in data:
- if len(eachItem) == 2:
- if eachItem[0]:
- itemSub = self.AppendItem(parentId = item,
- text = eachItem[0])
- self.__AppendItems(itemSub, eachItem[1])
- else:
- if eachItem[0]:
- label = eachItem[0]
- if eachItem[3]:
- if self.menustyle == 1:
- label += ' [' + eachItem[3] + ']'
- elif self.menustyle == 2:
- label = '[' + eachItem[3] + ']'
-
- itemNew = self.AppendItem(parentId = item,
- text = label)
-
- data = { 'item' : eachItem[0],
- 'description' : eachItem[1],
- 'handler' : eachItem[2],
- 'command' : eachItem[3],
- 'keywords' : eachItem[4] }
-
- self.SetPyData(itemNew, data)
+ self.showNotification.emit(message=label)
Modified: grass/trunk/gui/wxpython/gui_core/prompt.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/prompt.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gui_core/prompt.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -42,14 +42,14 @@
See subclass GPromptPopUp and GPromptSTC.
"""
- def __init__(self, parent, modulesData, updateCmdHistory):
+ def __init__(self, parent, menuModel, updateCmdHistory):
self.parent = parent # GConsole
self.panel = self.parent.GetPanel()
self.promptRunCmd = Signal('GPrompt.promptRunCmd')
# probably only subclasses need this
- self.modulesData = modulesData
+ self._menuModel = menuModel
self.mapList = self._getListOfMaps()
self.mapsetList = utils.ListOfMapsets()
@@ -121,29 +121,6 @@
self.OnCmdErase(None)
self.ShowStatusText('')
- def GetPanel(self):
- """!Get main widget panel"""
- return self.panel
-
- def GetInput(self):
- """!Get main prompt widget"""
- return self.input
-
- def SetFilter(self, data, module = True):
- """!Set filter
-
- @param data data dict
- @param module True to filter modules, otherwise data
- """
- if module:
- # TODO: remove this and module param
- raise NotImplementedError("Replace by call to common ModulesData object (SetFilter with module=True)")
- else:
- if data:
- self.dataList = data
- else:
- self.dataList = self._getListOfMaps()
-
def GetCommands(self):
"""!Get list of launched commands"""
return self.commands
@@ -155,9 +132,9 @@
class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
"""!Styled wxGUI prompt with autocomplete and calltips"""
- def __init__(self, parent, modulesData, updateCmdHistory = True, margin = False):
+ def __init__(self, parent, menuModel, updateCmdHistory = True, margin = False):
GPrompt.__init__(self, parent = parent,
- modulesData = modulesData, updateCmdHistory = updateCmdHistory)
+ menuModel = menuModel, updateCmdHistory = updateCmdHistory)
wx.stc.StyledTextCtrl.__init__(self, self.panel, id = wx.ID_ANY)
#
@@ -218,7 +195,10 @@
if self.toComplete['entity'] == 'command':
item = self.toComplete['cmd'].rpartition('.')[0] + '.' + self.autoCompList[event.GetIndex()]
try:
- desc = self.modulesData.GetCommandDesc(item)
+ nodes = self._menuModel.SearchNodes(key='command', value=item)
+ desc = ''
+ if nodes:
+ desc = nodes[0].data['description']
except KeyError:
desc = ''
self.ShowStatusText(desc)
@@ -406,9 +386,14 @@
self.InsertText(pos, '.')
self.CharRight()
self.toComplete = self.EntityToComplete()
+ if self.toComplete is None:
+ return
try:
if self.toComplete['entity'] == 'command':
- self.autoCompList = self.modulesData.GetDictOfModules()[entry.strip()]
+ for command in globalvar.grassCmd:
+ if command.find(self.toComplete['cmd']) == 0:
+ dotNumber = list(self.toComplete['cmd']).count('.')
+ self.autoCompList.append(command.split('.',dotNumber)[-1])
except (KeyError, TypeError):
return
self.ShowList()
@@ -559,7 +544,7 @@
try:
txt = self.cmdbuffer[self.cmdindex]
- except:
+ except KeyError:
txt = ''
# clear current line and insert command history
Modified: grass/trunk/gui/wxpython/gui_core/query.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/query.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gui_core/query.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -13,10 +13,17 @@
@author Anna Kratochvilova <kratochanna gmail.com>
"""
-
+import os
+import sys
+import random
import wx
-import wx.gizmos as gizmos
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+
+from gui_core.treeview import TreeListView
+from core.treemodel import TreeModel, DictNode
+
class QueryDialog(wx.Dialog):
def __init__(self, parent, data = None):
wx.Dialog.__init__(self, parent, id = wx.ID_ANY,
@@ -27,20 +34,17 @@
self.panel = wx.Panel(self, id = wx.ID_ANY)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self._colNames = [_("Feature"), _("Value")]
+ self._model = QueryTreeBuilder(self.data, column=self._colNames[1])
+ self.tree = TreeListView(model=self._model, parent=self.panel,
+ columns=self._colNames,
+ style=wx.TR_DEFAULT_STYLE |
+ wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
- self.tree = gizmos.TreeListCtrl(self.panel, id = wx.ID_ANY,
- style = wx.TR_DEFAULT_STYLE |
- wx.TR_HIDE_ROOT)
-
- self.tree.AddColumn("Feature")
- self.tree.AddColumn("Value")
- self.tree.SetMainColumn(0)
self.tree.SetColumnWidth(0, 220)
self.tree.SetColumnWidth(1, 400)
-
+ self.tree.ExpandAll(self._model.root)
self.mainSizer.Add(item = self.tree, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
- if self.data:
- self._load()
close = wx.Button(self.panel, id = wx.ID_CLOSE)
close.Bind(wx.EVT_BUTTON, lambda event: self.Close())
@@ -59,46 +63,15 @@
# for Windows
self.SendSizeEvent()
- def _load(self):
- self.tree.DeleteAllItems()
- self.root = self.tree.AddRoot("The Root Item")
- for part in self.data:
- self._addItem(self.root, part)
-
- self.tree.UnselectAll()
- self.tree.ExpandAll(self.root)
-
- def _print(self):
- string = []
- for part in self.data:
- self._printItem(string, '', part)
- string.append('')
- return '\n'.join(string)
-
- def _addItem(self, parent, data):
- for k, v in data.iteritems():
- if isinstance(v, dict):
- item = self.tree.AppendItem(parent, text = k)
- self.tree.SetItemText(item, '', 1)
- self._addItem(item, v)
- else:
- item = self.tree.AppendItem(parent, text = k)
- self.tree.SetItemText(item, str(v), 1)
-
- def _printItem(self, string, indent, data):
- for k, v in data.iteritems():
- if isinstance(v, dict):
- string.append(indent + k)
- self._printItem(string, indent + ' ', v)
- else:
- string.append(indent + k + ': ' + str(v))
-
def SetData(self, data):
+ state = self.tree.GetExpansionState()
self.data = data
- self._load()
+ self._model = QueryTreeBuilder(self.data, column=self._colNames[1])
+ self.tree.SetModel(self._model)
+ self.tree.SetExpansionState(state)
def Copy(self, event):
- text = self._print()
+ text = printResults(self._model, self._colNames[1])
if wx.TheClipboard.Open():
do = wx.TextDataObject()
do.SetText(text)
@@ -110,6 +83,47 @@
event.Skip()
+def QueryTreeBuilder(data, column):
+ """!Builds tree model from query results.
+
+ @param data query results as a dictionary
+ @param column column name
+
+ @returns tree model
+ """
+ def addNode(parent, data, model):
+ for k, v in data.iteritems():
+ if isinstance(v, dict):
+ node = model.AppendNode(parent=parent, label=k)
+ addNode(parent=node, data=v, model=model)
+ else:
+ node = model.AppendNode(parent=parent, label=k,
+ data={column: str(v)})
+
+ model = TreeModel(DictNode)
+ for part in data:
+ addNode(parent=model.root, data=part, model=model)
+
+ return model
+
+
+def printResults(model, valueCol):
+ """!Print all results to string.
+
+ @param model results tree model
+ @param valueCol column name with value to be printed
+ """
+ def printTree(node, textList, valueCol, indent=0):
+ textList.append(indent*' ' + node.label + ': ' + node.data.get(valueCol, ''))
+ for child in node.children:
+ printTree(node=child, textList=textList, valueCol=valueCol, indent=indent + 2)
+
+ textList=[]
+ for child in model.root.children:
+ printTree(node=child, textList=textList, valueCol=valueCol)
+ return '\n'.join(textList)
+
+
def PrepareQueryResults(coordinates, result):
"""!Prepare query results as a Query dialog input.
@@ -133,9 +147,9 @@
data.append(part)
return data
+
def test():
app = wx.PySimpleApp()
- import pprint
from grass.script import vector as gvect
from grass.script import raster as grast
testdata1 = grast.raster_what(map = ('elevation_shade at PERMANENT','landclass96'),
Added: grass/trunk/gui/wxpython/gui_core/treeview.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/treeview.py (rev 0)
+++ grass/trunk/gui/wxpython/gui_core/treeview.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -0,0 +1,203 @@
+"""!
+ at package gui_core.treeview
+
+ at brief tree view for dislaying tree model (used for search tree)
+
+Classes:
+ - treeview::TreeView
+
+(C) 2013 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 Anna Petrasova <kratochanna gmail.com>
+"""
+
+import os
+import sys
+import wx
+from wx.lib.mixins.treemixin import VirtualTree, ExpansionState
+try:
+ import wx.lib.agw.customtreectrl as CT
+except ImportError:
+ import wx.lib.customtreectrl as CT
+import wx.gizmos as gizmos
+
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+
+from core.treemodel import TreeModel, DictNode
+
+from grass.pydispatch.signal import Signal
+
+
+class AbstractTreeViewMixin(VirtualTree):
+ """!Abstract tree view class for displaying tree model.
+
+ Concrete implementation must inherit both this mixin class and a wx tree widget.
+ More functionality and signals can be added if needed.
+
+ Signals:
+ selectionChanged - attribute 'node'
+ itemActivated - attribute 'node'
+ """
+ def __init__(self, model, parent, *args, **kw):
+ self._model = model
+ super(AbstractTreeViewMixin, self).__init__(parent=parent, *args, **kw)
+ self.RefreshItems()
+
+ self.selectionChanged = Signal('TreeView.selectionChanged')
+ self.itemActivated = Signal('TreeView.itemActivated')
+
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, lambda evt:
+ self._emitSignal(evt.GetItem(), self.selectionChanged))
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, lambda evt:
+ self._emitSignal(evt.GetItem(), self.itemActivated))
+
+ def SetModel(self, model):
+ """!Set tree model and refresh.
+
+ @param model tree model
+ """
+ self._model = model
+ self.RefreshItems()
+
+ def OnGetItemText(self, index, column=0):
+ """!Overridden method necessary to communicate with tree model.
+
+ @param index index as explained in VirtualTree doc
+ @param column column index if applicable
+ """
+ node = self._model.GetNodeByIndex(index)
+ # remove & because of & needed in menu (&Files)
+ label = node.label.replace('&', '')
+ return label
+
+ def OnGetChildrenCount(self, index):
+ """!Overridden method necessary to communicate with tree model."""
+ return len(self._model.GetChildrenByIndex(index))
+
+ def GetSelected(self):
+ """!Get currently selected items.
+
+ @return list of nodes representing selected items (can be empty)
+ """
+ selected = []
+ for sel in self.GetSelections():
+ index = self.GetIndexOfItem(sel)
+ selected.append(self._model.GetNodeByIndex(index))
+ return selected
+
+ def Select(self, node, select=True):
+ """!Select items.
+
+ @param node node representing item
+ @param select True/False to select/deselect
+ """
+ index = self._model.GetIndexOfNode(node)
+ for i in range(len(index))[1:]:
+ item = self.GetItemByIndex(index[:i])
+ self.Expand(item)
+
+ item = self.GetItemByIndex(index)
+ self.SelectItem(item, select)
+
+ def _emitSignal(self, item, signal):
+ """!Helper method for emitting signals.
+
+ @param item tree item
+ @param signal signal to be emitted
+ """
+ if not item or not item.IsOk():
+ return
+ index = self.GetIndexOfItem(item)
+ node = self._model.GetNodeByIndex(index)
+ signal.emit(node = node)
+
+
+class TreeView(AbstractTreeViewMixin, wx.TreeCtrl):
+ """!Tree view class inheriting from wx.TreeCtrl"""
+ def __init__(self, model, parent, *args, **kw):
+ super(TreeView, self).__init__(parent=parent, model=model, *args, **kw)
+
+class CTreeView(AbstractTreeViewMixin, CT.CustomTreeCtrl):
+ """!Tree view class inheriting from wx.TreeCtrl"""
+ def __init__(self, model, parent, **kw):
+ if 'agwStyle' not in kw:
+ kw['agwStyle'] = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT |\
+ CT.TR_HAS_BUTTONS | CT.TR_LINES_AT_ROOT | CT.TR_SINGLE
+ super(CTreeView, self).__init__(parent=parent, model=model, **kw)
+
+class TreeListView(AbstractTreeViewMixin, ExpansionState, gizmos.TreeListCtrl):
+ def __init__(self, model, parent, columns, **kw):
+ self._columns = columns
+ super(TreeListView, self).__init__(parent=parent, model=model, **kw)
+ for column in columns:
+ self.AddColumn(column)
+ self.SetMainColumn(0)
+ # refresh again
+ self.RefreshItems()
+
+ def OnGetItemText(self, index, column=0):
+ """!Overridden method necessary to communicate with tree model.
+
+ @param index index as explained in VirtualTree doc
+ @param column column index if applicable
+ """
+ node = self._model.GetNodeByIndex(index)
+ # remove & because of & needed in menu (&Files)
+ if column > 0:
+ return node.data.get(self._columns[column], '')
+ else:
+ label = node.label.replace('&', '')
+ return label
+
+
+class TreeFrame(wx.Frame):
+ """!Frame for testing purposes only."""
+ def __init__(self, model=None):
+ wx.Frame.__init__(self, None, title='Test tree')
+
+ panel = wx.Panel(self)
+# self.tree = TreeListView(model=model, parent=panel, columns=['col1', 'xxx'])
+# self.tree = TreeView(model=model, parent=panel)
+ self.tree = CTreeView(model=model, parent=panel)
+ self.tree.selectionChanged.connect(self.OnSelChanged)
+ self.tree.itemActivated.connect(self.OnItemActivated)
+ self.tree.SetMinSize((150, 300))
+
+ szr = wx.BoxSizer(wx.VERTICAL)
+ szr.Add(self.tree, 1, wx.ALIGN_CENTER)
+ panel.SetSizerAndFit(szr)
+ szr.SetSizeHints(self)
+
+ def OnSelChanged(self):
+ print 'selected items: ' + \
+ str([node.label for node in self.tree.GetSelected()])
+
+ def OnItemActivated(self, node):
+ print 'activated: ' + node.label
+
+
+def main():
+ tree = TreeModel(DictNode)
+ root = tree.root
+ n1 = tree.AppendNode(parent=root, label='node1')
+ n2 = tree.AppendNode(parent=root, label='node2')
+ n3 = tree.AppendNode(parent=root, label='node3') # pylint: disable=W0612
+ n11 = tree.AppendNode(parent=n1, label='node11', data={'xxx': 'A'})
+ n12 = tree.AppendNode(parent=n1, label='node12', data={'xxx': 'B'}) # pylint: disable=W0612
+ n21 = tree.AppendNode(parent=n2, label='node21', data={'xxx': 'A'}) # pylint: disable=W0612
+ n111 = tree.AppendNode(parent=n11, label='node111', data={'xxx': 'A'}) # pylint: disable=W0612
+
+
+ app = wx.PySimpleApp()
+ frame = TreeFrame(model=tree)
+# frame.tree.Select(n111)
+ frame.Show()
+ app.MainLoop()
+
+
+if __name__ == '__main__':
+ main()
Modified: grass/trunk/gui/wxpython/gui_core/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/widgets.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/gui_core/widgets.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -13,7 +13,6 @@
- widgets::BaseValidator
- widgets::IntegerValidator
- widgets::FloatValidator
- - widgets::ItemTree
- widgets::GListCtrl
- widgets::SearchModuleWidget
- widgets::ManageSettingsWidget
@@ -55,9 +54,7 @@
from core.gcmd import GMessage, GError
from core.debug import Debug
-from wx.lib.newevent import NewEvent
-
class NotebookController:
"""!Provides handling of notebook page names.
@@ -642,85 +639,6 @@
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
-
class SingleSymbolPanel(wx.Panel):
"""!Panel for displaying one symbol.
@@ -846,68 +764,75 @@
class SearchModuleWidget(wx.Panel):
- """!Search module widget (used in SearchModuleWindow)
+ """!Search module widget (used e.g. in SearchModuleWindow)
- Signal moduleSelected - attribute 'name' is module name
+ Signals:
+ moduleSelected - attribute 'name' is module name
+ showSearchResult - attribute 'result' is a node (representing module)
+ showNotification - attribute 'message'
"""
- def __init__(self, parent, modulesData, id = wx.ID_ANY,
+ def __init__(self, parent, model,
showChoice = True, showTip = False, **kwargs):
- self.showTip = showTip
- self.showChoice = showChoice
- self.modulesData = modulesData
+ self._showTip = showTip
+ self._showChoice = showChoice
+ self._model = model
+ self._results = [] # list of found nodes
+ self._resultIndex = -1
self.moduleSelected = Signal('SearchModuleWidget.moduleSelected')
+ self.showSearchResult = Signal('SearchModuleWidget.showSearchResult')
+ self.showNotification = Signal('SearchModuleWidget.showNotification')
- wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
+ wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY, **kwargs)
self._searchDict = { _('description') : 'description',
_('command') : 'command',
_('keywords') : 'keywords' }
- # signal which requests showing of a notification
- self.showNotification = Signal('SearchModuleWidget.showNotification')
- self.box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+ self._box = wx.StaticBox(parent = self, id = wx.ID_ANY,
label = " %s " % _("Find module - (press Enter for next match)"))
- self.searchBy = wx.Choice(parent = self, id = wx.ID_ANY)
+ self._searchBy = wx.Choice(parent = self, id = wx.ID_ANY)
items = [_('description'), _('keywords'), _('command')]
datas = ['description', 'keywords', 'command']
for item, data in zip(items, datas):
- self.searchBy.Append(item = item, clientData = data)
- self.searchBy.SetSelection(0)
+ self._searchBy.Append(item = item, clientData = data)
+ self._searchBy.SetSelection(0)
+ self._searchBy.Bind(wx.EVT_CHOICE, self.OnSearchModule)
- self.search = wx.SearchCtrl(parent = self, id = wx.ID_ANY,
+ self._search = wx.SearchCtrl(parent = self, id = wx.ID_ANY,
size = (-1, 25), style = wx.TE_PROCESS_ENTER)
- self.search.Bind(wx.EVT_TEXT, self.OnSearchModule)
+ self._search.Bind(wx.EVT_TEXT, self.OnSearchModule)
+ self._search.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
- if self.showTip:
- self.searchTip = StaticWrapText(parent = self, id = wx.ID_ANY,
- size = (-1, 35))
+ if self._showTip:
+ self._searchTip = StaticWrapText(parent = self, id = wx.ID_ANY,
+ size = (-1, 35))
- if self.showChoice:
- self.searchChoice = wx.Choice(parent = self, id = wx.ID_ANY)
- self.searchChoice.SetItems(self.modulesData.GetCommandItems())
- self.searchChoice.Bind(wx.EVT_CHOICE, self.OnSelectModule)
+ if self._showChoice:
+ self._searchChoice = wx.Choice(parent = self, id = wx.ID_ANY)
+ self._searchChoice.SetItems(self._searchModule(key='command', value=''))
+ self._searchChoice.Bind(wx.EVT_CHOICE, self.OnSelectModule)
self._layout()
def _layout(self):
"""!Do layout"""
- sizer = wx.StaticBoxSizer(self.box, wx.HORIZONTAL)
+ sizer = wx.StaticBoxSizer(self._box, wx.HORIZONTAL)
gridSizer = wx.GridBagSizer(hgap = 3, vgap = 3)
- gridSizer.Add(item = self.searchBy,
+ gridSizer.Add(item = self._searchBy,
flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
- gridSizer.Add(item = self.search,
+ gridSizer.Add(item = self._search,
flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (0, 1))
row = 1
- if self.showChoice:
- gridSizer.Add(item = self.searchChoice,
+ if self._showChoice:
+ gridSizer.Add(item = self._searchChoice,
flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (row, 0), span = (1, 2))
row += 1
- if self.showTip:
- gridSizer.Add(item = self.searchTip,
+ if self._showTip:
+ gridSizer.Add(item = self._searchTip,
flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (row, 0), span = (1, 2))
row += 1
@@ -918,62 +843,65 @@
self.SetSizer(sizer)
sizer.Fit(self)
- def GetCtrl(self):
- """!Get SearchCtrl widget"""
- return self.search
+ def OnKeyUp(self, event):
+ """!Key or key combination pressed"""
+ if event.GetKeyCode() == wx.WXK_RETURN and not event.ControlDown():
+ if self._results:
+ self._resultIndex += 1
+ if self._resultIndex == len(self._results):
+ self._resultIndex = 0
+ self.showSearchResult.emit(result=self._results[self._resultIndex])
+ event.Skip()
def GetSelection(self):
"""!Get selected element"""
- selection = self.searchBy.GetStringSelection()
+ selection = self._searchBy.GetStringSelection()
return self._searchDict[selection]
def SetSelection(self, i):
"""!Set selection element"""
- self.searchBy.SetSelection(i)
+ self._searchBy.SetSelection(i)
def OnSearchModule(self, event):
"""!Search module by keywords or description"""
+ commands = self._searchModule(key=self.GetSelection(), value=self._search.GetValue())
+ if self._showChoice:
+ self._searchChoice.SetItems(commands)
+ if commands:
+ self._searchChoice.SetSelection(0)
- text = event.GetEventObject().GetValue()
- if not text:
- self.modulesData.SetFilter()
- mList = self.modulesData.GetCommandItems()
- if self.showChoice:
- self.searchChoice.SetItems(mList)
- label = _("%d modules found") % len(mList)
- else:
- findIn = self.searchBy.GetClientData(self.searchBy.GetSelection())
- modules, nFound = self.modulesData.FindModules(text = text, findIn = findIn)
- self.modulesData.SetFilter(modules)
- if self.showChoice:
- self.searchChoice.SetItems(self.modulesData.GetCommandItems())
- self.searchChoice.SetSelection(0)
- label = _("%d modules match") % nFound
+ label = _("%d modules match") % len(commands)
+ if self._showTip:
+ self._searchTip.SetLabel(label)
- if self.showTip:
- self.searchTip.SetLabel(label)
-
self.showNotification.emit(message=label)
event.Skip()
+ def _searchModule(self, key, value):
+ nodes = self._model.SearchNodes(key=key, value=value)
+ self._results = nodes
+ self._resultIndex = -1
+ return [node.data['command'] for node in nodes if node.data['command']]
+
def OnSelectModule(self, event):
"""!Module selected from choice, update command prompt"""
- cmd = event.GetString().split(' ', 1)[0]
-
+ cmd = self._searchChoice.GetStringSelection()
self.moduleSelected.emit(name = cmd)
- desc = self.modulesData.GetCommandDesc(cmd)
- if self.showTip:
- self.searchTip.SetLabel(desc)
+ if self._showTip:
+ for module in self._results:
+ if cmd == module.data['command']:
+ self._searchTip.SetLabel(module.data['description'])
+ break
def Reset(self):
"""!Reset widget"""
- self.searchBy.SetSelection(0)
- self.search.SetValue('')
- if self.showTip:
- self.searchTip.SetLabel('')
+ self._searchBy.SetSelection(0)
+ self._search.SetValue('')
+ if self._showTip:
+ self._searchTip.SetLabel('')
class ManageSettingsWidget(wx.Panel):
"""!Widget which allows loading and saving settings into file."""
Modified: grass/trunk/gui/wxpython/lmgr/frame.py
===================================================================
--- grass/trunk/gui/wxpython/lmgr/frame.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/lmgr/frame.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -103,6 +103,7 @@
self._giface = LayerManagerGrassInterface(self)
+ self._menuTreeBuilder = LayerManagerMenuData()
self._auimgr = wx.aui.AuiManager(self)
@@ -232,7 +233,7 @@
def _createMenuBar(self):
"""!Creates menu bar"""
- self.menubar = Menu(parent = self, data = LayerManagerMenuData())
+ self.menubar = Menu(parent=self, model=self._menuTreeBuilder.GetModel(separators=True))
self.SetMenuBar(self.menubar)
self.menucmd = self.menubar.GetCmd()
@@ -276,6 +277,7 @@
self._gconsole = GConsole(guiparent = self, giface = self._giface,
ignoredCmdPattern = '^d\..*|^r[3]?\.mapcalc$|^i.group')
self.goutput = GConsoleWindow(parent = self, gconsole = self._gconsole,
+ menuModel=self._menuTreeBuilder.GetModel(),
gcstyle = GC_SEARCH | GC_PROMPT)
self.notebook.AddPage(page = self.goutput, text = _("Command console"), name = 'output')
@@ -313,7 +315,8 @@
# create 'search module' notebook page
if not UserSettings.Get(group = 'manager', key = 'hideTabs', subkey = 'search'):
- self.search = SearchModuleWindow(parent = self)
+ self.search = SearchModuleWindow(parent = self, model=self._menuTreeBuilder.GetModel())
+ self.search.showNotification.connect(lambda message: self.SetStatusText(message))
self.notebook.AddPage(page = self.search, text = _("Search module"), name = 'search')
else:
self.search = None
@@ -691,12 +694,11 @@
Return command as a list"""
layer = None
-
if event:
cmd = self.menucmd[event.GetId()]
else:
cmd = ''
-
+
try:
cmdlist = cmd.split(' ')
except: # already list?
@@ -725,13 +727,13 @@
def RunMenuCmd(self, event = None, cmd = []):
"""!Run command selected from menu"""
- if event:
+ if event:
cmd = self.GetMenuCmd(event)
self._gconsole.RunCmd(cmd)
def OnMenuCmd(self, event = None, cmd = []):
"""!Parse command selected from menu"""
- if event:
+ if event:
cmd = self.GetMenuCmd(event)
GUI(parent = self).ParseCommand(cmd)
Modified: grass/trunk/gui/wxpython/lmgr/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/lmgr/menudata.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/lmgr/menudata.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -16,41 +16,13 @@
"""
import os
-import sys
from core.globalvar import ETCWXDIR
-from core.menudata import MenuData
+from core.menutree import MenuTreeModelBuilder
-class LayerManagerMenuData(MenuData):
+class LayerManagerMenuData(MenuTreeModelBuilder):
def __init__(self, filename = None):
if not filename:
- global etcwxdir
filename = os.path.join(ETCWXDIR, 'xml', 'menudata.xml')
- MenuData.__init__(self, filename)
-
- def GetModules(self):
- """!Create dictionary of modules used to search module by
- keywords, description, etc."""
- modules = dict()
-
- for node in self.tree.getiterator():
- if node.tag == 'menuitem':
- module = description = ''
- keywords = []
- for child in node.getchildren():
- if child.tag == 'help':
- description = child.text
- if child.tag == 'command':
- module = child.text
- if child.tag == 'keywords':
- if child.text:
- keywords = child.text.split(',')
-
- if module:
- modules[module] = { 'description': description,
- 'keywords' : keywords }
- if len(keywords) < 1:
- print >> sys.stderr, "WARNING: Module <%s> has no keywords" % module
-
- return modules
+ MenuTreeModelBuilder.__init__(self, filename)
Modified: grass/trunk/gui/wxpython/modules/extensions.py
===================================================================
--- grass/trunk/gui/wxpython/modules/extensions.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/modules/extensions.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -5,7 +5,7 @@
Classes:
- extensions::InstallExtensionWindow
- - extensions::ExtensionTree
+ - extensions::ExtensionTreeModelBuilder
- extensions::UninstallExtensionWindow
- extensions::CheckListExtension
@@ -15,115 +15,24 @@
(>=v2). Read the file COPYING that comes with GRASS for details.
@author Martin Landa <landa.martin gmail.com>
+ at author Anna Petrasova <kratochanna gmail.com>
"""
import os
import sys
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 core.utils import SetAddOnPath
-from gui_core.forms import GUI
-from gui_core.widgets import ItemTree, GListCtrl, SearchModuleWidget
+from core.menutree import TreeModel, ModuleNode
+from gui_core.widgets import GListCtrl, SearchModuleWidget
+from gui_core.treeview import CTreeView
-class ExtensionModulesData(object):
- """!Holds information about modules.
-
- @todo add some test
- @todo this class has some common methods with core::modulesdata::ModulesData
- """
- def __init__(self, modulesDesc):
-
- self.moduleDesc = modulesDesc
- self.moduleDescOriginal = modulesDesc
-
- def GetCommandDesc(self, cmd):
- """!Gets the description for a given module (command).
-
- If the given module is not available, an empty string is returned.
-
- \code
- print data.GetCommandDesc('r.info')
- Outputs basic information about a raster map.
- \endcode
- """
- if cmd in self.moduleDesc:
- return self.moduleDesc[cmd]['description']
-
- return ''
-
- def GetCommandItems(self):
- """!Gets list of available modules (commands).
-
- The list contains available module names.
-
- \code
- print data.GetCommandItems()[0:4]
- ['d.barscale', 'd.colorlist', 'd.colortable', 'd.correlate']
- \endcode
- """
- items = self.moduleDesc.keys()
- items.sort()
-
- return items
-
- def FindModules(self, text, findIn):
- """!Finds modules according to given text.
-
- @param text string to search
- @param findIn where to search for text
- (allowed values are 'description', 'keywords' and 'command')
- """
- modules = dict()
- iFound = 0
- for module, data in self.moduleDescOriginal.iteritems():
- found = False
- if findIn == 'description':
- if text in data['description']:
- found = True
- elif findIn == 'keywords':
- if text in data['keywords']:
- found = True
- elif findIn == 'command':
- if module[:len(text)] == text:
- found = True
- else:
- raise ValueError("Parameter findIn is not valid")
-
- if found:
- iFound += 1
- modules[module] = data
- return modules, iFound
-
- def SetFilter(self, data = None):
- """!Sets filter modules
-
- If @p data is not specified, module dictionary is derived
- from an internal data structures.
-
- @todo Document this method.
-
- @param data data dict
- """
- if data:
- self.moduleDesc = data
- else:
- self.moduleDesc = self.moduleDescOriginal
-
- def SetData(self, data):
- self.moduleDesc = self.moduleDescOriginal = data
-
class InstallExtensionWindow(wx.Frame):
def __init__(self, parent, id = wx.ID_ANY,
title = _("Fetch & install extension from GRASS Addons"), **kwargs):
@@ -142,13 +51,15 @@
self.repo = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY)
- self.tree = ExtensionTree(parent = self.panel, log = parent.GetLogWindow())
+ # modelBuilder loads data into tree model
+ self.modelBuilder = ExtensionTreeModelBuilder()
+ # tree view displays model data
+ self.tree = CTreeView(parent=self.panel, model=self.modelBuilder.GetModel())
- self.modulesData = ExtensionModulesData(modulesDesc = self.tree.GetModules())
- self.search = SearchModuleWidget(parent = self.panel, modulesData = self.modulesData,
+ self.search = SearchModuleWidget(parent=self.panel, model=self.modelBuilder.GetModel(),
showChoice = False)
self.search.SetSelection(0)
- self.search.moduleSelected.connect(lambda name: self.OnShowItem(None))
+ self.search.showSearchResult.connect(lambda result: self.tree.Select(result))
# show text in statusbar when notification appears
self.search.showNotification.connect(lambda message: self.SetStatusText(message))
@@ -174,26 +85,26 @@
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'))
+ defaultUrl = 'http://svn.osgeo.org/grass/grass-addons/grass7'
+ self.repo.SetValue(task.get_param(value = 'svnurl').get('default', defaultUrl))
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.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.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
+ self.btnClose.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
self.btnFetch.Bind(wx.EVT_BUTTON, self.OnFetch)
self.btnInstall.Bind(wx.EVT_BUTTON, self.OnInstall)
- 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.tree.selectionChanged.connect(self.OnItemSelected)
+ self.tree.itemActivated.connect(self.OnItemActivated)
wx.CallAfter(self._fetch)
@@ -246,13 +157,11 @@
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:
+ if not item or 'command' not in item[0].data:
GError(_("Extension not defined"), parent = self)
return
+
+ name = item[0].data['command']
flags = list()
for key in self.options.keys():
@@ -264,32 +173,7 @@
return ['g.extension'] + flags + ['extension=' + name,
'svnurl=' + self.repo.GetValue().strip()]
-
- def OnUpdateStatusBar(self, event):
- """!Update statusbar text
- @todo This method is a dead code. Is it useful?
- """
- 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.GetEventObject().GetValue())
-
- 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"""
self._fetch()
@@ -298,22 +182,22 @@
"""!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())
- modulesDesc = self.tree.GetModules()
- self.modulesData.SetData(modulesDesc)
+ self.modelBuilder.Load(url = self.repo.GetValue().strip())
+ self.tree.RefreshItems()
self.SetStatusText("", 0)
wx.EndBusyCursor()
- def OnItemActivated(self, event):
- item = event.GetItem()
- data = self.tree.GetPyData(item)
+ def OnItemActivated(self, node):
+ data = node.data
if data and 'command' in data:
- self.OnInstall(event = None)
+ self.OnInstall(event=None)
def OnInstall(self, event):
"""!Install selected extension"""
log = self.parent.GetLogWindow()
- log.RunCmd(self._getCmd(), onDone = self.OnDone)
+ cmd = self._getCmd()
+ if cmd:
+ log.RunCmd(cmd, onDone = self.OnDone)
def OnDone(self, cmd, returncode):
if returncode == 0:
@@ -322,11 +206,9 @@
globalvar.UpdateGRASSAddOnCommands()
- def OnItemSelected(self, event):
+ def OnItemSelected(self, node):
"""!Item selected"""
- item = event.GetItem()
- self.tree.itemSelected = item
- data = self.tree.GetPyData(item)
+ data = node.data
if data is None:
self.SetStatusText('', 0)
self.btnInstall.Enable(False)
@@ -334,36 +216,28 @@
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)
-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):
+class ExtensionTreeModelBuilder:
+ """!Tree model of available extensions."""
+ def __init__(self):
+ self.mainNodes = dict()
+ self.model = TreeModel(ModuleNode)
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
+ node = self.model.AppendNode(parent=self.model.root, label=prefix)
+ self.mainNodes[prefix] = node
+ def GetModel(self):
+ return self.model
+
+ def _emptyTree(self):
+ """!Remove modules from tree keeping the main structure"""
+ for node in self.mainNodes.values():
+ for child in reversed(node.children):
+ self.model.RemoveNode(child)
+
def _expandPrefix(self, c):
name = { 'd' : 'display',
'db' : 'database',
@@ -384,22 +258,9 @@
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 = True):
"""!Load list of extensions"""
- self.DeleteAllItems()
- self.root = self.AddRoot(_("Menu tree"))
- self._initTree()
+ self._emptyTree()
if full:
flags = 'g'
@@ -411,7 +272,7 @@
if not ret:
return
- mdict = dict()
+ currentNode = None
for line in ret.splitlines():
if full:
try:
@@ -419,74 +280,36 @@
except ValueError:
key = 'name'
value = line
-
+
if key == 'name':
try:
prefix, name = value.split('.', 1)
except ValueError:
prefix = ''
name = value
- if prefix not in mdict:
- mdict[prefix] = dict()
- mdict[prefix][name] = dict()
- mdict[prefix][name]['command'] = value
+ mainNode = self.mainNodes[self._expandPrefix(prefix)]
+ currentNode = self.model.AppendNode(parent=mainNode, label=value)
+ currentNode.data = {'command': value}
else:
- mdict[prefix][name][key] = value
+ if currentNode is not None:
+ currentNode.data[key] = value
else:
try:
prefix, name = line.strip().split('.', 1)
- except:
+ except ValueError:
prefix = ''
name = line.strip()
if self._expandPrefix(prefix) == prefix:
prefix = ''
-
- 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:
- if prefix:
- text = prefix + '.' + name
- else:
- text = name
- new = self.AppendItem(parentId = item,
- text = text)
- data = dict()
- for key in mdict[prefix][name].keys():
- data[key] = mdict[prefix][name][key]
-
- self.SetPyData(new, data)
-
- self._loaded = True
+ module = prefix + '.' + name
+ mainNode = self.mainNodes[self._expandPrefix(prefix)]
+ currentNode = self.model.AppendNode(parent=mainNode, label=module)
+ currentNode.data = {'command': module,
+ 'keywords': '',
+ 'description': ''}
- def IsLoaded(self):
- """Check if items are loaded"""
- return self._loaded
- def GetModules(self):
- modules = {}
- root = self.GetRootItem()
- child, cookie = self.GetFirstChild(root)
- while child and child.IsOk():
- if self.ItemHasChildren(child):
- subChild, subCookie = self.GetFirstChild(child)
- while subChild and subChild.IsOk():
- name = self.GetItemText(subChild)
- data = self.GetPyData(subChild)
- modules[name] = data
- subChild, subCookie = self.GetNextChild(child, subCookie)
- child, cookie = self.GetNextChild(root, cookie)
-
- return modules
-
class UninstallExtensionWindow(wx.Frame):
def __init__(self, parent, id = wx.ID_ANY,
title = _("Uninstall GRASS Addons extensions"), **kwargs):
@@ -509,7 +332,7 @@
self.btnClose = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
self.btnUninstall.Bind(wx.EVT_BUTTON, self.OnUninstall)
- self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
+ self.btnClose.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
self._layout()
@@ -536,13 +359,8 @@
self.Layout()
- def OnCloseWindow(self, event):
- """!Close window"""
- self.Destroy()
-
def OnUninstall(self, event):
"""!Uninstall selected extensions"""
- log = self.parent.GetLogWindow()
eList = self.extList.GetExtensions()
if not eList:
GError(_("No extension selected for removal. "
@@ -568,8 +386,7 @@
# update prompt
globalvar.UpdateGRASSAddOnCommands(eList)
- log = self.parent.GetLogWindow()
- log.GetPrompt().SetFilter(None)
+
class CheckListExtension(GListCtrl):
"""!List of mapset/owner/group"""
Modified: grass/trunk/gui/wxpython/psmap/frame.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/frame.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/psmap/frame.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -59,7 +59,7 @@
wx.Frame.__init__(self, parent = parent, id = id, title = title, name = "PsMap", **kwargs)
self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
#menubar
- self.menubar = Menu(parent = self, data = PsMapMenuData())
+ self.menubar = Menu(parent = self, model = PsMapMenuData().GetModel())
self.SetMenuBar(self.menubar)
#toolbar
Modified: grass/trunk/gui/wxpython/psmap/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/psmap/menudata.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/psmap/menudata.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -16,10 +16,10 @@
import os
-from core import globalvar
-from core.menudata import MenuData
+from core import globalvar
+from core.menutree import MenuTreeModelBuilder
-class PsMapMenuData(MenuData):
+class PsMapMenuData(MenuTreeModelBuilder):
def __init__(self, path = None):
"""!Menu for Cartographic Composer (psmap.py)
@@ -28,4 +28,4 @@
if not path:
path = os.path.join(globalvar.ETCWXDIR, 'xml', 'menudata_psmap.xml')
- MenuData.__init__(self, path)
+ MenuTreeModelBuilder.__init__(self, path)
Modified: grass/trunk/gui/wxpython/scripts/vkrige.py
===================================================================
--- grass/trunk/gui/wxpython/scripts/vkrige.py 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/scripts/vkrige.py 2013-04-02 19:17:47 UTC (rev 55594)
@@ -100,8 +100,7 @@
## Command output. From menuform module, cmdPanel class
self._gconsole = gconsole.GConsole(guiparent = self)
- self.goutput = goutput.GConsoleWindow(parent = self, gconsole = self._gconsole, margin = False,
- gcstyle = goutput.GC_SEARCH | goutput.GC_PROMPT)
+ self.goutput = goutput.GConsoleWindow(parent = self, gconsole = self._gconsole, margin = False)
self.goutputId = self.RPackagesBook.GetPageCount()
self.outpage = self.RPackagesBook.AddPage(page = self.goutput, text = _("Command output"), name = 'output')
self._gconsole.Bind(gconsole.EVT_CMD_RUN,
Modified: grass/trunk/gui/wxpython/wxpythonlib.dox
===================================================================
--- grass/trunk/gui/wxpython/wxpythonlib.dox 2013-04-02 18:18:59 UTC (rev 55593)
+++ grass/trunk/gui/wxpython/wxpythonlib.dox 2013-04-02 19:17:47 UTC (rev 55594)
@@ -71,13 +71,12 @@
- goutput::GStdout
- goutput::GStderr
- goutput::GConsole
-- core::menudata
- - menudata::MenuData
+- core::menutree
+ - menutree::MenuTreeModelBuilder
- core::modulesdata
- modulesdata::ModulesData
- core::render
- render::Layer
- - render::Layer
- render::MapLayer
- render::Overlay
- render::Map
@@ -152,7 +151,6 @@
- gui_core::menu
- menu::Menu
- menu::SearchModuleWindow
- - menu::MenuTree
- gui_core::preferences
- preferences::PreferencesBaseDialog
- preferences::PreferencesDialog
@@ -161,8 +159,12 @@
- gui_core::prompt
- prompt::GPrompt
- prompt::GPromptSTC
+- gui_core::query
+ - query::QueryDialog
- gui_core::toolbars
- toolbars::BaseToolbar
+- gui_core::treeview
+ - treeview::TreeView
- gui_core::widgets
- widgets::ScrolledPanel
- widgets::NTCValidator
@@ -175,7 +177,6 @@
- widgets::IntegerValidator
- widgets::FloatValidator
- widgets::NTCValidator
- - widgets::ItemTree
- widgets::SearchModuleWidget
\subsection lmgr Layer Manager
More information about the grass-commit
mailing list