Jelajahi Sumber

wxGUI/toolboxes: initial version of wxGUI toolboxes (co-author: wenzeslaus)

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@56034 15284696-431f-4ddb-bdfa-cd5b030d7da7
Anna Petrášová 12 tahun lalu
induk
melakukan
92238a5aef

+ 11 - 1
gui/wxpython/Makefile

@@ -1,7 +1,7 @@
 MODULE_TOPDIR = ../..
 
 SUBDIRS = docs animation mapswipe gmodeler rlisetup psmap dbmgr vdigit iclass
-EXTRA_CLEAN_FILES = menustrings.py build_ext.pyc
+EXTRA_CLEAN_FILES = menustrings.py build_ext.pyc xml/menudata.xml
 
 include $(MODULE_TOPDIR)/include/Make/Dir.make
 include $(MODULE_TOPDIR)/include/Make/Doxygen.make
@@ -20,18 +20,28 @@ PYDSTDIRS := $(patsubst %,$(ETCDIR)/%,animation core dbmgr gcp gmodeler gui_core
 DSTDIRS := $(patsubst %,$(ETCDIR)/%,icons scripts xml)
 
 default: $(DSTFILES)
+	-$(MAKE) $(ETCDIR)/xml/module_items.xml
+	-$(MAKE) xml/menudata.xml
 	-$(MAKE) menustrings.py
 	$(MAKE) parsubdirs
 
+
 $(ETCDIR)/%: % | $(PYDSTDIRS) $(DSTDIRS)
 	$(INSTALL_DATA) $< $@
 
+xml/menudata.xml: core/toolboxes.py
+	$(call run_grass,$(PYTHON) $< > $@)
+
 menustrings.py: core/menutree.py $(ETCDIR)/xml/menudata.xml $(ETCDIR)/xml/menudata_modeler.xml $(ETCDIR)/xml/menudata_psmap.xml
 	@echo "# This is a generated file.\n" > $@
 	$(call run_grass,$(PYTHON) $< >> $@)
 	$(call run_grass,$(PYTHON) $< "modeler" >> $@)
 	$(call run_grass,$(PYTHON) $< "psmap" >> $@)
 
+$(ETCDIR)/xml/module_items.xml: tools/build_modules_xml.py
+	@echo "Generating interface description for all modules..."
+	$(call run_grass,$(PYTHON) $< > $@)
+	
 $(PYDSTDIRS): %: | $(ETCDIR)
 	$(MKDIR) $@
 

+ 10 - 4
gui/wxpython/core/menutree.py

@@ -83,8 +83,8 @@ class MenuTreeModelBuilder:
             self.model.AppendNode(parent=node, label='', data=data)
         elif item.tag == 'menuitem':
             origLabel = _(item.find('label').text)
-            desc     = _(item.find('help').text)
             handler  = item.find('handler').text
+            desc     = item.find('help')  # optional
             gcmd     = item.find('command')  # optional
             keywords = item.find('keywords') # optional
             shortcut = item.find('shortcut') # optional
@@ -93,6 +93,10 @@ class MenuTreeModelBuilder:
                 gcmd = gcmd.text
             else:
                 gcmd = ""
+            if desc.text:
+                desc = _(desc.text)
+            else:
+                desc = ""
             if keywords != None:
                 keywords = keywords.text
             else:
@@ -117,7 +121,7 @@ class MenuTreeModelBuilder:
         elif item.tag == 'menu':
             self._createMenu(item, node)
         else:
-            raise Exception(_("Unknow tag %s") % item.tag)
+            raise ValueError(_("Unknow tag %s") % item.tag)
 
     def GetModel(self, separators=False):
         """Returns copy of model with or without separators
@@ -215,10 +219,12 @@ if __name__ == "__main__":
 
     sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "gui", "wxpython"))
 
-
+    # FIXME: cross-dependencies
     if menu == 'manager':
         from lmgr.menudata     import LayerManagerMenuData
-        menudata = LayerManagerMenuData()
+        from core.globalvar    import ETCWXDIR
+        filename = os.path.join(ETCWXDIR, 'xml', 'menudata.xml')
+        menudata = LayerManagerMenuData(filename)
     elif menu == 'modeler':
         from gmodeler.menudata import ModelerMenuData
         menudata = ModelerMenuData()

+ 387 - 0
gui/wxpython/core/toolboxes.py

@@ -0,0 +1,387 @@
+"""!
+@package core.toolboxes
+
+@brief Functions for modifying menu from default/user toolboxes specified in XML files
+
+(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.
+
+@author Vaclav Petras <wenzeslaus gmail.com>
+@author Anna Petrasova <kratochanna gmail.com>
+"""
+
+import os
+import sys
+import copy
+import xml.etree.ElementTree as etree
+from xml.parsers import expat
+
+# Get the XML parsing exceptions to catch. The behavior chnaged with Python 2.7
+# and ElementTree 1.3.
+if hasattr(etree, 'ParseError'):
+    ETREE_EXCEPTIONS = (etree.ParseError, expat.ExpatError)
+else:
+    ETREE_EXCEPTIONS = (expat.ExpatError)
+
+if sys.version_info[0:2] > (2, 6):
+    has_xpath = True
+else:
+    has_xpath = False
+
+
+if __name__ == '__main__':
+    sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+
+from core.globalvar import ETCWXDIR
+from core.utils import GetSettingsPath
+from core.gcmd import GError
+
+import grass.script.task as gtask
+from grass.script.core import ScriptError
+
+
+mainMenuFile = os.path.join(ETCWXDIR, 'xml', 'main_menu.xml')
+toolboxesFile = os.path.join(ETCWXDIR, 'xml', 'toolboxes.xml')
+wxguiItemsFile = os.path.join(ETCWXDIR, 'xml', 'wxgui_items.xml')
+moduleItemsFile = os.path.join(ETCWXDIR, 'xml', 'module_items.xml')
+
+userToolboxesFile = os.path.join(GetSettingsPath(), 'toolboxes', 'toolboxes.xml')
+userMainMenuFile = os.path.join(GetSettingsPath(), 'toolboxes', 'main_menu.xml')
+if not os.path.exists(userToolboxesFile):
+    userToolboxesFile = None
+if not os.path.exists(userMainMenuFile):
+    userMainMenuFile = None
+
+
+def getMenuFile():
+    """!Returns path to XML file for building menu.
+
+    Creates toolbox directory where user defined toolboxes should be located.
+    Checks whether it is needed to create new XML file (user changed toolboxes)
+    or the already generated file could be used.
+    If something goes wrong during building or user doesn't modify menu,
+    default file (from distribution) is returned.
+    """
+    fallback = os.path.join(ETCWXDIR, 'xml', 'menudata.xml')
+    # always create toolboxes directory if does not exist yet
+    tbDir = _setupToolboxes()
+
+    if tbDir:
+        menudataFile = os.path.join(tbDir, 'menudata.xml')
+        generateNew = False
+        # when any of main_menu.xml or toolboxes.xml are changed,
+        # generate new menudata.xml
+
+        if os.path.exists(menudataFile):
+            # remove menu file when there is no main_menu and toolboxes
+            if not userToolboxesFile and not userMainMenuFile:
+                os.remove(menudataFile)
+                return fallback
+
+            if bool(userToolboxesFile) != bool(userMainMenuFile):
+                # always generate new because we don't know if there has been any change
+                generateNew = True
+            else:
+                # if newer files -> generate new
+                menudataTime = os.path.getmtime(menudataFile)
+                if userToolboxesFile:
+                    if os.path.getmtime(userToolboxesFile) > menudataTime:
+                        generateNew = True
+                if userMainMenuFile:
+                    if os.path.getmtime(userMainMenuFile) > menudataTime:
+                        generateNew = True
+        elif userToolboxesFile or userMainMenuFile:
+            generateNew = True
+        else:
+            return fallback
+
+        if generateNew:
+            try:
+                tree = toolboxes2menudata()
+            except ETREE_EXCEPTIONS:
+                GError(_("Unable to parse user toolboxes XML files. "
+                         "Default toolboxes will be loaded."))
+                return fallback
+
+            try:
+                xml = _getXMLString(tree.getroot())
+                fh = open(os.path.join(tbDir, 'menudata.xml'), 'w')
+                fh.write(xml)
+                fh.close()
+                return menudataFile
+            except:
+                return fallback
+        else:
+            return menudataFile
+    else:
+        return fallback
+
+
+def _setupToolboxes():
+    """!Create 'toolboxes' directory if doesn't exist."""
+    path = os.path.join(GetSettingsPath(), 'toolboxes')
+    if not os.path.exists(path):
+        try:
+            os.mkdir(path)
+        except:
+            GError(_('Unable to create toolboxes directory.'))
+            return None
+    return path
+
+
+def toolboxes2menudata(userDefined=True):
+    """!Creates XML file with data for menu.
+
+    Parses toolboxes files from distribution and from users,
+    puts them together, adds metadata to modules and convert
+    tree to previous format used for loading menu.
+
+    @param userDefined use toolboxes defined by user or not (during compilation)
+
+    @return ElementTree instance
+    """
+    wxguiItems = etree.parse(wxguiItemsFile)
+    moduleItems = etree.parse(moduleItemsFile)
+
+    if userDefined and userMainMenuFile:
+        mainMenu = etree.parse(userMainMenuFile)
+    else:
+        mainMenu = etree.parse(mainMenuFile)
+    root = mainMenu.getroot()
+
+    if userDefined and userToolboxesFile:
+        userToolboxes = etree.parse(userToolboxesFile)
+        _expandUserToolboxesItem(root, userToolboxes)
+        _expandToolboxes(root, userToolboxes)
+
+    if not userToolboxesFile:
+        _removeUserToolboxesItem(root)
+
+    toolboxes = etree.parse(toolboxesFile)
+    _expandToolboxes(root, toolboxes)
+
+    _expandItems(root, moduleItems, 'module-item')
+    _expandItems(root, wxguiItems, 'wxgui-item')
+
+    # in case of compilation there are no additional runtime modules
+    # but we need to create empty elements
+    _expandRuntimeModules(root)
+
+    _addHandlers(root)
+    _convertTree(root)
+    _indent(root)
+
+    return mainMenu
+
+
+def _indent(elem, level=0):
+    """!Helper function to fix indentation of XML files."""
+    i = "\n" + level * "  "
+    if len(elem):
+        if not elem.text or not elem.text.strip():
+            elem.text = i + "  "
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+        for elem in elem:
+            _indent(elem, level + 1)
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+    else:
+        if level and (not elem.tail or not elem.tail.strip()):
+            elem.tail = i
+
+
+def _expandToolboxes(node, toolboxes):
+    """!Expands tree with toolboxes.
+
+    Function is called recursively.
+
+    @param node tree node where to look for subtoolboxes to be expanded
+    @param toolboxes tree of toolboxes to be used for expansion
+    """
+    nodes = node.findall('.//toolbox')
+    if node.tag == 'toolbox':  # root
+        nodes.append(node)
+    for n in nodes:
+        if n.find('items') is None:
+            continue
+        for subtoolbox in n.findall('./items/subtoolbox'):
+            items = n.find('./items')
+            idx = items.getchildren().index(subtoolbox)
+
+            if has_xpath:
+                toolbox = toolboxes.find('.//toolbox[@name="%s"]' % subtoolbox.get('name'))
+            else:
+                toolbox = None
+                potentialToolboxes = toolboxes.findall('.//toolbox')
+                sName = subtoolbox.get('name')
+                for pToolbox in potentialToolboxes:
+                    if pToolbox.get('name') == sName:
+                        toolbox = pToolbox
+                        break
+
+            if toolbox is None:  # not in file
+                continue
+            _expandToolboxes(toolbox, toolboxes)
+            items.insert(idx, toolbox)
+            items.remove(subtoolbox)
+
+
+def _expandUserToolboxesItem(node, toolboxes):
+    """!Expand tag 'user-toolboxes-list'.
+
+    Include all user toolboxes.
+    """
+    tboxes = toolboxes.findall('.//toolbox')
+
+    for n in node.findall('./items/user-toolboxes-list'):
+        items = node.find('./items')
+        idx = items.getchildren().index(n)
+        el = etree.Element('toolbox', attrib={'name': 'dummy'})
+        items.insert(idx, el)
+        label = etree.SubElement(el, tag='label')
+        label.text = _("Toolboxes")
+        it = etree.SubElement(el, tag='items')
+        for toolbox in tboxes:
+            it.append(copy.deepcopy(toolbox))
+
+
+def _removeUserToolboxesItem(root):
+    """!Removes tag 'user-toolboxes-list' if there are no user toolboxes."""
+    for n in root.findall('./items/user-toolboxes-list'):
+        items = root.find('./items')
+        items.remove(n)
+
+
+def _expandItems(node, items, itemTag):
+    """!Expand items from file"""
+    for moduleItem in node.findall('.//' + itemTag):
+        itemName = moduleItem.get('name')
+        if has_xpath:
+            moduleNode = items.find('.//%s[@name="%s"]' % (itemTag, itemName))
+        else:
+            moduleNode = None
+            potentialModuleNodes = items.findall('.//%s' % itemTag)
+            for mNode in potentialModuleNodes:
+                if mNode.get('name') == itemName:
+                    moduleNode = mNode
+                    break
+
+        if moduleNode is None:  # module not available in dist
+            continue
+        mItemChildren = moduleItem.getchildren()
+        tagList = [n.tag for n in mItemChildren]
+        for node in moduleNode.getchildren():
+            if node.tag not in tagList:
+                moduleItem.append(node)
+
+
+def _expandRuntimeModules(node):
+    """!Add information to modules (desc, keywords)
+    by running them with --interface-description."""
+    modules = node.findall('.//module-item')
+    for module in modules:
+        name = module.get('name')
+        if module.find('module') is None:
+            n = etree.SubElement(parent=module, tag='module')
+            n.text = name
+
+        if module.find('description') is None:
+            desc, keywords = _loadMetadata(name)
+            n = etree.SubElement(parent=module, tag='description')
+            n.text = _escapeXML(desc)
+            n = etree.SubElement(parent=module, tag='keywords')
+            n.text = _escapeXML(','.join(keywords))
+
+
+def _escapeXML(text):
+    """!Helper function for correct escaping characters for XML.
+
+    Duplicate function in core/toolboxes.
+    """
+    return text.replace('<', '&lt;').replace("&", '&amp;').replace(">", '&gt;')
+
+
+def _loadMetadata(module):
+    """!Load metadata to modules.
+
+    @param module module name
+    @return (description, keywords as a list)
+    """
+    try:
+        task = gtask.parse_interface(module)
+    except ScriptError:
+        return '', ''
+
+    return task.get_description(full=True), \
+        task.get_keywords()
+
+
+def _addHandlers(node):
+    """!Add missing handlers to modules"""
+    for n in node.findall('.//module-item'):
+        if n.find('handler') is None:
+            handlerNode = etree.SubElement(parent=n, tag='handler')
+            handlerNode.text = 'OnMenuCmd'
+
+    # e.g. g.region -p
+    for n in node.findall('.//wxgui-item'):
+        if n.find('command') is not None:
+            handlerNode = etree.SubElement(parent=n, tag='handler')
+            handlerNode.text = 'RunMenuCmd'
+
+
+def _convertTag(node, old, new):
+    """!Converts tag name."""
+    for n in node.findall('.//%s' % old):
+        n.tag = new
+
+
+def _convertTagAndRemoveAttrib(node, old, new):
+    "Converts tag name and removes attributes."
+    for n in node.findall('.//%s' % old):
+        n.tag = new
+        n.attrib = {}
+
+
+def _convertTree(root):
+    """!Converts tree to be the form readable by core/menutree.py."""
+    root.attrib = {}
+    label = root.find('label')
+    root.remove(label)
+    _convertTag(root, 'description', 'help')
+    _convertTag(root, 'wx-id', 'id')
+    _convertTag(root, 'module', 'command')
+    _convertTag(root, 'related-module', 'command')
+    _convertTagAndRemoveAttrib(root, 'wxgui-item', 'menuitem')
+    _convertTagAndRemoveAttrib(root, 'module-item', 'menuitem')
+
+    root.tag = 'menudata'
+    i1 = root.find('./items')
+    i1.tag = 'menubar'
+    _convertTagAndRemoveAttrib(root, 'toolbox', 'menu')
+
+
+def _getXMLString(root):
+    """!Adds comment (about aotogenerated file) to XML.
+
+    @return XML as string
+    """
+    xml = etree.tostring(root, encoding='UTF-8')
+    return xml.replace("<?xml version='1.0' encoding='UTF-8'?>\n",
+                       "<?xml version='1.0' encoding='UTF-8'?>\n"
+                       "<!--This is an auto-generated file-->\n")
+
+
+def main():
+    tree = toolboxes2menudata(userDefined=False)
+    root = tree.getroot()
+    sys.stdout.write(_getXMLString(root))
+
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())

+ 13 - 5
gui/wxpython/lmgr/menudata.py

@@ -17,12 +17,20 @@ This program is free software under the GNU General Public License
 
 import os
 
-from core.globalvar import ETCWXDIR
 from core.menutree  import MenuTreeModelBuilder
+from core.toolboxes import getMenuFile
+from core.globalvar import ETCWXDIR
+from core.gcmd import GError
+
 
 class LayerManagerMenuData(MenuTreeModelBuilder):
-    def __init__(self, filename = None):
+    def __init__(self, filename=None):
         if not filename:
-            filename = os.path.join(ETCWXDIR, 'xml', 'menudata.xml')
-        
-        MenuTreeModelBuilder.__init__(self, filename)
+            filename = getMenuFile()
+        try:
+            MenuTreeModelBuilder.__init__(self, filename)
+        except (ValueError, AttributeError, TypeError):
+            GError(_("Unable to parse user toolboxes XML files. "
+                     "Default toolboxes will be loaded."))
+            fallback = os.path.join(ETCWXDIR, 'xml', 'menudata.xml')
+            MenuTreeModelBuilder.__init__(self, fallback)

+ 85 - 0
gui/wxpython/tools/build_modules_xml.py

@@ -0,0 +1,85 @@
+"""!
+@package tools.build_modules_xml
+
+@brief Builds XML metadata of GRASS modules. Runs only during compilation.
+
+(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.
+
+@author Vaclav Petras <wenzeslaus gmail.com>
+@author Anna Petrasova <kratochanna gmail.com>
+"""
+
+import sys
+from datetime import datetime
+
+
+def escapeXML(text):
+    """!Helper function for correct escaping characters for XML
+
+    Duplicate function in core/toolboxes.
+    """
+    return text.replace('<', '&lt;').replace("&", '&amp;').replace(">", '&gt;')
+
+
+def parse_modules(fd):
+    """!Writes metadata to xml file."""
+    import grass.script as grass
+    mlist = list(grass.get_commands()[0])  # what about windows?
+    indent = 4
+    for m in mlist:
+        # TODO: get rid of g.mapsets_picker.py
+        if m == 'g.mapsets_picker.py':
+            continue
+        desc, keyw = get_module_metadata(m)
+        fd.write('%s<module-item name="%s">\n' % (' ' * indent, m))
+        indent += 4
+        fd.write('%s<module>%s</module>\n' % (' ' * indent, m))
+        fd.write('%s<description>%s</description>\n' % (' ' * indent, escapeXML(desc)))
+        fd.write('%s<keywords>%s</keywords>\n' % (' ' * indent, escapeXML(','.join(keyw))))
+        indent -= 4
+        fd.write('%s</module-item>\n' % (' ' * indent))
+
+
+def get_module_metadata(name):
+    import grass.script.task as gtask
+    try:
+        task = gtask.parse_interface(name)
+    except:
+        return '', ''
+
+    return task.get_description(full=True), \
+        task.get_keywords()
+
+
+def header(fd):
+    import grass.script.core as grass
+    fd.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+    fd.write('<!DOCTYPE module-items SYSTEM "module_items.dtd">\n')
+    fd.write('<!--This file is automatically generated using %s-->\n' % sys.argv[0])
+    vInfo = grass.version()
+    fd.write('<!--version="%s" revision="%s" date="%s"-->\n' % \
+                 (vInfo['version'].split('.')[0],
+                  vInfo['revision'],
+                  datetime.now()))
+    fd.write('<module-items>\n')
+
+
+def footer(fd):
+    fd.write('</module-items>\n')
+
+
+def main():
+    fh = sys.stdout
+
+    header(fh)
+    parse_modules(fh)
+    footer(fh)
+
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())

+ 12 - 0
gui/wxpython/xml/main_menu.dtd

@@ -0,0 +1,12 @@
+<!ELEMENT toolbox (label, items)>
+<!ATTLIST toolbox name NMTOKEN #REQUIRED>
+
+<!ELEMENT items ((subtoolbox | user-toolboxes-list)*)>
+
+<!ELEMENT subtoolbox EMPTY>
+<!ATTLIST subtoolbox name NMTOKEN #REQUIRED>
+
+<!ELEMENT user-toolboxes-list EMPTY>
+
+<!ELEMENT label (#PCDATA)>
+

+ 17 - 0
gui/wxpython/xml/main_menu.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbox SYSTEM "main_menu.dtd">
+<toolbox name="DefaultMainMenu">
+  <label>Default GRASS GIS main menu bar</label>
+  <items>
+    <subtoolbox name="File"/>
+    <subtoolbox name="Settings"/>
+    <subtoolbox name="Raster"/>
+    <subtoolbox name="Vector"/>
+    <subtoolbox name="Imagery"/>
+    <subtoolbox name="Volumes"/>
+    <subtoolbox name="Database"/>
+    <user-toolboxes-list />
+    <subtoolbox name="Help"/>
+  </items>
+</toolbox>
+

+ 2 - 1
gui/wxpython/xml/menudata.dtd

@@ -2,7 +2,8 @@
 <!ELEMENT menubar (menu*)>
 <!ELEMENT menu (label, items)>
 <!ELEMENT items ((separator | menuitem | menu)*)>
-<!ELEMENT menuitem (label, help, keywords?, handler, command?, shortcut?, id?)>
+<!ELEMENT menuitem (label, ((help, keywords?, handler, command?, shortcut?, id?) | (command, help, keywords, id?, handler) |
+                            (handler, help, shortcut?, id?)))>
 <!ELEMENT separator EMPTY>
 <!ELEMENT label (#PCDATA)>
 <!ELEMENT help (#PCDATA)>

File diff ditekan karena terlalu besar
+ 0 - 3438
gui/wxpython/xml/menudata.xml


+ 10 - 0
gui/wxpython/xml/module_items.dtd

@@ -0,0 +1,10 @@
+<!ELEMENT module-items (module-item*)>
+
+<!ELEMENT module-item (label?, module, description, keywords)>
+<!ATTLIST module-item name NMTOKEN #REQUIRED>
+
+<!ELEMENT label (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT module (#PCDATA)>
+<!ELEMENT keywords (#PCDATA)>
+

+ 34 - 0
gui/wxpython/xml/toolboxes.dtd

@@ -0,0 +1,34 @@
+<!ELEMENT toolboxes (toolbox*)>
+
+<!ELEMENT toolbox (label, items)>
+<!ATTLIST toolbox name NMTOKEN #REQUIRED>
+
+<!ELEMENT items ((module-item | wxgui-item | subtoolbox | separator)*)>
+
+<!-- Subelement label is mandatory, however this may change in the future. -->
+<!ELEMENT module-item (label, module?, description?, keywords?)>
+<!ATTLIST module-item name NMTOKEN #REQUIRED>
+
+<!ELEMENT wxgui-item (label?, ((handler, related-module?) | command)?, description?, keywords?, shortcut?, wx-id?)>
+<!ATTLIST wxgui-item name NMTOKEN #REQUIRED>
+
+<!--
+Element subtoolbox could use xlink syntax but it is not much supported,
+so it would be useless. Used syntax is easier and more conforms to other
+elements which are not typical candidates for xlink use.
+-->
+<!ELEMENT subtoolbox EMPTY>
+<!ATTLIST subtoolbox name NMTOKEN #REQUIRED>
+
+<!ELEMENT separator EMPTY>
+
+<!ELEMENT label (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT handler (#PCDATA)>
+<!ELEMENT command (#PCDATA)>
+<!ELEMENT module (#PCDATA)>
+<!ELEMENT related-module (#PCDATA)>
+<!ELEMENT keywords (#PCDATA)>
+<!ELEMENT shortcut (#PCDATA)>
+<!ELEMENT wx-id (#PCDATA)>
+

File diff ditekan karena terlalu besar
+ 1736 - 0
gui/wxpython/xml/toolboxes.xml


+ 14 - 0
gui/wxpython/xml/wxgui_items.dtd

@@ -0,0 +1,14 @@
+<!ELEMENT wxgui-items (wxgui-item*)>
+
+<!ELEMENT wxgui-item (label, ((handler, related-module?) | command), description, keywords?, shortcut?, wx-id?)>
+<!ATTLIST wxgui-item name NMTOKEN #REQUIRED>
+
+<!ELEMENT label (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT handler (#PCDATA)>
+<!ELEMENT command (#PCDATA)>
+<!ELEMENT related-module (#PCDATA)>
+<!ELEMENT keywords (#PCDATA)>
+<!ELEMENT shortcut (#PCDATA)>
+<!ELEMENT wx-id (#PCDATA)>
+

+ 348 - 0
gui/wxpython/xml/wxgui_items.xml

@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wxgui_items SYSTEM "wxgui_items.dtd">
+<wxgui-items>
+  <wxgui-item name="Georectify">
+    <label>Georectify</label>
+    <handler>OnGCPManager</handler>
+    <description>Manage Ground Control Points for Georectification</description>
+  </wxgui-item>
+  <wxgui-item name="GraphicalModeler">
+    <label>Graphical modeler</label>
+    <handler>OnGModeler</handler>
+    <related-module>g.gui.gmodeler</related-module>
+    <description>Launch Graphical modeler</description>
+    <keywords>general,gui,graphical modeler,workflow</keywords>
+  </wxgui-item>
+  <wxgui-item name="RunModel">
+    <label>Run model</label>
+    <handler>OnRunModel</handler>
+    <description>Run model prepared by Graphical modeler</description>
+  </wxgui-item>
+  <wxgui-item name="AnimationTool">
+    <label>Animation tool</label>
+    <handler>OnAnimationTool</handler>
+    <related-module>g.gui.animation</related-module>
+    <description>Launch animation tool.</description>
+    <keywords>general,gui,display</keywords>
+  </wxgui-item>
+  <wxgui-item name="CartographicComposer">
+    <label>Cartographic Composer</label>
+    <handler>OnPsMap</handler>
+    <related-module>g.gui.psmap</related-module>
+    <description>Launch Cartographic Composer</description>
+    <keywords>postscript,printing</keywords>
+  </wxgui-item>
+  <wxgui-item name="MapSwipe">
+    <label>Map Swipe</label>
+    <handler>OnMapSwipe</handler>
+    <related-module>g.gui.mapswipe</related-module>
+    <description>Launch Map Swipe</description>
+    <keywords>general,gui,display</keywords>
+  </wxgui-item>
+  <wxgui-item name="LaunchScript">
+    <label>Launch script</label>
+    <handler>OnRunScript</handler>
+    <description>Launches script file.</description>
+  </wxgui-item>
+  <wxgui-item name="Quit">
+    <label>Quit</label>
+    <handler>OnCloseWindow</handler>
+    <description>Quit</description>
+    <shortcut>Ctrl+Q</shortcut>
+    <wx-id>ID_EXIT</wx-id>
+  </wxgui-item>
+  <wxgui-item name="Preferences">
+    <label>Preferences</label>
+    <handler>OnPreferences</handler>
+    <description>User GUI preferences (display font, commands, digitizer, etc.)</description>
+    <wx-id>ID_PREFERENCES</wx-id>
+  </wxgui-item>
+  <wxgui-item name="RasterMapCalculator">
+    <label>Raster map calculator</label>
+    <handler>OnMapCalculator</handler>
+    <related-module>r.mapcalc</related-module>
+    <description>Raster map calculator.</description>
+    <keywords>raster,algebra</keywords>
+  </wxgui-item>
+  <wxgui-item name="Histogram">
+    <label>Histogram</label>
+    <handler>OnHistogram</handler>
+    <description>Generate histogram of image</description>
+  </wxgui-item>
+  <wxgui-item name="VolumeCalculator">
+    <label>Volume calculator</label>
+    <handler>OnMapCalculator</handler>
+    <related-module>r3.mapcalc</related-module>
+    <description>3D raster map calculator.</description>
+    <keywords>raster,algebra</keywords>
+  </wxgui-item>
+  <wxgui-item name="GRASSHelp">
+    <label>GRASS help</label>
+    <command>g.manual -i</command>
+    <description>Display the HTML man pages of GRASS GIS</description>
+    <keywords>general,manual,help</keywords>
+    <wx-id>ID_HELP</wx-id>
+  </wxgui-item>
+  <wxgui-item name="GUIHelp">
+    <label>GUI help</label>
+    <command>g.manual entry=wxGUI</command>
+    <description>Display the HTML man pages of GRASS GIS</description>
+    <keywords>general,manual,help</keywords>
+  </wxgui-item>
+  <wxgui-item name="AboutSystem">
+    <label>About system</label>
+    <handler>OnSystemInfo</handler>
+    <description>Prints system information</description>
+  </wxgui-item>
+  <wxgui-item name="AboutGRASSGIS">
+    <label>About GRASS GIS</label>
+    <handler>OnAboutGRASS</handler>
+    <description>About GRASS GIS</description>
+    <wx-id>ID_ABOUT</wx-id>
+  </wxgui-item>
+  <wxgui-item name="New">
+    <label>New</label>
+    <handler>OnWorkspaceNew</handler>
+    <description>Create new workspace</description>
+    <shortcut>Ctrl+N</shortcut>
+    <wx-id>ID_NEW</wx-id>
+  </wxgui-item>
+  <wxgui-item name="Open">
+    <label>Open</label>
+    <handler>OnWorkspaceOpen</handler>
+    <description>Load workspace from file</description>
+    <shortcut>Ctrl+O</shortcut>
+    <wx-id>ID_OPEN</wx-id>
+  </wxgui-item>
+  <wxgui-item name="Save">
+    <label>Save</label>
+    <handler>OnWorkspaceSave</handler>
+    <description>Save workspace</description>
+    <shortcut>Ctrl+S</shortcut>
+    <wx-id>ID_SAVE</wx-id>
+  </wxgui-item>
+  <wxgui-item name="SaveAs">
+    <label>Save as</label>
+    <handler>OnWorkspaceSaveAs</handler>
+    <description>Save workspace to file</description>
+    <wx-id>ID_SAVEAS</wx-id>
+  </wxgui-item>
+  <wxgui-item name="Close">
+    <label>Close</label>
+    <handler>OnWorkspaceClose</handler>
+    <description>Close workspace file</description>
+    <wx-id>ID_CLOSE</wx-id>
+  </wxgui-item>
+  <wxgui-item name="LoadGRCFileTclTkGUI">
+    <label>Load GRC file (Tcl/Tk GUI)</label>
+    <handler>OnWorkspaceLoadGrcFile</handler>
+    <description>Load map layers from GRC file to layer tree</description>
+  </wxgui-item>
+  <wxgui-item name="AddRaster">
+    <label>Add raster</label>
+    <handler>OnAddRaster</handler>
+    <description>Add raster map layer to current display</description>
+    <shortcut>Ctrl+Shift+R</shortcut>
+  </wxgui-item>
+  <wxgui-item name="AddVector">
+    <label>Add vector</label>
+    <handler>OnAddVector</handler>
+    <description>Add vector map layer to current display</description>
+    <shortcut>Ctrl+Shift+V</shortcut>
+  </wxgui-item>
+  <wxgui-item name="AddMultipleRastersOrVectors">
+    <label>Add multiple rasters or vectors</label>
+    <handler>OnAddMaps</handler>
+    <description>Add multiple raster or vector map layers to current display</description>
+    <shortcut>Ctrl+Shift+L</shortcut>
+  </wxgui-item>
+  <wxgui-item name="NewMapDisplayWindow">
+    <label>New map display window</label>
+    <handler>OnNewDisplay</handler>
+    <description>Open new map display window</description>
+  </wxgui-item>
+  <wxgui-item name="CloseCurrentMapDisplayWindow">
+    <label>Close current map display window</label>
+    <handler>OnDisplayClose</handler>
+    <description>Close current map display window</description>
+    <shortcut>Ctrl+W</shortcut>
+  </wxgui-item>
+  <wxgui-item name="CloseAllOpenMapDisplayWindows">
+    <label>Close all open map display windows</label>
+    <handler>OnDisplayCloseAll</handler>
+    <description>Close all open map display windows</description>
+  </wxgui-item>
+  <wxgui-item name="CommonFormatsImport">
+    <label>Common formats import</label>
+    <handler>OnImportGdalLayers</handler>
+    <related-module>r.in.gdal</related-module>
+    <description>Import raster data into a GRASS map layer using GDAL.</description>
+    <keywords>raster,import</keywords>
+  </wxgui-item>
+  <wxgui-item name="CommonImportFormats">
+    <label>Common import formats</label>
+    <handler>OnImportOgrLayers</handler>
+    <related-module>v.in.ogr</related-module>
+    <description>Converts vector layers into a GRASS vector map using OGR.</description>
+    <keywords>vector,import</keywords>
+  </wxgui-item>
+  <wxgui-item name="DXFImport">
+    <label>DXF import</label>
+    <handler>OnImportDxfFile</handler>
+    <related-module>v.in.dxf</related-module>
+    <description>Converts files in DXF format to GRASS vector map format.</description>
+    <keywords>vector,import,dxf</keywords>
+  </wxgui-item>
+  <wxgui-item name="LinkExternalRasterData">
+    <label>Link external raster data</label>
+    <handler>OnLinkGdalLayers</handler>
+    <related-module>r.external</related-module>
+    <description>Link GDAL supported raster data as a pseudo GRASS raster map layer.</description>
+    <keywords>raster,import,input,external</keywords>
+  </wxgui-item>
+  <wxgui-item name="LinkExternalVectorData">
+    <label>Link external vector data</label>
+    <handler>OnLinkOgrLayers</handler>
+    <related-module>v.external</related-module>
+    <description>Creates a new pseudo-vector map as a link to an OGR-supported layer.</description>
+    <keywords>vector,import,input,external,OGR,PostGIS</keywords>
+  </wxgui-item>
+  <wxgui-item name="OutputFormatForVectorData">
+    <label>Output format for vector data</label>
+    <handler>OnVectorOutputFormat</handler>
+    <related-module>v.external.out</related-module>
+    <description>Defines vector output format utilizing OGR library.</description>
+    <keywords>vector,export,output,external,OGR,PostGIS</keywords>
+  </wxgui-item>
+  <wxgui-item name="DisplayRegion">
+    <label>Display region</label>
+    <command>g.region -p</command>
+    <description>Manages the boundary definitions for the geographic region.</description>
+    <keywords>general,settings</keywords>
+  </wxgui-item>
+  <wxgui-item name="MapsetAccess">
+    <label>Mapset access</label>
+    <handler>OnMapsets</handler>
+    <related-module>g.mapsets</related-module>
+    <description>Set/unset access to other mapsets in current location</description>
+    <keywords>general,settings,search path</keywords>
+  </wxgui-item>
+  <wxgui-item name="ChangeLocationAndMapset">
+    <label>Change location and mapset</label>
+    <handler>OnChangeLocation</handler>
+    <description>Change current location and mapset.</description>
+    <keywords>general,location,current</keywords>
+  </wxgui-item>
+  <wxgui-item name="ChangeMapset">
+    <label>Change mapset</label>
+    <handler>OnChangeMapset</handler>
+    <description>Change current mapset.</description>
+    <keywords>general,mapset,current</keywords>
+  </wxgui-item>
+  <wxgui-item name="ChangeWorkingDirectory">
+    <label>Change working directory</label>
+    <handler>OnChangeCWD</handler>
+    <description>Change working directory</description>
+  </wxgui-item>
+  <wxgui-item name="ShowSettings">
+    <label>Show settings</label>
+    <command>g.gisenv -n</command>
+    <description>Outputs and modifies the user's current GRASS variable settings.</description>
+    <keywords>general,settings,variables</keywords>
+  </wxgui-item>
+  <wxgui-item name="CreateNewLocation">
+    <label>Create new location</label>
+    <handler>OnLocationWizard</handler>
+    <description>Launches location wizard to create new GRASS location.</description>
+    <keywords>general,location,wizard</keywords>
+  </wxgui-item>
+  <wxgui-item name="CreateNewMapset">
+    <label>Create new mapset</label>
+    <handler>OnCreateMapset</handler>
+    <description>Creates new mapset in the current location, changes current mapset.</description>
+    <keywords>general,mapset,create</keywords>
+  </wxgui-item>
+  <wxgui-item name="VersionAndCopyright">
+    <label>Version and copyright</label>
+    <command>g.version -c</command>
+    <description>Displays version and copyright information.</description>
+    <keywords>general,version</keywords>
+  </wxgui-item>
+  <wxgui-item name="DisplayMapProjection">
+    <label>Display map projection</label>
+    <command>g.proj -p</command>
+    <description>Converts co-ordinate system descriptions (i.e. projection information) between various formats (including GRASS format).</description>
+    <keywords>general,projection,create location</keywords>
+  </wxgui-item>
+  <wxgui-item name="InstallExtensionFromAddons">
+    <label>Install extension from addons</label>
+    <handler>OnInstallExtension</handler>
+    <related-module>g.extension</related-module>
+    <description>Installs new extension from GRASS AddOns SVN repository.</description>
+    <keywords>general,installation,extensions</keywords>
+  </wxgui-item>
+  <wxgui-item name="UninstallExtension">
+    <label>Uninstall extension</label>
+    <handler>OnUninstallExtension</handler>
+    <related-module>g.extension</related-module>
+    <description>Removes installed GRASS AddOns extension.</description>
+    <keywords>general,installation,extensions</keywords>
+  </wxgui-item>
+  <wxgui-item name="ManageColorRulesInteractively">
+    <label>Manage color rules interactively</label>
+    <handler>OnRasterRules</handler>
+    <description>Interactive management of raster color tables.</description>
+    <keywords>raster,color table</keywords>
+  </wxgui-item>
+  <wxgui-item name="SetUpSamplingAndAnalysisFramework">
+    <label>Set up sampling and analysis framework</label>
+    <handler>OnRLiSetup</handler>
+    <description>Configuration editor for r.li.'index'</description>
+    <keywords>raster,landscape structure analysis</keywords>
+  </wxgui-item>
+  <wxgui-item name="OrdinaryOrBlockKriging">
+    <label>Ordinary or block kriging</label>
+    <command>v.krige</command>
+    <description>Performs ordinary or block kriging.</description>
+    <keywords>vector,raster,interpolation,kriging</keywords>
+  </wxgui-item>
+  <wxgui-item name="CreateNewVectorMap">
+    <label>Create new vector map</label>
+    <handler>OnNewVector</handler>
+    <description>Create new empty vector map</description>
+  </wxgui-item>
+  <wxgui-item name="CleanVectorMap">
+    <label>Clean vector map</label>
+    <handler>OnVectorCleaning</handler>
+    <related-module>v.clean</related-module>
+    <description>Toolset for cleaning topology of vector map.</description>
+    <keywords>vector,topology,geometry</keywords>
+  </wxgui-item>
+  <wxgui-item name="ManageColorRulesInteractively">
+    <label>Manage color rules interactively</label>
+    <handler>OnVectorRules</handler>
+    <description>Interactive management of vector color tables.</description>
+    <keywords>vector,color table</keywords>
+  </wxgui-item>
+  <wxgui-item name="VectorNetworkAnalysisTool">
+    <label>Vector network analysis tool</label>
+    <handler>OnVNet</handler>
+    <description>Tool for interactive vector network analysis.</description>
+    <keywords>gui,vector,network</keywords>
+  </wxgui-item>
+  <wxgui-item name="CreateOrEditGroup">
+    <label>Create/edit group</label>
+    <handler>OnEditImageryGroups</handler>
+    <related-module>i.group</related-module>
+    <description>Creates, edits, and lists groups of imagery files.</description>
+    <keywords>imagery,map management</keywords>
+  </wxgui-item>
+  <wxgui-item name="InteractiveInputForSupervisedClassification">
+    <label>Interactive input for supervised classification</label>
+    <handler>OnIClass</handler>
+    <related-module>g.gui.iclass</related-module>
+    <description>Generates spectral signatures by allowing the user to outline training areas.</description>
+    <keywords>general,gui,imagery,classification,signatures</keywords>
+  </wxgui-item>
+</wxgui-items>
+