commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r8929 - in trunk/gnue-designer: . src src/app src/base src/forms


From: jcater
Subject: [gnue] r8929 - in trunk/gnue-designer: . src src/app src/base src/forms src/standalone utils
Date: Wed, 25 Oct 2006 18:59:36 -0500 (CDT)

Author: jcater
Date: 2006-10-25 18:59:35 -0500 (Wed, 25 Oct 2006)
New Revision: 8929

Added:
   trunk/gnue-designer/src/base/document.py
   trunk/gnue-designer/src/base/parsertoobj.py
   trunk/gnue-designer/src/standalone/
   trunk/gnue-designer/src/standalone/__init__.py
   trunk/gnue-designer/utils/
   trunk/gnue-designer/utils/package_standalone_definitions.py
Removed:
   trunk/gnue-designer/src/base/Document.py
Modified:
   trunk/gnue-designer/src/app/documents.py
   trunk/gnue-designer/src/forms/document.py
Log:

* Added a script to be run when packaging Designer releases 
(utils/package_standalone_definitions.py) that takes the tool's G*Parser.py 
files and creates standalone versions using proxy classes, so designer does not 
require each individual tool to be installed
* Misc cleanup as I get back into coding


Modified: trunk/gnue-designer/src/app/documents.py
===================================================================
--- trunk/gnue-designer/src/app/documents.py    2006-10-25 16:22:31 UTC (rev 
8928)
+++ trunk/gnue-designer/src/app/documents.py    2006-10-25 23:59:35 UTC (rev 
8929)
@@ -35,19 +35,19 @@
 document_types = []
 
 
-class Properties: 
-    """ 
+class Properties:
+    """
     A container class to hold our property values
     """
     pass
 
 
-def register_document_type(instance, name, title, 
-           fileExtensions, defaultFileExtension="", 
+def register_document_type(instance, name, title,
+           fileExtensions, defaultFileExtension="",
            description="", nickname="", xmlOpeningTag=""):
     """
-    Register a new document handler. 
-    """           
+    Register a new document handler.
+    """
     properties = Properties()
     properties.instance = instance
     properties.name = name
@@ -58,12 +58,12 @@
     properties.defaultFileExtension = defaultFileExtension or \
                    fileExtensions.keys()[0]
     properties.xmlOpeningTag = xmlOpeningTag
-    
+
     document_types.append(properties)
-    if instance: 
+    if instance:
         document_types_valid.append(properties)
-    else: 
+    else:
         document_types_invalid.append(properties)
-        
+
     return properties
 

Deleted: trunk/gnue-designer/src/base/Document.py
===================================================================
--- trunk/gnue-designer/src/base/Document.py    2006-10-25 16:22:31 UTC (rev 
8928)
+++ trunk/gnue-designer/src/base/Document.py    2006-10-25 23:59:35 UTC (rev 
8929)
@@ -1,891 +0,0 @@
-# GNU Enterprise Designer - Basic Framework
-#
-# Copyright 2001-2006 Free Software Foundation
-#
-# This file is part of GNU Enterprise.
-#
-# GNU Enterprise is free software; you can redistribute it
-# and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
-# version 2, or (at your option) any later version.
-#
-# GNU Enterprise is distributed in the hope that it will be
-# useful, but WITHOUT ANY WARRANTY; without even the implied
-# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-# PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public
-# License along with program; see the file COPYING. If not,
-# write to the Free Software Foundation, Inc., 59 Temple Place
-# - Suite 330, Boston, MA 02111-1307, USA.
-#
-# $Id$
-
-"""
-This is the base instance class for a designer session. Every
-open file will be associated with its own document instance.
-"""
-
-__all__ = ['BaseInstance']
-
-# -----------------------------------------------------------------
-# System imports
-# -----------------------------------------------------------------
-import sys
-import os
-import time
-import dircache
-import new
-
-# -----------------------------------------------------------------
-# GNUe Imports
-# -----------------------------------------------------------------
-from gnue.common.apps import GDebug
-from gnue.common.apps import RuntimeSettings
-from gnue.common.utils.FileUtils import dyn_import
-from gnue.common.events import EventController, Event
-
-from gnue.designer.base.MenuBar import MenuBar
-from gnue.designer.base.UndoManager import UndoManager
-from gnue.designer.base.tools import TriggerEditor
-from gnue.designer.base.ToolBase import ToolBase
-from gnue.designer.base.ObjectList import ObjectList
-from gnue.designer.base import TemplateBase
-from gnue.designer.base.TemplateParser import WizardRunner
-from gnue.designer import VERSION, PACKAGE as TITLE
-
-from gnue.designer.app.documents import document_types_valid
-
-
-# ===================================================================
-# Base document class
-# ===================================================================
-class BaseDocument(EventController):
-
-
-    # ===============================================================
-    # Virtual functions (Override these functions in your Instance)
-    # ===============================================================
-    wizardRunner = WizardRunner
-
-    def init(self):
-        """
-        initialize the instance (called at the
-        beginning of the __init__ process)
-        """
-
-    def init(self):
-        """
-        Finalize the instance (called at the
-        end of the __init__ process)
-        """
-
-    def loadFile(self, buffer):
-        """
-        Called to load the object from a file buffer/handle
-        """
-        return None
-
-    def loadEmpty(self, style=None):
-        """
-        Called to load an "empty" (new) object.  Create the root
-        object and any initial child objects (if appropriate)
-        """
-        return None
-
-    def inventoryObject(self, object):
-        """
-        Called in a tree-like fashion for every object
-        whether loaded in the beginning or later added.
-        """
-        pass
-
-    def preSave(self):
-        """
-        Called just before saving the file using GObject's dumpTree
-        You might do some sanity checks, etc.
-        """
-        return
-
-    def createTools(self):
-        """
-        Add any ToolBase instances
-        """
-        pass
-
-    def createEditors(self):
-        """
-        Add any EditorComponent instances
-        """
-        pass
-
-    def createWizards(self):
-        """
-        Add any runtime-loadable wizards/tools
-        """
-        pass
-
-    def initMenu(self):
-        """
-        Add any tool-specific functions to the menu bar
-        """
-        pass
-
-    def initToolBar(self):
-        """
-        Add any tool-specific functions to the tool bar
-        """
-        pass
-
-
-    def buildWizardCurrentDict(self):
-        """
-        Used by TemplateParser to build a wizard.current dict
-        """
-        return {'object': self._currentObject}
-
-
-    # ===============================================================
-    # Public Functions
-    # ===============================================================
-
-
-    # ---------------------------------------------------------------
-    # Register interface elements
-    # ---------------------------------------------------------------
-    def addTool(self, id, title, baseclass, hotkey=None, menuGroup=499):
-        """
-        Add a ToolBase instance
-        """
-        self._toolCache.append((id, title, baseclass, hotkey, menuGroup))
-
-
-    def registerEditor(self, baseclass, gtype, filter=None):
-        """
-        Register an editor class
-
-        Parameters:
-
-          baseclass: An EditorComponent class
-
-          gtype: A string indicating a GObject._type identifier,
-             or a list of such strings.
-
-          filter: A function that is passed a GObject and should
-             return True/False indicating if an editor instance
-             should be created.
-
-        """
-        if isinstance(gtype,basestring):
-            gtype = [gtype]
-        for gtype1 in gtype:
-            self._editorMapping[gtype1] = (filter, baseclass)
-
-
-    # ---------------------------------------------------------------
-    # Set the saved/unsaved status
-    # ---------------------------------------------------------------
-
-    def save(self):
-
-        if self.preSave():
-            print "Not saving definition"
-            return
-
-        location = self._path
-        fileHandle = None
-        fileHandle2 = None
-        if self._makeBackup:
-            try:
-                fileHandle = open(location,'r')
-                fileHandle2 = open(location + "~",'w')
-                fileHandle2.writelines(fileHandle.readlines())
-            except:
-                pass
-            else:
-                if fileHandle != None:
-                    fileHandle.close()
-                if fileHandle2 != None:
-                    fileHandle2.close()
-
-        self._makeBackup = 0
-
-        fileHandle = open(location,'w')
-
-        fileHandle.write('<?xml version="1.0" encoding="UTF-8"?>\n\n')
-
-        for comment in self.rootObject._rootComments:
-            if comment.find(TITLE) > 0:
-                self.rootObject._rootComments.remove(comment)
-
-        # Place a timestamp in the XML as a comment
-        # TODO: Replace with Dublin Core?
-        fileHandle.write(('<!--  %s (%s)\n%s      Saved on: %s  -->\n\n' \
-           % (TITLE, VERSION, (len(self.wizardName) and (
-               "      Created by " + self.wizardName + "\n") or ""),\
-              time.strftime("%Y-%m-%d %H:%M:%S",
-              time.localtime(time.time())))).encode('UTF-8'))
-
-        fileHandle.write(''.join(["<!--%s-->\n\n" % comment.encode('UTF-8') \
-                         for comment in self.rootObject._rootComments]))
-
-        
fileHandle.write(self.rootObject.dumpXML(treeDump=True).encode('UTF-8'))
-        fileHandle.close()
-
-        self.app.mru.addLocation(location)
-        self.makeClean()
-
-
-    # Mark our form as "dirty" (unsaved changes)
-    def makeDirty(self):
-        if not self._isdirty:
-            self._isdirty = True
-            if self._path == "":
-                self.ui.setTitle( u_("Untitled %s*") % 
self.properties.nickname)
-            else:
-                self.ui.setTitle(self._path + "*")
-        self.dispatchEvent('MakeDirty')
-
-
-    # Mark our form as "clean" (no unsaved changes)
-    def makeClean(self):
-        self._isdirty = 0
-        self._isnew = 0
-        if self._path == "":
-            self.ui.setTitle( u_("Untitled %s") % self.properties.nickname)
-        else:
-            self.ui.setTitle( self._path)
-        self.dispatchEvent('MakeClean')
-
-
-    # ---------------------------------------------------------------
-    # GObject convenience methods
-    # ---------------------------------------------------------------
-    def getNextGenericName (self, type):
-        return self.getUniqueName(type.capitalize() + '1')
-
-
-    def getUniqueName(self, name, limitingObject=None):
-
-        try:
-            usedNames = limitingObject.usedNames
-        except:
-            usedNames = self.usedNames
-
-        if name.lower() not in usedNames:
-            usedNames.append(name.lower())
-            return name
-
-        index = len(name) - 1
-
-        while index > 0 and '0' <= name[index] <= '9':
-            index -= 1
-
-        index += 1
-        if index >= len(name):
-            start = 1
-            base = name
-        else:
-            start = int(name[index:])
-            base = name[:index]
-
-        while ("%s%s" % (base, start)).lower() in usedNames:
-            start += 1
-
-        rv = "%s%s" % (base, start)
-        usedNames.append(rv.lower())
-        if rv.lower() not in self.usedNames:
-            self.usedNames.append(rv.lower())
-        return rv
-
-
-    # ---------------------------------------------------------------
-    # Return, or create, an ObjectList based on the xml tag
-    # ---------------------------------------------------------------
-    def getObjectList(self, tag):
-        try:
-            return self.objectLists[tag]
-        except KeyError:
-            defin = self.incubator.elements[tag]
-            baseClass = defin['BaseClass']
-
-            # Determine the "name" attribute"
-            nameAttr = None
-            try:
-                if defin['Attributes'].has_key('name'):
-                    nameAttr = 'name'
-                else:
-                    for attribute, props in defin['Attributes'].items():
-                        try:
-                            if props['Unique']:
-                                nameAttr = attribute
-                                break
-                        except KeyError:
-                            pass
-            except KeyError:
-                pass
-
-            list = ObjectList(self, baseClass, nameAttr)
-            self.objectLists[tag] = list
-            return list
-
-
-    # ================================================================
-    # Private functions
-    # ================================================================
-
-    def __init__(self, app, properties, location=None,
-                 buffer=None, style=None):
-        EventController.__init__(self)
-
-        self.app = app
-        self.properties = properties
-
-        # During startup, we will cache all events
-        # so we can execute them when everything has
-        # been initialized.
-        self.startCachingEvents()
-
-        self.ui = app.ui.createInstance(self)
-
-        # Local variables
-        self.wizardName = ""
-        self._isdirty = False
-        self._makeBackup = True
-        self._isNew = True
-        self.connections = app.connections
-        self.nameMappings = {}
-        self.usedNames = []
-
-        # Create the supplemental tools
-        self._toolCache = []
-        self._editorMapping = {}
-        self._pages = []
-        self.objectLists = {}
-        self._path = ""
-
-        self.globalAccelerators = []
-        self.globalAcceleratorListeners = []
-
-        self._nameMappers = {} # {GDataSource: {'name': [(GFBlock,'name')]}}
-
-
-        self.registerEventListeners({
-                           # Menu/Toolbar stuff
-                           'RequestSave'         : self._OnSave,
-                           'RequestSaveAs'       : self._OnSaveAs,
-                           'RequestClose'        : self._OnClose,
-
-                           # Object stuff
-                           'ObjectSelected'      : 
self.__object_selected_event,
-                           'ObjectCreated'       : self.__object_created_event,
-                           'ObjectModified'      : 
self.__object_modified_event,
-                           'ObjectDeleted'       : self.__object_deleted_event,
-                          })
-
-
-        # Call the document-specific init method
-        self.init()
-
-        # Register ourself with RuntimeSettings
-        RuntimeSettings.init(configFilename="gnue-des.ini",
-                             homeConfigDir=".gnue")
-        RuntimeSettings.registerInstance(self)
-
-        # Tell RuntimeSettings that we have information to save
-        self.runtime_section = self.properties.nickname + 'Layout'
-        RuntimeSettings.registerRuntimeSettingHandler(self, self)
-
-        # And the "Most Recenty Used" manager
-        RuntimeSettings.registerRuntimeSettingHandler(self, app.mru)
-
-        # Set up the Undo/Redo Manager
-        UndoManager(self)
-
-        # Load any files specified on the command
-        # line, or create a new document
-        if location == None:
-
-            if buffer != None:
-                self.__loadFromBuffer(buffer)
-                self.makeDirty()
-            else:
-                self.__createEmptyInstance(style)
-
-        else:
-            if not os.access (location, os.R_OK):
-                self.show()
-                if not self.app.ui.dialogYesNo(
-                  u_('The requested file does not exist.\n') +
-                  u_('Do you want to create this file?') +
-                  u_('\n\nFile: %s') \
-                    % location, u_("File Not Found"), self.ui):
-                    # TODO: Is this right?
-                    sys.exit()
-                self.hide()
-                self.__createEmptyInstance(style)
-                self._path = location
-                self.makeDirty()
-
-            elif not os.access (location, os.W_OK):
-                self.show()
-                if not self.app.ui.dialogCancel(
-                  u_('The requested file is Read Only.\n') +
-                  u_('To save any changes, you will \n') +
-                  u_('be required to do a "Save As..."\n\nFile: %s') \
-                    % location, u_("Read Only Warning"), self.ui) :
-                    # TODO: Is this right?
-                    sys.exit()
-                self.hide()
-                self.__loadFromFile(location)
-            else:
-                self.__loadFromFile(location)
-
-        self.menubar = MenuBar(self)
-
-
-        gStartupStatus(u_('Creating User Interface'))
-
-        # Set up the menu system
-        #   ... our common menu
-        self._initMenu()
-        #   ... and the document-centric menu
-        self.initMenu()
-
-        self.createWizards()
-
-        # Set up the editor components...
-        #   ... common
-        self.registerEditor(TriggerEditor.TriggerEditor, 'GCTrigger',
-                            TriggerEditor.EditorFilter)
-        #   ... and document-centric
-        self.createEditors()
-
-        # Create the document-centric tools
-        self.createTools()
-
-        # And tell the UI driver to create the UI portions
-        self.ui.initTools()
-
-        # Finalize menu bar
-        self.menubar.finalize()
-        self.app.mru.addMenu(self.menubar.getMenu('File|Open Recent|'), self)
-
-        self.toolbar = self.ui.toolbar
-        self.initToolBar()
-
-        # TODO: This is a hack to disable any menu items
-        # TODO: for actions we've yet to implement
-        for action in ('RequestRevert','RequestRedo','RequestCopy',
-                       'RequestPaste','RequestPasteSpecial','RequestCut'):
-            self.dispatchEvent('Disable:%s' % action)
-
-
-        # Add ourselve to the main app's instance list
-        self.app.addDocument(self)
-
-
-        self.dispatchEvent('ObjectSelected', originator=self,
-                           object=self.rootObject)
-
-        # Inventory the objects
-        gStartupStatus(u_('Inventorying Document Objects'))
-        self.rootObject.walk(self.__inventory)
-
-        self.finalize()
-        self.ui.finalize()
-
-        self.stopCachingEvents()
-
-
-    def _initMenu(self):
-        # Add the [sub]menus
-        for location, text, grouping in (
-              ('File', u_('&File'), 100),
-              ('File|New', u_('&New'), 100),
-              ('File|Open Recent', u_('&Open Recent'), 200.1),
-              ('File|Connect To', u_('&Connect To'), 400),
-              ('Edit', u_('&Edit'), 200),
-              ('Insert',u_('&Insert'), 300),
-              ('Modify',u_('&Modify'), 400),
-              ('Tools',u_('&Tools'), 500),
-              ('View',u_('&View'), 800),
-              ('Help',u_('&Help'), 999)):
-
-            self.menubar.addMenu(location, text, grouping)
-
-        for location, event, text, hotkey, help, grouping in (
-           ('File', 'RequestOpen', u_('&Open'), 'Ctrl+O',
-                u_("Open an existing document"), 200.1),
-           ('File|Open Recent', 'XXXX', u_('&Foo'), None,
-                u_("This is a placeholder for the Open Recent menu"), 200.1),
-           ('File|New', 'RequestNewWizard', u_('From &Wizard...'), None,
-                u_("Create a new document using a wizard"), 900.1),
-           ('File', 'RequestSave', u_("&Save"), 'Ctrl+S',
-                u_("Save the current document"),300.1),
-           ('File', 'RequestSaveAs', u_("Save &As..."),None,
-                u_("Save the current document under a new name"), 300.2),
-           ('File', 'RequestSaveAll', u_("Save A&ll"),None,
-                u_("Save all open document"),300.3),
-           ('File', 'RequestRevert', u_("Reload"), None,
-                u_("Reload the current document as of its last save " + \
-                   "(abandoning any changes)"), 500),
-           ('File', 'RequestClose', u_("&Close"), 'Ctrl+W',
-                u_("Close the current document"), 990),
-           ('File', 'RequestExit', u_("E&xit"), None,
-                u_("Exit GNUe Designer"), 995),
-           ('Edit', 'RequestUndo', u_("&Undo"), 'Ctrl+Z',
-                u_("Undo the last action"), 100.1),
-           ('Edit', 'RequestRedo', u_("&Redo"), 'Ctrl+Y',
-                u_("Redo the last undo action"), 100.2),
-           ('Edit', 'RequestCut', u_("Cu&t"), 'Ctrl+X',
-                u_("Cut the current object and move to the clipboard"), 200.1),
-           ('Edit', 'RequestCopy', u_("&Copy"), 'Ctrl+C',
-                u_("Copy the current object to the clipboard"), 200.2),
-           ('Edit', 'RequestPaste', u_("&Paste"), 'Ctrl+V',
-                u_("Paste the current object on the clipboard"), 200.3),
-           ('Edit', 'RequestPasteSpecial', u_("Paste &Special..."), None,
-                u_("Paste the current object on the clipboard " + \
-                   "with special attributes"), 200.4),
-           ('Modify','RequestDelete', u_("&Delete Item"), 'Delete',
-                u_("Delete the current object"),100),
-           ('Help', 'RequestAbout', u_("&About GNUe Designer"), None,
-                u_("More information about GNUe Designer"), 900),
-         ):
-            self.menubar.addAction(location, text, event,
-                            grouping, canDisable=True,
-                            icon=None, hotkey=hotkey, help=help)
-
-        # Add supported tools to File|New
-        for tool in document_types_valid:
-            self.menubar.addAction(
-                'File|New', '&%s' % tool.nickname,
-                'RequestNew', 100,
-                help=u_('Create a new %s') % tool.description,
-                eventdata={'type': tool.instance})
-
-        # Add connections
-        for conn in self.connections.getAllConnectionParameters().keys():
-            self.menubar.addAction('File|Connect To', conn,
-                     'Connect:%s' % conn,
-                     help=u_("Login to %s connection") % conn,
-                     eventdata={'connection': conn})
-            self.registerEventListeners(
-                  {'Connect:%s' % conn: self.__OnConnectTo})
-
-
-    def __loadFromFile(self, location):
-        try:
-            self._path = location
-            fileHandle = open(location,'r')
-            self.__loadFromBuffer(fileHandle)
-            fileHandle.close()
-            self.makeClean()
-            self._isNew = 0
-        except IOError, msg:
-            print "\n%s %s\n\nUnable to open file '%s'. \n" + \
-                  "Unexpected read error:\n  %s.\n" % (
-                         TITLE, VERSION, location, msg)
-            sys.exit()
-        self.app.mru.addLocation(location)
-
-
-    def addNameMapper(self, instance, attribute, childinst, childattr):
-        try:
-            instm = self._nameMappers[instance]
-        except KeyError:
-            instm = {}
-            self._nameMappers[instance] = instm
-        try:
-            attrm = instm[attribute]
-        except KeyError:
-            attrm = []
-            instm[attribute] = attrm
-        attrm.append ( (childinst, childattr) )
-
-
-    def __loadFromBuffer(self, fileHandle):
-        self.rootObject = self.loadBuffer(fileHandle)
-
-
-    def __createEmptyInstance(self, style):
-        self.rootObject = self.loadEmpty(style)
-        self.makeClean()
-        self._isNew = True
-
-
-    # ---------------------------------------------------------------
-    #
-    # ---------------------------------------------------------------
-    #
-    #  Used by RuntimeSettings
-    #
-    def saveRuntimeSettings(self):
-        return ( self.runtime_section, self.ui.getRuntimeSettings() )
-
-
-    # ---------------------------------------------------------------
-    #
-    # ---------------------------------------------------------------
-    # Do we need to be saved?
-    def isDirty(self):
-        return self._isdirty
-
-
-    # ---------------------------------------------------------------
-    #
-    # ---------------------------------------------------------------
-    # Take an object and mangle it all up
-    # until it is useful to us
-    def __inventory (self, object):
-
-        # Add a GObjectHelper to intercept __getitem__ calls on GObject
-        add_GObject_hooks(object, self)
-
-        if object != self.rootObject:
-
-            # Assign an ID if none exists
-            if hasattr(object, 'name'):
-                if object.name == None or object.name.startswith(object._type):
-                    object.name = self.getNextGenericName(object._type[2:])
-                self.nameMappings[object.name.lower()] = object
-                self.usedNames.append(object.name.lower())
-
-        # Do we create an EditorComponent instance?
-        if object._type in self._editorMapping.keys():
-            filter = self._editorMapping[object._type][0]
-            if filter is None or filter(object):
-                self.ui.createEditor(object,
-                      *self._editorMapping[object._type][1:])
-
-        # Now, give the tool-specific instances a chance
-        object.dispatch_designer_event('InventoryObject')
-        self.inventoryObject(object)
-
-
-    def __object_selected_event (self, event):
-        object = event.object
-        handler = event.originator
-        self._currentObject = object
-
-    def __object_created_event (self, event):
-        self.__inventory(event.object)
-        self.makeDirty()
-
-    def __object_modified_event (self, event):
-        object = event.object
-        # Check for any name dependencies
-        # (i.e., GFEntry is dependent on GFBlock.name and GFField.name)
-        # Automatically create any change events for the child objects
-        if hasattr(object, '_nameDependencies'):
-            for key in object._nameDependencies.keys():
-                masterattr, slaveattr = object._nameDependencies[key]
-                if masterattr in event.new.keys():
-                    key[slaveattr] = object[masterattr]
-
-        self.makeDirty()
-
-
-    def __object_deleted_event (self, event):
-        object = event.object
-
-        # Delete the actual object from its parent
-        object.getParent()._children.remove(object)
-
-        self.makeDirty()
-
-
-
-    def __OnConnectTo(self, event):
-        conn = event.connection
-        try:
-            tempDO = self.connections.getConnection(conn, 'object')
-            self.dispatchEvent('ConnectionEstablished',connection=conn)
-            self.dispatchEvent('Disable:Connect:%s' % conn)
-        except:
-            print u_("Unable to connect to %s") % conn
-
-
-    # ---------------------------------------------------------------
-    #
-    # ---------------------------------------------------------------
-    def _OnSave(self, event):
-        if not len(self._path):
-            self._OnSaveAs(event)
-        else:
-            self.save()
-
-
-    def _OnSaveAs(self, event):
-        wildcards = []
-        # Make the "default" file extension for a tool
-        # appear before the other extensions.
-        filterIndex = [self.properties.defaultFileExtension]
-        wildcards += [
-         ( self.properties.defaultFileExtension,
-           
self.properties.fileExtensions[self.properties.defaultFileExtension]) ]
-
-        for type in self.properties.fileExtensions.keys():
-            if type != self.properties.defaultFileExtension:
-                wildcards += [
-                   ( type, self.properties.fileExtensions[type]) ]
-                filterIndex.append(type)
-
-        path = self.app.ui.dialogSaveFile(
-                    u_("Save %s As...") % self.properties.description,
-                    wildcards=wildcards,
-                    parentWindow=self.ui)
-
-        if path:
-            if os.path.isfile(path):
-                overwrite = self.app.ui.dialogYesNo(
-                      u_('The file "%s".\n' % path) +
-                      u_("exists. Overwrite?"),
-                      u_("Unsaved Changes"),
-                      icon="warn", parentWindow=self.ui)
-                if not overwrite:
-                    self.OnSaveAs(event)
-                    return
-
-            self._path = path
-            self.ui.setTitle (self._path)
-            self.save()
-
-
-
-    def _OnClose(self, event):
-        if self.isDirty():
-            save = self.app.ui.dialogYesNoCancel(
-                    u_("This document has unsaved changes.\n") +
-                    u_("Save changes before closing?"),
-                    u_("Unsaved Changes"), icon="warn", parentWindow=self.ui)
-            if save == True:
-                self.OnSave(event)
-            elif save == -1:
-                event.Veto()
-                return
-
-        RuntimeSettings.saveRuntimeSettings(self)
-        self.app.mru.removeMenu(
-             self.menubar.getMenu('File|Open Recent|'), self)
-        self.app.removeDocument(self)
-        self.dispatchEvent('DocumentClosing')
-        self.ui.close()
-
-
-    # ---------------------------------------------------------------
-    #
-    # ---------------------------------------------------------------
-    def loadWizards(self, package):
-        templates = []
-
-        basedir = os.path.dirname(package.__file__)
-        processed = []  # Base file names processed (e.g., base of Simple.py*
-                      # is Simple) This will keep us from importing Simple
-                      # three times if Simple.py, Simple.pyc, and Simple.lib
-                      # all exist.
-
-        for dir in dircache.listdir(basedir):
-            base = dir.split('.')[0]
-            if not dir[0] in ('.','_') and not base in processed:
-                processed.append(base)
-                try:
-                    templates.append(dyn_import(
-                       '%s.%s' % (package.__name__,base)).TemplateInformation)
-                except ImportError, mesg:
-                    assert gDebug(2,
-                       "%s.%s doesn't appear to be a valid wizard" % (
-                       package.__name__, base))
-                    assert gDebug(5,' --> %s' % (mesg))
-                except AttributeError:
-                    assert gDebug(2,'Wizard %s for package %s is missing'
-                             ' a \'TemplateInformation\' attribute.' %
-                                     (base,package.__name__))
-
-        for template in templates:
-            try:
-                location = template['MenuLocation']
-                try:
-                    location, translation, grouping = location
-                    grouping = float(grouping)
-                except:
-                    location, translation = location
-                    grouping = 499.0
-
-                if location:
-                    self.wizardRunner(template, self)
-                    self.menubar.addAction(location=location, text=translation,
-                                            event='Wizard:%s' % (
-                                                 template['BaseID']),
-                                            grouping=grouping,
-                                            canDisable=True,
-                                            eventdata={'template':template},
-                                            help=template['Description'])
-            except ValueError:
-                continue
-
-
-
-# =================================================================
-# GObject Hooks
-# =================================================================
-def add_GObject_hooks(object, document):
-    """
-    Capture the _setItemHook event, so that setting atttributes like:
-
-          gobject['text'] = newtext
-
-    will automatically cause ObjectModified events to fire.
-
-    Also, add a .dispatch_designer_event method that calls the
-    Document.dispatchEvent method, automatically passing in
-    object=self
-
-    """
-    object._dispatch_designer_event = document.dispatchEvent
-    object.dispatch_designer_event = new.instancemethod(
-                  _gobject_dispatch_event, object, object.__class__)
-    object._setItemHook = new.instancemethod(_gobject_set_item_hook,
-                                             object,
-                                             object.__class__)
-
-    object.gparser_definition = \
-         document.incubator.elements[object._type[2:].lower()]
-
-
-def _gobject_dispatch_event(self, event, **params):
-    params['object'] = self
-    if not params.has_key('originator'):
-       params['originator'] = '__inline__'
-    self._dispatch_designer_event(event, **params)
-
-
-def _gobject_set_item_hook(self, key, value):
-    """
-    Hook into the GObject._setItemHook
-
-    Here, "self" is any arbitrary GObject.
-    """
-    dict_key = key.replace(':','__')
-    try:
-        old_values = {key: object.__dict__[dict_key]}
-    except KeyError:
-        old_values = {}
-
-    self.__dict__[dict_key] = value
-    self._dispatch_designer_event('ObjectModified',
-         object = self, new={key:value}, old=old_values,
-         originator = '__inline__')
-
-
-
-# =================================================================
-# Helper class used by the tool-specific packages
-# =================================================================
-class ModuleProperties:
-    xmlOpeningTag = 'undefined'
-    short = 'undefined'
-    application = 'GNUe Tool'
-    description = 'undefined'
-    fileExtensions = {}
-    defaultFileExtension = 'undefined'

Copied: trunk/gnue-designer/src/base/document.py (from rev 8916, 
trunk/gnue-designer/src/base/Document.py)
===================================================================
--- trunk/gnue-designer/src/base/Document.py    2006-10-24 05:49:19 UTC (rev 
8916)
+++ trunk/gnue-designer/src/base/document.py    2006-10-25 23:59:35 UTC (rev 
8929)
@@ -0,0 +1,891 @@
+# GNU Enterprise Designer - Basic Framework
+#
+# Copyright 2001-2006 Free Software Foundation
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+"""
+This is the base instance class for a designer session. Every
+open file will be associated with its own document instance.
+"""
+
+__all__ = ['BaseDocument']
+
+# -----------------------------------------------------------------
+# System imports
+# -----------------------------------------------------------------
+import sys
+import os
+import time
+import dircache
+import new
+
+# -----------------------------------------------------------------
+# GNUe Imports
+# -----------------------------------------------------------------
+from gnue.common.apps import GDebug
+from gnue.common.apps import RuntimeSettings
+from gnue.common.utils.FileUtils import dyn_import
+from gnue.common.events import EventController, Event
+
+from gnue.designer.base.MenuBar import MenuBar
+from gnue.designer.base.UndoManager import UndoManager
+from gnue.designer.base.tools import TriggerEditor
+from gnue.designer.base.ToolBase import ToolBase
+from gnue.designer.base.ObjectList import ObjectList
+from gnue.designer.base import TemplateBase
+from gnue.designer.base.TemplateParser import WizardRunner
+from gnue.designer import VERSION, PACKAGE as TITLE
+
+from gnue.designer.app.documents import document_types_valid
+
+
+# ===================================================================
+# Base document class
+# ===================================================================
+class BaseDocument(EventController):
+
+
+    # ===============================================================
+    # Virtual functions (Override these functions in your Instance)
+    # ===============================================================
+    wizardRunner = WizardRunner
+
+    def init(self):
+        """
+        initialize the instance (called at the
+        beginning of the __init__ process)
+        """
+
+    def init(self):
+        """
+        Finalize the instance (called at the
+        end of the __init__ process)
+        """
+
+    def loadFile(self, buffer):
+        """
+        Called to load the object from a file buffer/handle
+        """
+        return None
+
+    def loadEmpty(self, style=None):
+        """
+        Called to load an "empty" (new) object.  Create the root
+        object and any initial child objects (if appropriate)
+        """
+        return None
+
+    def inventoryObject(self, object):
+        """
+        Called in a tree-like fashion for every object
+        whether loaded in the beginning or later added.
+        """
+        pass
+
+    def preSave(self):
+        """
+        Called just before saving the file using GObject's dumpTree
+        You might do some sanity checks, etc.
+        """
+        return
+
+    def createTools(self):
+        """
+        Add any ToolBase instances
+        """
+        pass
+
+    def createEditors(self):
+        """
+        Add any EditorComponent instances
+        """
+        pass
+
+    def createWizards(self):
+        """
+        Add any runtime-loadable wizards/tools
+        """
+        pass
+
+    def initMenu(self):
+        """
+        Add any tool-specific functions to the menu bar
+        """
+        pass
+
+    def initToolBar(self):
+        """
+        Add any tool-specific functions to the tool bar
+        """
+        pass
+
+
+    def buildWizardCurrentDict(self):
+        """
+        Used by TemplateParser to build a wizard.current dict
+        """
+        return {'object': self._currentObject}
+
+
+    # ===============================================================
+    # Public Functions
+    # ===============================================================
+
+
+    # ---------------------------------------------------------------
+    # Register interface elements
+    # ---------------------------------------------------------------
+    def addTool(self, id, title, baseclass, hotkey=None, menuGroup=499):
+        """
+        Add a ToolBase instance
+        """
+        self._toolCache.append((id, title, baseclass, hotkey, menuGroup))
+
+
+    def registerEditor(self, baseclass, gtype, filter=None):
+        """
+        Register an editor class
+
+        Parameters:
+
+          baseclass: An EditorComponent class
+
+          gtype: A string indicating a GObject._type identifier,
+             or a list of such strings.
+
+          filter: A function that is passed a GObject and should
+             return True/False indicating if an editor instance
+             should be created.
+
+        """
+        if isinstance(gtype,basestring):
+            gtype = [gtype]
+        for gtype1 in gtype:
+            self._editorMapping[gtype1] = (filter, baseclass)
+
+
+    # ---------------------------------------------------------------
+    # Set the saved/unsaved status
+    # ---------------------------------------------------------------
+
+    def save(self):
+
+        if self.preSave():
+            print "Not saving definition"
+            return
+
+        location = self._path
+        fileHandle = None
+        fileHandle2 = None
+        if self._makeBackup:
+            try:
+                fileHandle = open(location,'r')
+                fileHandle2 = open(location + "~",'w')
+                fileHandle2.writelines(fileHandle.readlines())
+            except:
+                pass
+            else:
+                if fileHandle != None:
+                    fileHandle.close()
+                if fileHandle2 != None:
+                    fileHandle2.close()
+
+        self._makeBackup = 0
+
+        fileHandle = open(location,'w')
+
+        fileHandle.write('<?xml version="1.0" encoding="UTF-8"?>\n\n')
+
+        for comment in self.rootObject._rootComments:
+            if comment.find(TITLE) > 0:
+                self.rootObject._rootComments.remove(comment)
+
+        # Place a timestamp in the XML as a comment
+        # TODO: Replace with Dublin Core?
+        fileHandle.write(('<!--  %s (%s)\n%s      Saved on: %s  -->\n\n' \
+           % (TITLE, VERSION, (len(self.wizardName) and (
+               "      Created by " + self.wizardName + "\n") or ""),\
+              time.strftime("%Y-%m-%d %H:%M:%S",
+              time.localtime(time.time())))).encode('UTF-8'))
+
+        fileHandle.write(''.join(["<!--%s-->\n\n" % comment.encode('UTF-8') \
+                         for comment in self.rootObject._rootComments]))
+
+        
fileHandle.write(self.rootObject.dumpXML(treeDump=True).encode('UTF-8'))
+        fileHandle.close()
+
+        self.app.mru.addLocation(location)
+        self.makeClean()
+
+
+    # Mark our form as "dirty" (unsaved changes)
+    def makeDirty(self):
+        if not self._isdirty:
+            self._isdirty = True
+            if self._path == "":
+                self.ui.setTitle( u_("Untitled %s*") % 
self.properties.nickname)
+            else:
+                self.ui.setTitle(self._path + "*")
+        self.dispatchEvent('MakeDirty')
+
+
+    # Mark our form as "clean" (no unsaved changes)
+    def makeClean(self):
+        self._isdirty = 0
+        self._isnew = 0
+        if self._path == "":
+            self.ui.setTitle( u_("Untitled %s") % self.properties.nickname)
+        else:
+            self.ui.setTitle( self._path)
+        self.dispatchEvent('MakeClean')
+
+
+    # ---------------------------------------------------------------
+    # GObject convenience methods
+    # ---------------------------------------------------------------
+    def getNextGenericName (self, type):
+        return self.getUniqueName(type.capitalize() + '1')
+
+
+    def getUniqueName(self, name, limitingObject=None):
+
+        try:
+            usedNames = limitingObject.usedNames
+        except:
+            usedNames = self.usedNames
+
+        if name.lower() not in usedNames:
+            usedNames.append(name.lower())
+            return name
+
+        index = len(name) - 1
+
+        while index > 0 and '0' <= name[index] <= '9':
+            index -= 1
+
+        index += 1
+        if index >= len(name):
+            start = 1
+            base = name
+        else:
+            start = int(name[index:])
+            base = name[:index]
+
+        while ("%s%s" % (base, start)).lower() in usedNames:
+            start += 1
+
+        rv = "%s%s" % (base, start)
+        usedNames.append(rv.lower())
+        if rv.lower() not in self.usedNames:
+            self.usedNames.append(rv.lower())
+        return rv
+
+
+    # ---------------------------------------------------------------
+    # Return, or create, an ObjectList based on the xml tag
+    # ---------------------------------------------------------------
+    def getObjectList(self, tag):
+        try:
+            return self.objectLists[tag]
+        except KeyError:
+            defin = self.incubator.elements[tag]
+            baseClass = defin['BaseClass']
+
+            # Determine the "name" attribute"
+            nameAttr = None
+            try:
+                if defin['Attributes'].has_key('name'):
+                    nameAttr = 'name'
+                else:
+                    for attribute, props in defin['Attributes'].items():
+                        try:
+                            if props['Unique']:
+                                nameAttr = attribute
+                                break
+                        except KeyError:
+                            pass
+            except KeyError:
+                pass
+
+            list = ObjectList(self, baseClass, nameAttr)
+            self.objectLists[tag] = list
+            return list
+
+
+    # ================================================================
+    # Private functions
+    # ================================================================
+
+    def __init__(self, app, properties, location=None,
+                 buffer=None, style=None):
+        EventController.__init__(self)
+
+        self.app = app
+        self.properties = properties
+
+        # During startup, we will cache all events
+        # so we can execute them when everything has
+        # been initialized.
+        self.startCachingEvents()
+
+        self.ui = app.ui.createInstance(self)
+
+        # Local variables
+        self.wizardName = ""
+        self._isdirty = False
+        self._makeBackup = True
+        self._isNew = True
+        self.connections = app.connections
+        self.nameMappings = {}
+        self.usedNames = []
+
+        # Create the supplemental tools
+        self._toolCache = []
+        self._editorMapping = {}
+        self._pages = []
+        self.objectLists = {}
+        self._path = ""
+
+        self.globalAccelerators = []
+        self.globalAcceleratorListeners = []
+
+        self._nameMappers = {} # {GDataSource: {'name': [(GFBlock,'name')]}}
+
+
+        self.registerEventListeners({
+                           # Menu/Toolbar stuff
+                           'RequestSave'         : self._OnSave,
+                           'RequestSaveAs'       : self._OnSaveAs,
+                           'RequestClose'        : self._OnClose,
+
+                           # Object stuff
+                           'ObjectSelected'      : 
self.__object_selected_event,
+                           'ObjectCreated'       : self.__object_created_event,
+                           'ObjectModified'      : 
self.__object_modified_event,
+                           'ObjectDeleted'       : self.__object_deleted_event,
+                          })
+
+
+        # Call the document-specific init method
+        self.init()
+
+        # Register ourself with RuntimeSettings
+        RuntimeSettings.init(configFilename="gnue-des.ini",
+                             homeConfigDir=".gnue")
+        RuntimeSettings.registerInstance(self)
+
+        # Tell RuntimeSettings that we have information to save
+        self.runtime_section = self.properties.nickname + 'Layout'
+        RuntimeSettings.registerRuntimeSettingHandler(self, self)
+
+        # And the "Most Recenty Used" manager
+        RuntimeSettings.registerRuntimeSettingHandler(self, app.mru)
+
+        # Set up the Undo/Redo Manager
+        UndoManager(self)
+
+        # Load any files specified on the command
+        # line, or create a new document
+        if location == None:
+
+            if buffer != None:
+                self.__loadFromBuffer(buffer)
+                self.makeDirty()
+            else:
+                self.__createEmptyInstance(style)
+
+        else:
+            if not os.access (location, os.R_OK):
+                self.show()
+                if not self.app.ui.dialogYesNo(
+                  u_('The requested file does not exist.\n') +
+                  u_('Do you want to create this file?') +
+                  u_('\n\nFile: %s') \
+                    % location, u_("File Not Found"), self.ui):
+                    # TODO: Is this right?
+                    sys.exit()
+                self.hide()
+                self.__createEmptyInstance(style)
+                self._path = location
+                self.makeDirty()
+
+            elif not os.access (location, os.W_OK):
+                self.show()
+                if not self.app.ui.dialogCancel(
+                  u_('The requested file is Read Only.\n') +
+                  u_('To save any changes, you will \n') +
+                  u_('be required to do a "Save As..."\n\nFile: %s') \
+                    % location, u_("Read Only Warning"), self.ui) :
+                    # TODO: Is this right?
+                    sys.exit()
+                self.hide()
+                self.__loadFromFile(location)
+            else:
+                self.__loadFromFile(location)
+
+        self.menubar = MenuBar(self)
+
+
+        gStartupStatus(u_('Creating User Interface'))
+
+        # Set up the menu system
+        #   ... our common menu
+        self._initMenu()
+        #   ... and the document-centric menu
+        self.initMenu()
+
+        self.createWizards()
+
+        # Set up the editor components...
+        #   ... common
+        self.registerEditor(TriggerEditor.TriggerEditor, 'GCTrigger',
+                            TriggerEditor.EditorFilter)
+        #   ... and document-centric
+        self.createEditors()
+
+        # Create the document-centric tools
+        self.createTools()
+
+        # And tell the UI driver to create the UI portions
+        self.ui.initTools()
+
+        # Finalize menu bar
+        self.menubar.finalize()
+        self.app.mru.addMenu(self.menubar.getMenu('File|Open Recent|'), self)
+
+        self.toolbar = self.ui.toolbar
+        self.initToolBar()
+
+        # TODO: This is a hack to disable any menu items
+        # TODO: for actions we've yet to implement
+        for action in ('RequestRevert','RequestRedo','RequestCopy',
+                       'RequestPaste','RequestPasteSpecial','RequestCut'):
+            self.dispatchEvent('Disable:%s' % action)
+
+
+        # Add ourselve to the main app's instance list
+        self.app.addDocument(self)
+
+
+        self.dispatchEvent('ObjectSelected', originator=self,
+                           object=self.rootObject)
+
+        # Inventory the objects
+        gStartupStatus(u_('Inventorying Document Objects'))
+        self.rootObject.walk(self.__inventory)
+
+        self.finalize()
+        self.ui.finalize()
+
+        self.stopCachingEvents()
+
+
+    def _initMenu(self):
+        # Add the [sub]menus
+        for location, text, grouping in (
+              ('File', u_('&File'), 100),
+              ('File|New', u_('&New'), 100),
+              ('File|Open Recent', u_('&Open Recent'), 200.1),
+              ('File|Connect To', u_('&Connect To'), 400),
+              ('Edit', u_('&Edit'), 200),
+              ('Insert',u_('&Insert'), 300),
+              ('Modify',u_('&Modify'), 400),
+              ('Tools',u_('&Tools'), 500),
+              ('View',u_('&View'), 800),
+              ('Help',u_('&Help'), 999)):
+
+            self.menubar.addMenu(location, text, grouping)
+
+        for location, event, text, hotkey, help, grouping in (
+           ('File', 'RequestOpen', u_('&Open'), 'Ctrl+O',
+                u_("Open an existing document"), 200.1),
+           ('File|Open Recent', 'XXXX', u_('&Foo'), None,
+                u_("This is a placeholder for the Open Recent menu"), 200.1),
+           ('File|New', 'RequestNewWizard', u_('From &Wizard...'), None,
+                u_("Create a new document using a wizard"), 900.1),
+           ('File', 'RequestSave', u_("&Save"), 'Ctrl+S',
+                u_("Save the current document"),300.1),
+           ('File', 'RequestSaveAs', u_("Save &As..."),None,
+                u_("Save the current document under a new name"), 300.2),
+           ('File', 'RequestSaveAll', u_("Save A&ll"),None,
+                u_("Save all open document"),300.3),
+           ('File', 'RequestRevert', u_("Reload"), None,
+                u_("Reload the current document as of its last save " + \
+                   "(abandoning any changes)"), 500),
+           ('File', 'RequestClose', u_("&Close"), 'Ctrl+W',
+                u_("Close the current document"), 990),
+           ('File', 'RequestExit', u_("E&xit"), None,
+                u_("Exit GNUe Designer"), 995),
+           ('Edit', 'RequestUndo', u_("&Undo"), 'Ctrl+Z',
+                u_("Undo the last action"), 100.1),
+           ('Edit', 'RequestRedo', u_("&Redo"), 'Ctrl+Y',
+                u_("Redo the last undo action"), 100.2),
+           ('Edit', 'RequestCut', u_("Cu&t"), 'Ctrl+X',
+                u_("Cut the current object and move to the clipboard"), 200.1),
+           ('Edit', 'RequestCopy', u_("&Copy"), 'Ctrl+C',
+                u_("Copy the current object to the clipboard"), 200.2),
+           ('Edit', 'RequestPaste', u_("&Paste"), 'Ctrl+V',
+                u_("Paste the current object on the clipboard"), 200.3),
+           ('Edit', 'RequestPasteSpecial', u_("Paste &Special..."), None,
+                u_("Paste the current object on the clipboard " + \
+                   "with special attributes"), 200.4),
+           ('Modify','RequestDelete', u_("&Delete Item"), 'Delete',
+                u_("Delete the current object"),100),
+           ('Help', 'RequestAbout', u_("&About GNUe Designer"), None,
+                u_("More information about GNUe Designer"), 900),
+         ):
+            self.menubar.addAction(location, text, event,
+                            grouping, canDisable=True,
+                            icon=None, hotkey=hotkey, help=help)
+
+        # Add supported tools to File|New
+        for tool in document_types_valid:
+            self.menubar.addAction(
+                'File|New', '&%s' % tool.nickname,
+                'RequestNew', 100,
+                help=u_('Create a new %s') % tool.description,
+                eventdata={'type': tool.instance})
+
+        # Add connections
+        for conn in self.connections.getAllConnectionParameters().keys():
+            self.menubar.addAction('File|Connect To', conn,
+                     'Connect:%s' % conn,
+                     help=u_("Login to %s connection") % conn,
+                     eventdata={'connection': conn})
+            self.registerEventListeners(
+                  {'Connect:%s' % conn: self.__OnConnectTo})
+
+
+    def __loadFromFile(self, location):
+        try:
+            self._path = location
+            fileHandle = open(location,'r')
+            self.__loadFromBuffer(fileHandle)
+            fileHandle.close()
+            self.makeClean()
+            self._isNew = 0
+        except IOError, msg:
+            print "\n%s %s\n\nUnable to open file '%s'. \n" + \
+                  "Unexpected read error:\n  %s.\n" % (
+                         TITLE, VERSION, location, msg)
+            sys.exit()
+        self.app.mru.addLocation(location)
+
+
+    def addNameMapper(self, instance, attribute, childinst, childattr):
+        try:
+            instm = self._nameMappers[instance]
+        except KeyError:
+            instm = {}
+            self._nameMappers[instance] = instm
+        try:
+            attrm = instm[attribute]
+        except KeyError:
+            attrm = []
+            instm[attribute] = attrm
+        attrm.append ( (childinst, childattr) )
+
+
+    def __loadFromBuffer(self, fileHandle):
+        self.rootObject = self.loadBuffer(fileHandle)
+
+
+    def __createEmptyInstance(self, style):
+        self.rootObject = self.loadEmpty(style)
+        self.makeClean()
+        self._isNew = True
+
+
+    # ---------------------------------------------------------------
+    #
+    # ---------------------------------------------------------------
+    #
+    #  Used by RuntimeSettings
+    #
+    def saveRuntimeSettings(self):
+        return ( self.runtime_section, self.ui.getRuntimeSettings() )
+
+
+    # ---------------------------------------------------------------
+    #
+    # ---------------------------------------------------------------
+    # Do we need to be saved?
+    def isDirty(self):
+        return self._isdirty
+
+
+    # ---------------------------------------------------------------
+    #
+    # ---------------------------------------------------------------
+    # Take an object and mangle it all up
+    # until it is useful to us
+    def __inventory (self, object):
+
+        # Add a GObjectHelper to intercept __getitem__ calls on GObject
+        add_GObject_hooks(object, self)
+
+        if object != self.rootObject:
+
+            # Assign an ID if none exists
+            if hasattr(object, 'name'):
+                if object.name == None or object.name.startswith(object._type):
+                    object.name = self.getNextGenericName(object._type[2:])
+                self.nameMappings[object.name.lower()] = object
+                self.usedNames.append(object.name.lower())
+
+        # Do we create an EditorComponent instance?
+        if object._type in self._editorMapping.keys():
+            filter = self._editorMapping[object._type][0]
+            if filter is None or filter(object):
+                self.ui.createEditor(object,
+                      *self._editorMapping[object._type][1:])
+
+        # Now, give the tool-specific instances a chance
+        object.dispatch_designer_event('InventoryObject')
+        self.inventoryObject(object)
+
+
+    def __object_selected_event (self, event):
+        object = event.object
+        handler = event.originator
+        self._currentObject = object
+
+    def __object_created_event (self, event):
+        self.__inventory(event.object)
+        self.makeDirty()
+
+    def __object_modified_event (self, event):
+        object = event.object
+        # Check for any name dependencies
+        # (i.e., GFEntry is dependent on GFBlock.name and GFField.name)
+        # Automatically create any change events for the child objects
+        if hasattr(object, '_nameDependencies'):
+            for key in object._nameDependencies.keys():
+                masterattr, slaveattr = object._nameDependencies[key]
+                if masterattr in event.new.keys():
+                    key[slaveattr] = object[masterattr]
+
+        self.makeDirty()
+
+
+    def __object_deleted_event (self, event):
+        object = event.object
+
+        # Delete the actual object from its parent
+        object.getParent()._children.remove(object)
+
+        self.makeDirty()
+
+
+
+    def __OnConnectTo(self, event):
+        conn = event.connection
+        try:
+            tempDO = self.connections.getConnection(conn, 'object')
+            self.dispatchEvent('ConnectionEstablished',connection=conn)
+            self.dispatchEvent('Disable:Connect:%s' % conn)
+        except:
+            print u_("Unable to connect to %s") % conn
+
+
+    # ---------------------------------------------------------------
+    #
+    # ---------------------------------------------------------------
+    def _OnSave(self, event):
+        if not len(self._path):
+            self._OnSaveAs(event)
+        else:
+            self.save()
+
+
+    def _OnSaveAs(self, event):
+        wildcards = []
+        # Make the "default" file extension for a tool
+        # appear before the other extensions.
+        filterIndex = [self.properties.defaultFileExtension]
+        wildcards += [
+         ( self.properties.defaultFileExtension,
+           
self.properties.fileExtensions[self.properties.defaultFileExtension]) ]
+
+        for type in self.properties.fileExtensions.keys():
+            if type != self.properties.defaultFileExtension:
+                wildcards += [
+                   ( type, self.properties.fileExtensions[type]) ]
+                filterIndex.append(type)
+
+        path = self.app.ui.dialogSaveFile(
+                    u_("Save %s As...") % self.properties.description,
+                    wildcards=wildcards,
+                    parentWindow=self.ui)
+
+        if path:
+            if os.path.isfile(path):
+                overwrite = self.app.ui.dialogYesNo(
+                      u_('The file "%s".\n' % path) +
+                      u_("exists. Overwrite?"),
+                      u_("Unsaved Changes"),
+                      icon="warn", parentWindow=self.ui)
+                if not overwrite:
+                    self.OnSaveAs(event)
+                    return
+
+            self._path = path
+            self.ui.setTitle (self._path)
+            self.save()
+
+
+
+    def _OnClose(self, event):
+        if self.isDirty():
+            save = self.app.ui.dialogYesNoCancel(
+                    u_("This document has unsaved changes.\n") +
+                    u_("Save changes before closing?"),
+                    u_("Unsaved Changes"), icon="warn", parentWindow=self.ui)
+            if save == True:
+                self.OnSave(event)
+            elif save == -1:
+                event.Veto()
+                return
+
+        RuntimeSettings.saveRuntimeSettings(self)
+        self.app.mru.removeMenu(
+             self.menubar.getMenu('File|Open Recent|'), self)
+        self.app.removeDocument(self)
+        self.dispatchEvent('DocumentClosing')
+        self.ui.close()
+
+
+    # ---------------------------------------------------------------
+    #
+    # ---------------------------------------------------------------
+    def loadWizards(self, package):
+        templates = []
+
+        basedir = os.path.dirname(package.__file__)
+        processed = []  # Base file names processed (e.g., base of Simple.py*
+                      # is Simple) This will keep us from importing Simple
+                      # three times if Simple.py, Simple.pyc, and Simple.lib
+                      # all exist.
+
+        for dir in dircache.listdir(basedir):
+            base = dir.split('.')[0]
+            if not dir[0] in ('.','_') and not base in processed:
+                processed.append(base)
+                try:
+                    templates.append(dyn_import(
+                       '%s.%s' % (package.__name__,base)).TemplateInformation)
+                except ImportError, mesg:
+                    assert gDebug(2,
+                       "%s.%s doesn't appear to be a valid wizard" % (
+                       package.__name__, base))
+                    assert gDebug(5,' --> %s' % (mesg))
+                except AttributeError:
+                    assert gDebug(2,'Wizard %s for package %s is missing'
+                             ' a \'TemplateInformation\' attribute.' %
+                                     (base,package.__name__))
+
+        for template in templates:
+            try:
+                location = template['MenuLocation']
+                try:
+                    location, translation, grouping = location
+                    grouping = float(grouping)
+                except:
+                    location, translation = location
+                    grouping = 499.0
+
+                if location:
+                    self.wizardRunner(template, self)
+                    self.menubar.addAction(location=location, text=translation,
+                                            event='Wizard:%s' % (
+                                                 template['BaseID']),
+                                            grouping=grouping,
+                                            canDisable=True,
+                                            eventdata={'template':template},
+                                            help=template['Description'])
+            except ValueError:
+                continue
+
+
+
+# =================================================================
+# GObject Hooks
+# =================================================================
+def add_GObject_hooks(object, document):
+    """
+    Capture the _setItemHook event, so that setting atttributes like:
+
+          gobject['text'] = newtext
+
+    will automatically cause ObjectModified events to fire.
+
+    Also, add a .dispatch_designer_event method that calls the
+    Document.dispatchEvent method, automatically passing in
+    object=self
+
+    """
+    object._dispatch_designer_event = document.dispatchEvent
+    object.dispatch_designer_event = new.instancemethod(
+                  _gobject_dispatch_event, object, object.__class__)
+    object._setItemHook = new.instancemethod(_gobject_set_item_hook,
+                                             object,
+                                             object.__class__)
+
+    object.gparser_definition = \
+         document.incubator.elements[object._type[2:].lower()]
+
+
+def _gobject_dispatch_event(self, event, **params):
+    params['object'] = self
+    if not params.has_key('originator'):
+       params['originator'] = '__inline__'
+    self._dispatch_designer_event(event, **params)
+
+
+def _gobject_set_item_hook(self, key, value):
+    """
+    Hook into the GObject._setItemHook
+
+    Here, "self" is any arbitrary GObject.
+    """
+    dict_key = key.replace(':','__')
+    try:
+        old_values = {key: object.__dict__[dict_key]}
+    except KeyError:
+        old_values = {}
+
+    self.__dict__[dict_key] = value
+    self._dispatch_designer_event('ObjectModified',
+         object = self, new={key:value}, old=old_values,
+         originator = '__inline__')
+
+
+
+# =================================================================
+# Helper class used by the tool-specific packages
+# =================================================================
+class ModuleProperties:
+    xmlOpeningTag = 'undefined'
+    short = 'undefined'
+    application = 'GNUe Tool'
+    description = 'undefined'
+    fileExtensions = {}
+    defaultFileExtension = 'undefined'

Added: trunk/gnue-designer/src/base/parsertoobj.py
===================================================================
--- trunk/gnue-designer/src/base/parsertoobj.py 2006-10-25 16:22:31 UTC (rev 
8928)
+++ trunk/gnue-designer/src/base/parsertoobj.py 2006-10-25 23:59:35 UTC (rev 
8929)
@@ -0,0 +1,189 @@
+# GNU Enterprise Designer - Basic Framework
+#
+# Copyright 2001-2006 Free Software Foundation
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id: documents.py 8389 2006-04-07 02:44:20Z jcater $
+
+"""
+Take a GParser definition and create a Designer document model
+"""
+
+__all__ = ['create_proxy_definition']
+
+import copy
+import weakref
+import types
+
+from gnue.common.definitions.GParserHelpers import ParserObj
+
+
+class BaseObject(ParserObj):
+    """
+    This class is used by ProxyObjectFactory.
+    If used by itself, you will get plenty of
+    attribute errors as it depends on attributes
+    set on ProxyObject.
+    """
+
+    def __new__(cls, *args, **kwargs):
+        obj = object.__new__(cls, *args, **kwargs)
+
+
+    def __init__(self, parent=None, **kwargs):
+        """
+        """
+        # Set any initial attribute values
+        ParserObj.__init__(self, parent, self.__gobj_tag__)
+        self._attributes = self.__gobj_defaults__.copy()
+        for key, value in kwargs:
+            self._attributes[key] = value
+
+        self.parent = self._parent = weakref.proxy(parent)
+
+    def create_required_children(self):
+        """
+        Create any of the "required" child tags
+        """
+        for child_tag in self.__gobj_validchildren__:
+            if self.__gobj_tags__[child_tag].get('Required',False):
+                child = self.__gobj_tags__[child_tag]['BaseClass'](child)
+                child.create_required_children()
+
+
+    def __getitem__(self, name):
+        """
+        """
+        return self._attributes[name]
+
+
+    def __setitem__(self, name, value):
+        """
+        """
+        return self._attributes[name]
+
+
+    def get(self, name, default=None):
+        """
+        """
+        return self._attributes.get(name, default)
+
+
+
+# ===================================================================
+# Dynamic class
+# ===================================================================
+def ProxyObjectFactory():
+
+    # ---------------------------------------------------------------
+    class ProxyObject(BaseObject):
+
+        __gobj_defaults__ = {}
+        __gobj_tag__ = ''
+        __gobj_description__ = ''
+        __gobj_real_class__ = ''
+        __gobj_parenttags__ = ()
+        __gobj_validchildren__ = ()
+        __gobj_singleinstance__ = False
+        __gobj_required__ = False
+
+    # ---------------------------------------------------------------
+
+    return ProxyObject
+
+
+
+# ===================================================================
+# Create GObject classes from a GParser definition
+# ===================================================================
+def create_proxy_definition(definition):
+    tag_mappings = {}
+    tag_to_proxy = {}
+
+    for tag, tag_definition in definition.items():
+
+        tag_definition = copy.deepcopy(tag_definition)
+        # Build a reverse mapping from parent tags,
+        # indicating which child tags are valid for a tag.
+        for parent_tag in definition.get('ParentTags',[]):
+            if tag_mappings.has_key(parent_tag):
+                tag_mappings[parent_tag] = {'ValidChildren': [tag]}
+            else:
+                tag_mappings[parent_tag]['ValidChildren'].append(tag)
+
+        if tag_mappings.has_key(tag):
+            tag_mappings[tag].update(tag_definition)
+            tag_definition = tag_mappings[tag]
+        else:
+            tag_mappings[tag] = tag_definition
+            tag_definition['ValidChildren'] = []
+
+
+        base_class = ProxyObjectFactory()
+
+        base_class.__gobj_defaults__ = defaults = {}
+        base_class.__gobj_tag__ = tag
+        base_class.__gobj_real_class__ = _get_class_importable_name(
+                  tag_definition['BaseClass'])
+
+        for key, values in tag_definition.items():
+            if key not in ('Attributes'):
+                setattr(base_class,
+                        '__gobj_%s__' % key.lower().replace('-','_'),
+                        values)
+
+        tag_definition['BaseClass'] = base_class
+
+        # This creates a circular reference, but that's okay
+        # given this is very static over the lifetime of a running app.
+        base_class.__gobj_tags__ = tag_mappings
+
+
+    return tag_mappings
+
+
+# ===================================================================
+# Helpers
+# ===================================================================
+def _get_class_importable_name(obj, *args):
+    """
+    Take a class definition and create a string that can be
+    eval'd to return the original class.
+    """
+
+    if type(obj) in (types.ClassType, types.FunctionType, types.TypeType):
+        return '%s.%s' % (obj.__module__, obj.__name__)
+    else:
+        return str(obj)
+
+
+
+# ===================================================================
+# Testing/Development
+# ===================================================================
+if __name__ == '__main__':
+    # Test using form definition
+    from gnue.forms.GFParser import getXMLelements
+    create_proxy_definition(getXMLelements())
+
+    from gnue.designer.standalone.gfd import getXMLelements
+    create_proxy_definition(getXMLelements())
+
+
+

Modified: trunk/gnue-designer/src/forms/document.py
===================================================================
--- trunk/gnue-designer/src/forms/document.py   2006-10-25 16:22:31 UTC (rev 
8928)
+++ trunk/gnue-designer/src/forms/document.py   2006-10-25 23:59:35 UTC (rev 
8929)
@@ -37,7 +37,7 @@
 # ---------------------------------------------------------------------------
 # GNUe Imports
 # ---------------------------------------------------------------------------
-from gnue.designer.base.Document import BaseDocument
+from gnue.designer.base.document import BaseDocument
 from gnue.designer.base import PopupMenu
 from gnue.designer.base.ObjectList import ObjectList
 from gnue.designer.base.PopupMenu import ObjectMenu
@@ -313,18 +313,18 @@
     # =========================================================================
     # Public methods specific to a Forms document
     # =========================================================================
-    def find_gflabel_for(self, name): 
-        labels = self.rootObject.findChildrenOfType('GFLabel', 
+    def find_gflabel_for(self, name):
+        labels = self.rootObject.findChildrenOfType('GFLabel',
                          allowAllChildren=True)
-                         
+
         results = []
         append = results.append
-        
-        for label in labels: 
-           if hasattr(label,'for') and label['for'] == name: 
+
+        for label in labels:
+           if hasattr(label,'for') and label['for'] == name:
                append(label)
         return results
-           
+
     # =========================================================================
     # Private methods
     # =========================================================================

Added: trunk/gnue-designer/src/standalone/__init__.py
===================================================================

Added: trunk/gnue-designer/utils/package_standalone_definitions.py
===================================================================
--- trunk/gnue-designer/utils/package_standalone_definitions.py 2006-10-25 
16:22:31 UTC (rev 8928)
+++ trunk/gnue-designer/utils/package_standalone_definitions.py 2006-10-25 
23:59:35 UTC (rev 8929)
@@ -0,0 +1,178 @@
+# GNU Enterprise Designer - Utilities - Create standalone XML definitions
+#
+# Copyright 2006 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+"""
+This takes a GParser definition from a GNUe tool, and
+creates a .py file that extracts a standalone-version of the
+getXMLelements() dict that can be used by Designer so
+Designer can know the .
+
+Designer will check to see if a product is installed and
+use that definition intead of the standalone. It will simply
+fall-back to these pre-compiled ones.
+"""
+
+# ===================================================================
+default_files = (
+       ('gfd.py', 'gnue.forms.GFParser'),
+       ('grd.py', 'gnue.reports.GRParser'),
+       ('gld.py', 'gnue.appserver.gld.GLParser'),
+       ('gcd.py', 'gnue.appserver.gcd.GCParser'),
+    )
+# ===================================================================
+
+import sys
+import os
+import pprint
+import sys
+import types
+import __builtin__
+import copy
+
+from gnue.common.utils.FileUtils import dyn_import
+
+
+def _get_class_importable_name(obj, *args):
+    """
+    Take a class definition and create a string that can be
+    eval'd to return the original class.
+    """
+
+    if type(obj) in (types.ClassType, types.FunctionType, types.TypeType):
+        return '%s.%s' % (obj.__module__, obj.__name__)
+    else:
+        return str(obj)
+
+def _replace_classes(target):
+    """
+    This converts class/function instances (gnue.common.foo.bar)
+    with an eval'able string ('gnue.common.foo.bar')
+    """
+    if type(target) == types.DictType:
+        for key in target.keys():
+            target[key] = _replace_classes(target[key])
+        return target
+    elif type(target) in (types.ClassType, types.FunctionType,
+                            types.TypeType):
+        return _get_class_importable_name(target)
+    elif type(target) in (types.ListType, types.TupleType):
+        return [_replace_classes(t) for t in target]
+    else:
+        return target
+
+# ===================================================================
+#
+# ===================================================================
+def create_standalone_proxy_definition(module, outfile):
+    """
+    Designed to be run by the packaging scripts.
+    This takes a product's GParser definition and creates
+    a standalone version that Designer can use without requiring
+    that product to be installed.
+    """
+
+    # ------------------------------------------------------
+    # These classes replace the built-in _() and u_()
+    # by not actually translating the text and returning a
+    # pretty-printable represenation of themself. This way,
+    # i18n stays intact.
+
+    # This has to be done after all other gnue.* classes are
+    # imported.
+    class _u_string(unicode):
+        def __repr__(self):
+            return 'u_(%s)' % unicode.__repr__(self)
+
+    class ___string(unicode):
+        def __repr__(self):
+            return '_(%s)' % unicode.__repr__(self)
+
+    __builtin__.__dict__['u_'] = _u_string
+    __builtin__.__dict__['_'] = ___string
+    # ------------------------------------------------------
+
+    mod = dyn_import(module)
+
+    if not hasattr(mod, 'getXMLelements'):
+        print "%s does not define getXMLelements" % module
+        return
+
+    xml_elements = _replace_classes(copy.deepcopy(mod.getXMLelements()))
+
+    out = open(outfile,'w')
+
+    out.write("""
+        # GNU Enterprise Designer - Standalone File Format Stubs
+        #
+        # Copyright 2005-2006 Free Software Foundation
+        #
+        # This file is part of GNU Enterprise.
+        #
+        # GNU Enterprise is free software; you can redistribute it
+        # and/or modify it under the terms of the GNU General Public
+        # License as published by the Free Software Foundation; either
+        # version 2, or (at your option) any later version.
+        #
+        # GNU Enterprise is distributed in the hope that it will be
+        # useful, but WITHOUT ANY WARRANTY; without even the implied
+        # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+        # PURPOSE. See the GNU General Public License for more details.
+        #
+        # You should have received a copy of the GNU General Public
+        # License along with program; see the file COPYING. If not,
+        # write to the Free Software Foundation, Inc., 59 Temple Place
+        # - Suite 330, Boston, MA 02111-1307, USA.
+        #
+        # $Id$
+
+        # THIS FILE WAS AUTOMATICALLY GENERATED.
+        # DO NOT EDIT DIRECTLY.
+
+        definition = """.replace('\n        ','\n'))
+
+    pp = pprint.PrettyPrinter(indent=4)
+    out.write(pp.pformat(copy.deepcopy(xml_elements)))
+    out.write('\n\ndef getXMLelements(): return definition\n\n')
+    out.close()
+
+
+if __name__ == '__main__':
+
+    default_files = (
+       ('gfd.py', 'gnue.forms.GFParser'),
+       ('grd.py', 'gnue.reports.base.GRParser'),
+       ('gld.py', 'gnue.appserver.gld.GLParser'),
+       ('gcd.py', 'gnue.appserver.gcd.GCParser'),
+    )
+
+    if sys.argv[1:]:
+       create_standalone_proxy_definition(*sys.argv[1:])
+    else:
+        dest_path = os.path.join(os.path.join(*os.path.split(__file__)[:-1]),
+             '..','src','standalone')
+        for out, package in default_files:
+            print "Writing %s" % os.path.join(dest_path, out)
+            create_standalone_proxy_definition(package,
+                     os.path.join(dest_path, out))
+
+
+





reply via email to

[Prev in Thread] Current Thread [Next in Thread]