[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r6165 - in trunk/gnue-appserver: . po samples scripts src src/gld
From: |
johannes |
Subject: |
r6165 - in trunk/gnue-appserver: . po samples scripts src src/gld |
Date: |
Fri, 6 Aug 2004 13:29:26 -0500 (CDT) |
Author: johannes
Date: 2004-08-06 13:29:25 -0500 (Fri, 06 Aug 2004)
New Revision: 6165
Added:
trunk/gnue-appserver/samples/base-C.gld
trunk/gnue-appserver/scripts/gnue-readgld
trunk/gnue-appserver/src/gld/
trunk/gnue-appserver/src/gld/GLParser.py
trunk/gnue-appserver/src/gld/__init__.py
trunk/gnue-appserver/src/gld/readgld.py
trunk/gnue-appserver/src/labels.py
Modified:
trunk/gnue-appserver/po/de.po
trunk/gnue-appserver/samples/appserver.gpd
trunk/gnue-appserver/samples/base.gsd
trunk/gnue-appserver/scripts/
trunk/gnue-appserver/setup.cvs
Log:
Added first version of GNUe labels support
Modified: trunk/gnue-appserver/po/de.po
===================================================================
--- trunk/gnue-appserver/po/de.po 2004-08-06 12:22:18 UTC (rev 6164)
+++ trunk/gnue-appserver/po/de.po 2004-08-06 18:29:25 UTC (rev 6165)
@@ -536,7 +536,7 @@
#: geasSessionManager.py:39
msgid "Cannot find a session with ID '%s'"
-msgstr "Die Sitzung imt ID '%s' wurde nicht gefunden"
+msgstr "Die Sitzung mit ID '%s' wurde nicht gefunden"
#: language/Object.py:36
msgid "Class '%(classname)s' has no member '%(member)s'"
Modified: trunk/gnue-appserver/samples/appserver.gpd
===================================================================
--- trunk/gnue-appserver/samples/appserver.gpd 2004-08-06 12:22:18 UTC (rev
6164)
+++ trunk/gnue-appserver/samples/appserver.gpd 2004-08-06 18:29:25 UTC (rev
6165)
@@ -1,7 +1,9 @@
<?xml version="1.0"?>
<processes title="GNUe Application Server">
- <process title="Address Sample" id="sample">
+ <process title="Address Person" id="sample">
+ <step type="form" location="appserver://appserver/form/address_person"
+ title="Address Person"/>
<step type="form" location="./sample.gfd"
title="Address management"/>
<step type="report" location="./sample.grd"
Added: trunk/gnue-appserver/samples/base-C.gld
===================================================================
--- trunk/gnue-appserver/samples/base-C.gld 2004-08-06 12:22:18 UTC (rev
6164)
+++ trunk/gnue-appserver/samples/base-C.gld 2004-08-06 18:29:25 UTC (rev
6165)
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<labels module="gnue" language="C">
+
+ <class name="module">
+ <property name="name" pos="100" search="100" label="Name"/>
+ <property name="comment" pos="200" label="Comment"/>
+ </class>
+
+ <class name="class">
+ <property name="module" pos="100" label="Module"/>
+ <property name="name" pos="200" search="100" label="Name"/>
+ <property name="comment" pos="300" label="Comment"/>
+ </class>
+
+ <class name="property">
+ <property name="module" pos="100" label="Module"/>
+ <property name="class" pos="200" label="Class"/>
+ <property name="name" pos="300" search="100" label="Name"/>
+ <property name="type" pos="400" label="Type"/>
+ <property name="length" pos="500" label="Length"/>
+ <property name="scale" pos="600" label="Scale"/>
+ <property name="nullable" pos="700" label="Nullable"/>
+ <property name="comment" pos="800" label="Comment"/>
+ </class>
+
+ <class name="procedure">
+ <property name="module" pos="100" label="Module"/>
+ <property name="class" pos="200" label="Class"/>
+ <property name="name" pos="300" search="100" label="Name"/>
+ <property name="type" pos="400" label="Type"/>
+ <property name="length" pos="500" label="Length"/>
+ <property name="scale" pos="600" label="Scale"/>
+ <property name="nullable" pos="700" label="Nullable"/>
+ <property name="language" pos="800" label="Language"/>
+ <property name="comment" pos="900" label="Comment"/>
+ <property name="code" pos="1000" label="Code"/>
+ <property name="compiledcode" pos="1100" label="Compiled Code"/>
+ </class>
+
+ <class name="parameter">
+ <property name="procedure" pos="100" label="Procedure"/>
+ <property name="name" pos="200" search="100" label="Name"/>
+ <property name="type" pos="300" label="Type"/>
+ <property name="length" pos="400" label="Length"/>
+ <property name="scale" pos="500" label="Scale"/>
+ <property name="comment" pos="600" label="Comment"/>
+ </class>
+
+ <class name="label">
+ <property name="property" pos="100" label="Property" search="100"/>
+ <property name="procedure" pos="110" label="Procedure" search="110"/>
+ <property name="language" pos="200" label="Language"/>
+ <property name="page" pos="300" label="Page"/>
+ <property name="label" pos="400" label="Label"/>
+ <property name="position" pos="500" label="Position"/>
+ <property name="search" pos="600" label="search"/>
+ <property name="info" pos="700" label="info"/>
+ </class>
+</labels>
Modified: trunk/gnue-appserver/samples/base.gsd
===================================================================
--- trunk/gnue-appserver/samples/base.gsd 2004-08-06 12:22:18 UTC (rev
6164)
+++ trunk/gnue-appserver/samples/base.gsd 2004-08-06 18:29:25 UTC (rev
6165)
@@ -147,6 +147,37 @@
<pkfield name="gnue_id"/>
</primarykey>
</table>
+
+ <table name="gnue_label">
+ <fields>
+ <field name="gnue_id" description="Object ID" length="32" nullable="N"
+ type="string"/>
+ <field name="gnue_property" length="32" type="string"
+ description="The property the label belongs to"/>
+ <field name="gnue_procedure" length="32" type="string"
+ description="The procedure the label belongs to"/>
+ <field name="gnue_language" length="5" type="string" nullable="N"
+ description="The language (locale) of this item"/>
+ <field name="gnue_page" type="string" length="35"
+ description="Name of the page"/>
+ <field name="gnue_label" type="string" length="35"
+ description="The label of the item"/>
+ <field name="gnue_position" type="number" length="6"/>
+ <field name="gnue_search" type="number" length="6"/>
+ <field name="gnue_info" type="number" length="6"/>
+ </fields>
+ <indexes/>
+ <constraints>
+ <constraint name="fk_gnue_label_gnue_property" type="foreignkey">
+ <constraintfield name="gnue_property"/>
+ <constraintref name="gnue_id" table="gnue_property"/>
+ </constraint>
+ </constraints>
+ <primarykey name="pk_gnue_label_gnue_id">
+ <pkfield name="gnue_id"/>
+ </primarykey>
+ </table>
+
</tables>
<data>
<tabledata name="gnue_module_dump" tablename="gnue_module">
@@ -201,6 +232,12 @@
<value field="gnue_module">00000000000000000000000000000000</value>
<value field="gnue_name">property</value>
</row>
+ <row>
+ <value field="gnue_comment">GNU Enterprise Business Object
Label</value>
+ <value field="gnue_id">00000000000000000000000000000070</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">label</value>
+ </row>
</rows>
</tabledata>
<tabledata name="gnue_property_dump" tablename="gnue_property">
@@ -551,7 +588,181 @@
<value field="gnue_nullable">FALSE</value>
<value field="gnue_type">string</value>
</row>
+ <!-- ============================================================== -->
+ <!-- gnue_label -->
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">Object ID</value>
+ <value field="gnue_id">00000000000000000000000000000071</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">id</value>
+ <value field="gnue_nullable">FALSE</value>
+ <value field="gnue_type">id</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">The property the label belongs to</value>
+ <value field="gnue_id">00000000000000000000000000000072</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">property</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">gnue_property</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">The procedure the label belongs
to</value>
+ <value field="gnue_id">00000000000000000000000000000073</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">procedure</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">gnue_procedure</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">The language (locale) of this
item</value>
+ <value field="gnue_id">00000000000000000000000000000074</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">language</value>
+ <value field="gnue_nullable">FALSE</value>
+ <value field="gnue_type">string</value>
+ <value field="gnue_length">5</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">The tab order position of the
item</value>
+ <value field="gnue_id">00000000000000000000000000000075</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">position</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">number</value>
+ <value field="gnue_length">6</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">Name of the page</value>
+ <value field="gnue_id">00000000000000000000000000000076</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">page</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">string</value>
+ <value field="gnue_length">35</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">Label of the property</value>
+ <value field="gnue_id">00000000000000000000000000000077</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">label</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">string</value>
+ <value field="gnue_length">35</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">Search index of the label</value>
+ <value field="gnue_id">00000000000000000000000000000078</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">search</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">number</value>
+ <value field="gnue_length">6</value>
+ </row>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000070</value>
+ <value field="gnue_comment">Info index of the label</value>
+ <value field="gnue_id">00000000000000000000000000000079</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">info</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">number</value>
+ <value field="gnue_length">6</value>
+ </row>
</rows>
</tabledata>
+ <tabledata name="gnue_procedure_dump" tablename="gnue_procedure">
+ <definition>
+ <column field="gnue_class" type="string(32)"/>
+ <column field="gnue_code" type="string"/>
+ <column field="gnue_comment" type="string(70)"/>
+ <column field="gnue_compiledcode" type="string"/>
+ <column field="gnue_id" type="string(32)"/>
+ <column field="gnue_language" type="string(10)"/>
+ <column field="gnue_length" type="number(6)"/>
+ <column field="gnue_module" type="string(32)"/>
+ <column field="gnue_name" type="string(35)"/>
+ <column field="gnue_nullable" type="boolean"/>
+ <column field="gnue_scale" type="number(4)"/>
+ <column field="gnue_type" type="string(35)"/>
+ </definition>
+ <rows>
+ <row>
+ <value field="gnue_class">00000000000000000000000000000020</value>
+ <value field="gnue_comment">Generate GNUe Form Definition</value>
+ <value field="gnue_id"
key="Y">00000000000000000000000000007001</value>
+ <value field="gnue_language">python</value>
+ <value field="gnue_module">00000000000000000000000000000000</value>
+ <value field="gnue_name">form</value>
+ <value field="gnue_nullable">TRUE</value>
+ <value field="gnue_type">string</value>
+ <value field="gnue_code">
+ from gnue.appserver import labels
+ print "Generating forms-code for", language, connection
+
+ labels.find = find
+ labels.abort = abort
+
+ formGen = labels.FormGenerator (self, language, connection,
+ formwidth, formheight)
+
+ return formGen.generateForm ()
+ </value>
+ </row>
+ </rows>
+ </tabledata>
+ <tabledata name="gnue_parameter_dump" tablename="gnue_parameter">
+ <definition>
+ <column field="gnue_comment" type="string(70)"/>
+ <column field="gnue_id" type="string(32)"/>
+ <column field="gnue_length" type="number(6)"/>
+ <column field="gnue_name" type="string(35)"/>
+ <column field="gnue_procedure" type="string(32)"/>
+ <column field="gnue_scale" type="number(4)"/>
+ <column field="gnue_type" type="string(35)"/>
+ </definition>
+ <rows>
+ <row>
+ <value
field="gnue_procedure">00000000000000000000000000007001</value>
+ <value field="gnue_id"
key="Y">00000000000000000000000000770001</value>
+ <value field="gnue_name">language</value>
+ <value field="gnue_comment">Langage (locale) for labels</value>
+ <value field="gnue_length">5</value>
+ <value field="gnue_type">string</value>
+ </row>
+ <row>
+ <value
field="gnue_procedure">00000000000000000000000000007001</value>
+ <value field="gnue_id"
key="Y">00000000000000000000000000770002</value>
+ <value field="gnue_name">connection</value>
+ <value field="gnue_comment">Name of the connection to use</value>
+ <value field="gnue_length">35</value>
+ <value field="gnue_type">string</value>
+ </row>
+ <row>
+ <value
field="gnue_procedure">00000000000000000000000000007001</value>
+ <value field="gnue_id"
key="Y">00000000000000000000000000770003</value>
+ <value field="gnue_name">formwidth</value>
+ <value field="gnue_comment">Maximum width of the form</value>
+ <value field="gnue_type">number</value>
+ <value field="gnue_length">4</value>
+ </row>
+ <row>
+ <value
field="gnue_procedure">00000000000000000000000000007001</value>
+ <value field="gnue_id"
key="Y">00000000000000000000000000770004</value>
+ <value field="gnue_name">formheight</value>
+ <value field="gnue_comment">Maximum height of the form</value>
+ <value field="gnue_type">number</value>
+ <value field="gnue_length">4</value>
+ </row>
+ </rows>
+ </tabledata>
</data>
</schema>
Property changes on: trunk/gnue-appserver/scripts
___________________________________________________________________
Name: svn:ignore
- gacvs
ggcvs
gcdcvs
+ gacvs
ggcvs
gcdcvs
gldcvs
Added: trunk/gnue-appserver/scripts/gnue-readgld
===================================================================
--- trunk/gnue-appserver/scripts/gnue-readgld 2004-08-06 12:22:18 UTC (rev
6164)
+++ trunk/gnue-appserver/scripts/gnue-readgld 2004-08-06 18:29:25 UTC (rev
6165)
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+# Copyright 2001-2004 Free Software Foundation
+#
+# $Id$
+
+import os, sys
+
+if hasattr(sys, 'frozen'):
+ sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0])))
+
+from gnue.appserver.gld import readgld
+
+if __name__ == '__main__':
+ readgld.gldReader ().run ()
Property changes on: trunk/gnue-appserver/scripts/gnue-readgld
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Id
Modified: trunk/gnue-appserver/setup.cvs
===================================================================
--- trunk/gnue-appserver/setup.cvs 2004-08-06 12:22:18 UTC (rev 6164)
+++ trunk/gnue-appserver/setup.cvs 2004-08-06 18:29:25 UTC (rev 6165)
@@ -34,6 +34,7 @@
createShell ('gacvs', 'gnue-appserver')
createShell ('ggcvs', 'gnue-gsdgen')
createShell ('gcdcvs', 'gnue-gcd2sql')
+createShell ('gldcvs', 'gnue-readgld')
# Add our GNUe RPC resource files to the config directory...
createLink ('grpc/appserver.grpc','%s/share/gnue/grpc/appserver.grpc' %
CONFDIR, overwrite=1)
Property changes on: trunk/gnue-appserver/src/gld
___________________________________________________________________
Name: svn:ignore
+ *.pyc
Added: trunk/gnue-appserver/src/gld/GLParser.py
===================================================================
--- trunk/gnue-appserver/src/gld/GLParser.py 2004-08-06 12:22:18 UTC (rev
6164)
+++ trunk/gnue-appserver/src/gld/GLParser.py 2004-08-06 18:29:25 UTC (rev
6165)
@@ -0,0 +1,267 @@
+# GNU Enterprise Appserver - GNUe Label Definitions - XML-Parser
+#
+# Copyright 2001-2004 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: $
+
+from gnue.common.definitions import GParser, GObjects, GRootObj
+from gnue.common.definitions.GParserHelpers import GContent
+from gnue.common.formatting import GTypecast
+from gnue.appserver.classrep import helpers, Namespace
+
+xmlElements = None
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class Error (gException):
+ pass
+
+class NoModuleError (Error):
+ def __init__ (self, classname):
+ msg = u_("Class '%s' has no module") % classname
+ Error.__init__ (self, msg)
+
+class ModuleMismatchError (Error):
+ def __init__ (self, classname, module):
+ msg = u_("The class '%(class)s' mismatches the given module attribute "
+ "'%(module)s'") % {'class': classname, 'module': module}
+ Error.__init__ (self, msg)
+
+class RefStyleError (Error):
+ def __init__ (self, itemname):
+ msg = u_("Element '%s' can either have a search- or info-attribute.") \
+ % itemname
+ Error.__init__ (self, msg)
+
+# =============================================================================
+# load an XML object tree from a given stream and return it's root object
+# =============================================================================
+
+def loadFile (stream, initialize = True):
+ return GParser.loadXMLObject (stream, xmlSchemaHandler, 'GLLabels',
+ 'labels', initialize)
+
+
+# =============================================================================
+# Build a dictionary tree with all available XML elements
+# =============================================================================
+
+def getXMLelements ():
+ global xmlElements
+
+ if xmlElements is None:
+ xmlElements = {
+ 'labels': {
+ 'BaseClass' : GLLabels,
+ 'Required' : True,
+ 'Attributes': {
+ 'module': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'language': {
+ 'Required': True,
+ 'Typecast': GTypecast.text}
+ },
+ 'ParentTags': (None)
+ },
+
+ 'class': {
+ 'BaseClass': GLClass,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'page': {
+ 'Typecast': GTypecast.text},
+ },
+ 'ParentTags': ('layout',)
+ },
+
+ 'property': {
+ 'BaseClass': GLProperty,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'pos': {
+ 'Default' : 0,
+ 'Typecast': GTypecast.integer},
+ 'label': {
+ 'Typecast': GTypecast.text},
+ 'page': {
+ 'Typecast': GTypecast.text},
+ 'info': {
+ 'Typecast': GTypecast.integer},
+ 'search': {
+ 'Typecast': GTypecast.integer}
+ },
+ 'MixedContent' : True,
+ 'KeepWhitespace': True,
+ 'ParentTags' : ('class',)
+ },
+
+ 'procedure': {
+ 'BaseClass': GLProcedure,
+ 'Attributes': {
+ 'name': {
+ 'Required': True,
+ 'Unique' : True,
+ 'Typecast': GTypecast.name},
+ 'pos': {
+ 'Default' : 0,
+ 'Typecast': GTypecast.integer},
+ 'label': {
+ 'Typecast': GTypecast.text},
+ 'page': {
+ 'Typecast': GTypecast.text},
+ 'info': {
+ 'Typecast': GTypecast.integer},
+ 'search': {
+ 'Typecast': GTypecast.integer}
+ },
+ 'MixedContent' : True,
+ 'KeepWhitespace': True,
+ 'ParentTags' : ('class',)
+ },
+ }
+
+ return GParser.buildImportableTags ('layout', xmlElements)
+
+
+# =============================================================================
+# Class called by the XML parser to process the XML file
+# =============================================================================
+
+class xmlSchemaHandler (GParser.xmlHandler):
+ def __init__ (self):
+ GParser.xmlHandler.__init__ (self)
+ self.xmlElements = getXMLelements ()
+
+
+# =============================================================================
+# Base class for all GNUe Layout Definition classes
+# =============================================================================
+
+class GLObject (GObjects.GObj):
+ pass
+
+
+# =============================================================================
+# Base class for all objects with a type-attribute
+# =============================================================================
+
+class GLClassElement (GLObject):
+ def __init__ (self, parent = None, objType = None):
+ GLObject.__init__ (self, parent, type = objType)
+
+ self.module = None
+ self.fullName = None
+
+ self._inits.extend ([None, self._validate])
+
+
+ # ---------------------------------------------------------------------------
+ # If an instance has a type attribute, verify it
+ # ---------------------------------------------------------------------------
+
+ def _validate (self):
+ self.module = self.findParentOfType ('GLLabels').module
+ self.fullName = Namespace.createName (self.module, self.name)
+
+ if not hasattr (self, 'page'):
+ self.page = self._parent.page
+
+ if not hasattr (self, 'search'): self.search = None
+ if not hasattr (self, 'info'): self.info = None
+
+ if self.search is not None and self.info is not None:
+ raise RefStyleError, (self.fullName)
+
+ if self.search is not None:
+ self.info = None
+
+ if self.info is not None:
+ self.search = None
+
+
+
+# =============================================================================
+# The layout object, root object of a GLD tree
+# =============================================================================
+
+class GLLabels (GRootObj.GRootObj, GLObject):
+ def __init__ (self, parent = None):
+ GRootObj.GRootObj.__init__ (self, 'labels', getXMLelements,
self.__module__)
+ GLObject.__init__ (self, parent, type = 'GLLabels')
+
+
+# =============================================================================
+# The class object
+# =============================================================================
+
+class GLClass (GLObject):
+ def __init__ (self, parent):
+ GLObject.__init__ (self, parent, type = 'GLClass')
+ self.fullName = None
+ self.page = None
+ self._inits.extend ([None, self._validate])
+
+ # ---------------------------------------------------------------------------
+ # Validate a class definition
+ # ---------------------------------------------------------------------------
+
+ def _validate (self):
+ if not isinstance (self._parent, GLLabels):
+ raise NoModuleError, self.name
+
+ nameParts = self.name.split ('_')
+ if len (nameParts) > 1:
+ if hasattr (self, 'module') and self.module != nameParts [0]:
+ raise ModuleMismatchError, (self.name, self.module)
+
+ (self.module, self.name) = nameParts [:2]
+
+ if not hasattr (self, 'module'):
+ self.module = self._parent.module
+
+ self.fullName = Namespace.createName (self.module, self.name)
+
+
+# =============================================================================
+# The property object
+# =============================================================================
+
+class GLProperty (GLClassElement):
+ def __init__ (self, parent):
+ GLClassElement.__init__ (self, parent, objType = 'GLProperty')
+
+# =============================================================================
+# The procedure object
+# =============================================================================
+
+class GLProcedure (GLClassElement):
+ def __init__ (self, parent):
+ GLClassElement.__init__ (self, parent, objType = 'GLProcedure')
+
Property changes on: trunk/gnue-appserver/src/gld/GLParser.py
___________________________________________________________________
Name: svn:keywords
+ +Id
Added: trunk/gnue-appserver/src/gld/__init__.py
===================================================================
Added: trunk/gnue-appserver/src/gld/readgld.py
===================================================================
--- trunk/gnue-appserver/src/gld/readgld.py 2004-08-06 12:22:18 UTC (rev
6164)
+++ trunk/gnue-appserver/src/gld/readgld.py 2004-08-06 18:29:25 UTC (rev
6165)
@@ -0,0 +1,463 @@
+# GNU Enterprise Appserver - GNUe Label Definition - Import GLDs
+#
+# Copyright 2001-2004 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: $
+
+import sys
+import os
+import whrandom
+
+from gnue.common.apps import GClientApp, i18n
+from gnue.common.utils.FileUtils import openResource
+from gnue.common.datasources import GDataSource, GConditions
+
+from gnue.appserver import VERSION
+from gnue.appserver.gld import GLParser
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class Error (gException):
+ pass
+
+
+# =============================================================================
+#
+# =============================================================================
+
+class gldReader (GClientApp.GClientApp):
+
+ NAME = "gnue-readgld"
+ VERSION = VERSION
+ COMMAND = "gnue-readgld"
+ USAGE = "%s %s" % (GClientApp.GClientApp.USAGE, "file file ...")
+ SUMMARY = _("Read GNUe Layout Definitions and update the class repository")
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, connections = None):
+ self.addCommandOption ('connection', 'c', argument='connectionname',
+ help = _("Use the connection <connectionname> for creating the
schema"))
+
+ self.addCommandOption ('username', 'u', argument="user",
+ help = _("Set the username for the database. If the database is to be "
+ "created, this username will be it's owner."))
+
+ self.addCommandOption ('password', 'p', argument="password",
+ help = _("Set the password for the database."))
+
+ ConfigOptions = {}
+
+ GClientApp.GClientApp.__init__ (self, connections, 'gnue-readgld',
ConfigOptions)
+
+
+ # ---------------------------------------------------------------------------
+ # Verify the given commandline options
+ # ---------------------------------------------------------------------------
+
+ def __checkOptions (self):
+ """
+ This function checks wether the given command line arguments and options
+ are usefull or not.
+ """
+ self._args = [unicode (a, i18n.encoding) for a in self.ARGUMENTS]
+
+ if not len (self._args):
+ self.handleStartupError (_("No input file specified."))
+
+ try:
+ self._files = []
+
+ for filename in self._args:
+ self._files.append (openResource (filename))
+
+ except IOError:
+ self.handleStartupError (u_("Unable to open input file %s.") % filename)
+
+
+ if not self.OPTIONS ['connection']:
+ self.handleStartupError (_("No connection specified."))
+
+
+ # ---------------------------------------------------------------------------
+ # Open the needed datasources
+ # ---------------------------------------------------------------------------
+
+ def __openDatasources (self):
+ attributes = {'name' : "dts_gnueModule",
+ 'database': self.OPTIONS ['connection'],
+ 'table' : 'gnue_module'}
+ fieldList = ['gnue_id', 'gnue_name']
+
+ self._dtsModules = GDataSource.DataSourceWrapper (
+ connections = self.connections,
+ attributes = attributes,
+ fields = fieldList,
+ unicodeMode = True)
+
+ attributes = {'name' : "dts_gnueClass",
+ 'database': self.OPTIONS ['connection'],
+ 'table' : 'gnue_class'}
+ fieldList = ['gnue_id', 'gnue_name', 'gnue_module']
+
+ self._dtsClasses = GDataSource.DataSourceWrapper (
+ connections = self.connections,
+ attributes = attributes,
+ fields = fieldList,
+ unicodeMode = True)
+
+ attributes = {'name' : "dts_gnueProperty",
+ 'database': self.OPTIONS ['connection'],
+ 'table' : 'gnue_property'}
+ fieldList = ['gnue_id', 'gnue_name', 'gnue_module', 'gnue_class']
+
+ self._dtsProperty = GDataSource.DataSourceWrapper (
+ connections = self.connections,
+ attributes = attributes,
+ fields = fieldList,
+ unicodeMode = True)
+
+ attributes = {'name' : "dts_gnueProcedure",
+ 'database': self.OPTIONS ['connection'],
+ 'table' : 'gnue_procedure'}
+ fieldList = ['gnue_id', 'gnue_name', 'gnue_module', 'gnue_class']
+
+ self._dtsProcedure = GDataSource.DataSourceWrapper (
+ connections = self.connections,
+ attributes = attributes,
+ fields = fieldList,
+ unicodeMode = True)
+
+
+ attributes = {'name' : "dts_gnueLabel",
+ 'database': self.OPTIONS ['connection'],
+ 'table' : 'gnue_label'}
+ fieldList = ['gnue_id', 'gnue_property', 'gnue_language', 'gnue_position',
+ 'gnue_page', 'gnue_label', 'gnue_procedure', 'gnue_search',
+ 'gnue_info']
+
+ self._dtsLabel = GDataSource.DataSourceWrapper (
+ connections = self.connections,
+ attributes = attributes,
+ fields = fieldList,
+ unicodeMode = True)
+
+ # ---------------------------------------------------------------------------
+ # Main program
+ # ---------------------------------------------------------------------------
+
+ def run (self):
+ """
+ This is the main function of the whole process. It verifies the given
+ options, loads all layout definitions and then logs into the connection to
+ perform all actions requested.
+ """
+
+ self.__checkOptions ()
+ self.__openDatasources ()
+
+ try:
+ self.modules = {}
+ self.classes = {}
+
+ for item in range (len (self._files)):
+ print _("Loading gld file '%s' ...") % self._args [item]
+
+ try:
+ schema = GLParser.loadFile (self._files [item])
+ schema.walk (self.__iterateObjects)
+
+ finally:
+ self._files [item].close ()
+
+ except Exception:
+ raise
+
+ else:
+ self.updateRepository ()
+
+
+ # ---------------------------------------------------------------------------
+ # Iterate over all top level elements
+ # ---------------------------------------------------------------------------
+
+ def __iterateObjects (self, sObject):
+ """
+ This function iterates over all objects of a GCD tree and processes the
+ GCModule and GCClass instances.
+
+ @param sObject: current GLD object to be processed
+ """
+ if sObject._type == 'GLLabels':
+ self.__translateModule (sObject)
+
+ elif sObject._type == 'GLClass':
+ self.__translateClass (sObject)
+
+
+
+ # ---------------------------------------------------------------------------
+ # A module translates to a gnue_module data entry only
+ # ---------------------------------------------------------------------------
+
+ def __translateModule (self, aModule):
+ """
+ This function adds a dictionary for the given module to the modules data
+ block for later update of the class repository.
+
+ @param aModule: GLD Layout object to be processed.
+ """
+
+ mName = aModule.module
+ self.modules [mName] = self.fetchTags (aModule, ['language'])
+ self.modules [mName] ['gnue_id'] = self.__findModule (mName)
+
+
+ # ---------------------------------------------------------------------------
+ # A class translation needs a table creation/modification and a data entry
+ # ---------------------------------------------------------------------------
+
+ def __translateClass (self, aClass):
+ """
+ This function creates an entry for schema creation of the given class, as
+ well as a dictionary for the class repository update.
+
+ @param aClass: GLD Class object to be processed.
+ """
+
+ cDef = self.fetchTags (aClass, ['name', 'page'])
+ cDef ['module'] = self.modules [aClass.module]['gnue_id']
+ cDef ['gnue_id'] = self.__findClass (aClass.module, cDef ['name'])
+ cDef ['properties'] = []
+ cDef ['language'] = self.modules [aClass.module]['language']
+
+ self.classes [aClass.fullName] = cDef
+
+ # After processing the class definition, iterate over all it's items
+ aClass.walk (self.__iterateClassObjects, defs = cDef)
+
+
+ # ---------------------------------------------------------------------------
+ # Iterate over all elements of a class definition
+ # ---------------------------------------------------------------------------
+
+ def __iterateClassObjects (self, sObject, defs):
+ """
+ This function processes all child objects of a GLD class instance.
+
+ @param sObject: current GLD object to be processed
+ @param defs: a class definition dictionary
+ """
+
+ if sObject._type in ['GLProperty', 'GLProcedure']:
+ pDef = self.fetchTags (sObject, ['name', 'pos', 'page', 'label', 'info',
+ 'search'])
+ pDef ['module'] = self.__findModule (sObject.module)
+ pDef ['class'] = defs ['gnue_id']
+
+ if sObject._type == 'GLProperty':
+ pDef ['gnue_id'] = self.__findProperty (pDef)
+ pDef ['relation'] = 'gnue_property'
+ else:
+ pDef ['gnue_id'] = self.__findProcedure (pDef)
+ pDef ['relation'] = 'gnue_procedure'
+
+ defs ['properties'].append (pDef)
+
+
+
+ # ---------------------------------------------------------------------------
+ # Find a class by name and module
+ # ---------------------------------------------------------------------------
+
+ def __findClass (self, module, classname):
+ moduleId = self.modules [module]['gnue_id']
+ mc = GConditions.buildConditionFromDict ({'gnue_name' : classname,
+ 'gnue_module': moduleId})
+ rs = self._dtsClasses.createResultSet (mc)
+ if rs.firstRecord () is None:
+ raise ClassNotFoundError, (module, classname)
+ return rs.current.getField ('gnue_id')
+
+
+ # ---------------------------------------------------------------------------
+ # Find a module by name
+ # ---------------------------------------------------------------------------
+
+ def __findModule (self, module):
+ if self.modules.has_key (module) and \
+ self.modules [module].has_key ('gnue_id'):
+ return self.modules [module]['gnue_id']
+ else:
+ mc = GConditions.buildConditionFromDict ({'gnue_name': module})
+ rs = self._dtsModules.createResultSet (mc)
+ if rs.firstRecord () is None:
+ raise ModuleNotFoundError, (module)
+ return rs.current.getField ('gnue_id')
+
+
+ # ---------------------------------------------------------------------------
+ # Find a property by name, module- and class-id
+ # ---------------------------------------------------------------------------
+
+ def __findProperty (self, pDef):
+ mc = GConditions.buildConditionFromDict ({'gnue_module': pDef ['module'],
+ 'gnue_class': pDef ['class'],
+ 'gnue_name': pDef ['name']})
+ rs = self._dtsProperty.createResultSet (mc)
+ if rs.firstRecord () is None:
+ raise ModuleNotFoundError, (module)
+ return rs.current.getField ('gnue_id')
+
+
+ # ---------------------------------------------------------------------------
+ # Find a procedure by name, module- and class-id
+ # ---------------------------------------------------------------------------
+
+ def __findProcedure (self, pDef):
+ mc = GConditions.buildConditionFromDict ({'gnue_module': pDef ['module'],
+ 'gnue_class': pDef ['class'],
+ 'gnue_name': pDef ['name']})
+ rs = self._dtsProcedure.createResultSet (mc)
+ if rs.firstRecord () is None:
+ raise ProcedureNotFoundError, (pDef ['name'])
+ return rs.current.getField ('gnue_id')
+
+
+ # ---------------------------------------------------------------------------
+ # Get a dictionary with all keys listed in tags and values from sObject
+ # ---------------------------------------------------------------------------
+
+ def fetchTags (self, sObject, tags):
+ """
+ This function creates a dictionary with all attributes from sObject listed
+ in tags, where the keys are constructed by 'gnue_%s' % attributename.
+
+ @param sObject: Schema object to retriev attributes from
+ @param tags: list of all attributes to retrieve
+ @return: dictionary with the attribute names as keys and their values
+ """
+ res = {}
+ for item in tags:
+ if hasattr (sObject, item):
+ res [item] = getattr (sObject, item)
+ return res
+
+
+ # ---------------------------------------------------------------------------
+ # update the class repository
+ # ---------------------------------------------------------------------------
+
+ def updateRepository (self):
+ stat = [0, 0, 0] # inserted, updated, unchanged
+
+ for cDef in self.classes.values ():
+ for pDef in cDef ['properties']:
+ cond = {pDef ['relation']: pDef ['gnue_id'],
+ 'gnue_language' : cDef ['language']}
+
+ label = {pDef ['relation']: pDef ['gnue_id'],
+ 'gnue_language' : cDef ['language'],
+ 'gnue_position' : pDef ['pos'],
+ 'gnue_page' : pDef ['page'],
+ 'gnue_label' : pDef ['label']}
+
+ if pDef.has_key ('search'):
+ label ['gnue_search'] = pDef ['search']
+ if pDef.has_key ('info'):
+ label ['gnue_info'] = pDef ['info']
+
+ resultSet = self._dtsLabel.createResultSet (cond)
+
+ if resultSet.firstRecord () is None:
+ resultSet.insertRecord ()
+ modifier = 0
+ label ['gnue_id'] = self.__generateId ()
+ else:
+ label ['gnue_id'] = resultSet.current.getField ('gnue_id')
+ modifier = 1
+
+ if not self.doUpdate (resultSet, label):
+ modifier += 1
+
+ stat [modifier] += 1
+
+ if stat [0] + stat [1]:
+ self.connections.commitAll ()
+
+ print u_(" Labels: %(ins)3d inserted, %(upd)3d updated, %(kept)3d "
+ "unchanged.") \
+ % {'ins': stat [0], 'upd': stat [1], 'kept': stat [2]}
+
+
+ # ---------------------------------------------------------------------------
+ # Perform an update on the given resultset using a given data dictionary
+ # ---------------------------------------------------------------------------
+
+ def doUpdate (self, resultSet, data):
+ """
+ This function sets all fields in the current record of the resultset base
+ on the key/values given by the data dictionary. It returns TRUE, if a field
+ value has been changed, otherwise FALSE. If a field was changed, the record
+ gets posted.
+
+ @param resultSet: resultset with the current record to be updated
+ @param data: dictionary with keys and values used for updates
+ @return: TRUE if a field has been changed, FALSE if no field has been
+ changed.
+ """
+ doPost = False
+
+ for key in data:
+ if resultSet.current.getField (key) != data [key]:
+ resultSet.current.setField (key, data [key])
+ doPost = True
+
+ if doPost:
+ resultSet.post ()
+
+ return doPost
+
+
+ # ---------------------------------------------------------------------------
+ # Generate a new object id
+ # ---------------------------------------------------------------------------
+
+ def __generateId (self):
+ """
+ This function generates a new gnue_id like it is done by appserver. Once
+ this algorithm should be replace by a better one.
+ """
+ result = u''
+ for i in range (0, 32):
+ result = result + str (int (whrandom.random () * 10))
+ return result
+
+
+# =============================================================================
+# Main program
+# =============================================================================
+
+if __name__ == '__main__':
+ gldReader ().run ()
Property changes on: trunk/gnue-appserver/src/gld/readgld.py
___________________________________________________________________
Name: svn:keywords
+ +Id
Added: trunk/gnue-appserver/src/labels.py
===================================================================
--- trunk/gnue-appserver/src/labels.py 2004-08-06 12:22:18 UTC (rev 6164)
+++ trunk/gnue-appserver/src/labels.py 2004-08-06 18:29:25 UTC (rev 6165)
@@ -0,0 +1,926 @@
+# GNU Enterprise Appserver - Dynamic Forms Support
+#
+# Copyright 2001-2004 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: $
+
+import string
+import math
+import mx.DateTime
+
+from xml.sax import saxutils
+from gnue.appserver.classrep import Namespace
+
+
+# =============================================================================
+# This class encapsulates the property of a business object class
+# =============================================================================
+
+class Property:
+
+ # ---------------------------------------------------------------------------
+ # Construct a new instance with some serious defaults
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, pObject, isCalculated = False):
+ fullName = Namespace.createName (pObject.module.name, pObject.name)
+ fieldName = fullName
+
+ if isCalculated:
+ fieldName = Namespace.createName (pObject.module.name, pObject.name [3:])
+
+ self.fullName = fullName
+ self.fieldName = "fld%s" % fieldName.title ().replace ('_', '')
+ self.dbField = fieldName
+ self.label = pObject.gnue_name
+ self.type = pObject.gnue_type
+ self.length = pObject.gnue_length
+ self.scale = pObject.gnue_scale
+ self.page = pObject.module.name.title ()
+ self.pos = None
+ self.search = None
+ self.info = None
+ self.ref = None
+ self.refOrder = None
+ self.refName = self.type.title ().replace ('_', '')
+ self.typecast = None
+ self.inputMask = None
+ self.displayMask = None
+ self.triggers = {}
+
+ masks = ['%x', '%X', '%x %X']
+
+ if self.type in ['date', 'time', 'datetime']:
+ typeId = ['date','time', 'datetime'].index (self.type)
+
+ self.typecast = 'date'
+ self.inputMask = masks [typeId]
+ self.displayMask = masks [typeId]
+ self.fieldLength = len (mx.DateTime.now ().strftime (self.displayMask))
+
+ elif self.type == 'number':
+ self.typecast = 'number'
+ self.fieldLength = self.length or 0 + self.scale or 0 + 1
+
+ elif self.type == 'boolean':
+ self.fieldLength = 1
+
+ else:
+ self.fieldLength = self.length or 32
+
+
+ # ---------------------------------------------------------------------------
+ # Update label information from a gnue-label object
+ # ---------------------------------------------------------------------------
+
+ def updateLabel (self, label):
+ """
+ This function updates the instance with all label information
+ """
+ self.label = label.label
+ self.page = label.page
+ self.pos = label.position
+ self.search = label.search
+ self.info = label.info
+
+
+ # ---------------------------------------------------------------------------
+ # Order reference items by their search- and info-order
+ # ---------------------------------------------------------------------------
+
+ def orderReferences (self):
+ """
+ If a property is a reference to another class, this function orders all
+ parts of the reference given by their search- and info-order.
+ """
+ if self.ref is None:
+ return
+
+ order = []
+ for refItem in self.ref.values ():
+ refItem.fieldName = "%s%s" % (self.dbField, refItem.fieldName)
+ if refItem.search is not None:
+ order.append ((refItem.search, refItem))
+ else:
+ order.append ((refItem.info, refItem))
+
+ order.sort ()
+ self.refOrder = [item [1] for item in order]
+
+
+ # ---------------------------------------------------------------------------
+ # Return TRUE if a property is a lookup-reference
+ # ---------------------------------------------------------------------------
+
+ def isLookup (self):
+ """
+ This function returns TRUE if a reference-property is a lookup reference,
+ which means all search-fields will get dropdowns.
+ """
+ if self.refOrder is None or not len (self.refOrder):
+ return False
+
+ first = self.refOrder [0]
+ return first.search is not None and first.search != 0
+
+
+ # ---------------------------------------------------------------------------
+ # Get all reference fields which need to be added to a block
+ # ---------------------------------------------------------------------------
+
+ def getRefBlockFields (self):
+ """
+ This function returns an ordered sequence of all reference-fields, which
+ has to be added to a detail-block.
+ """
+ result = []
+ lookup = self.isLookup ()
+
+ for item in self.refOrder:
+ # for search-dialogs, we need only the field with search-order 0, since
+ # all other fields will be handled by the dialog
+ if (not lookup and item.search != 0) or item.info is not None:
+ continue
+
+ result.append (item)
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Place all widgets in a row
+ # ---------------------------------------------------------------------------
+
+ def placeWidgets (self, maxWidth):
+ """
+ This function places all visible widgets in a form row. After this function
+ is finished the following properties are set:
+ width - the width of the corresponding widget
+ left - the left position (x) of the widget
+ widgetSpace - the number of characters used for all widgets of the property
+
+ If a property is a reference, 'width' and 'left' is set for all
+ reference-items.
+ """
+ startX = 1 + self.labelWidth + 1
+ self.left = startX
+ maxWidth -= startX + 1
+ if self.ref is None:
+ if self.type == 'string' and self.length is None:
+ self.width = maxWidth
+ else:
+ self.width = min (maxWidth, self.fieldLength)
+
+ self.widgetSpace = self.width
+ else:
+ refLength = 0
+ refStart = startX
+
+ for refItem in self.refOrder:
+ if refItem.style == 'dropdown':
+ refItem.minWidth = 7
+ refItem.fieldLength = max (refItem.fieldLength, refItem.minWidth)
+ else:
+ refItem.minWidth = None
+
+ refItem.width = refItem.fieldLength
+ refItem.left = refStart
+
+ refStart += refItem.width
+ refLength += refItem.fieldLength
+
+ self.widgetSpace = refLength
+
+ # search-fields exceed the available space, so try to distribute the
+ # available space
+ if refLength > maxWidth:
+ aliqLength = 0
+ refStart = startX
+ for refItem in self.refOrder:
+ pWidth = int (maxWidth * refItem.fieldLength / refLength)
+ if pWidth + aliqLength <= maxWidth:
+ refItem.width = max (pWidth, refItem.minWidth)
+ aliqLength += pWidth
+ else:
+ refItem.width = None
+
+ self.widgetSpace = aliqLength
+
+
+
+# =============================================================================
+# This class generates GNUe Forms based on appserver's class repository
+# =============================================================================
+
+class FormGenerator:
+
+ _START_ROW = 1 # starting row for widgets
+ _MIN_HEIGHT = 2 # default minimum height of stretchable widgets
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, aClass, language, connection, formWidth, formHeight):
+ self.aClass = aClass
+ self.languages = ['C']
+ self.connection = connection
+ self.fullName = Namespace.createName (aClass.module.name, aClass.name)
+
+ self.maxWidth = formWidth
+ self.maxHeight = formHeight
+
+ self.properties = {}
+ self.sources = {}
+ self.pages = {}
+ self.visPages = {}
+ self.blocks = {}
+
+ # if language is a full locale like 'de_AT' add 'de' and 'de_AT' as well
+ if '_' in language:
+ self.languages.append (language.split ('_') [0])
+ self.languages.append (language)
+
+ self.properties = self.__getPropertyDict (self.fullName)
+
+ self.__loadLabels (self.fullName, self.properties)
+ self.__fillupReferences ()
+ self.__updateEntryStyle ()
+ self.__updateSources ()
+ self.pages = self.__buildVirtualPages ()
+ self.visPages = self.__buildVisualPages ()
+ self.__arangePages ()
+
+
+
+ # ---------------------------------------------------------------------------
+ # Get all properties and labels for a given class
+ # ---------------------------------------------------------------------------
+
+ def __getPropertyDict (self, classname):
+ """
+ This function retrieves all properties and of the requested class,
+ including calculated fields.
+ @param classname: fully qualified name of the requested class
+ @return: dictionary of all properties and calculated fields, where the
+ fieldnames act as key and the values are Property instances.
+ """
+ result = {}
+
+ (module, klass) = Namespace.splitName (classname)
+
+ cond = ['and', ['eq', ['field', 'gnue_class.gnue_name'], ['const', klass]],
+ ['eq', ['field', 'gnue_class.gnue_module.gnue_name'],
+ ['const', module]]]
+
+ pList = ['gnue_name', 'gnue_length', 'gnue_type', 'gnue_scale']
+ for prop in find ('gnue_property', cond, [], pList):
+ if prop.gnue_type == 'id':
+ continue
+
+ record = Property (prop)
+ result [record.fullName] = record
+
+ # Add all calculated properties
+ cond = ['and', ['eq', ['field', 'gnue_class.gnue_name'], ['const', klass]],
+ ['eq', ['field', 'gnue_class.gnue_module.gnue_name'],
+ ['const', module]],
+ ['like', ['field', 'gnue_name'], ['const', 'get%']],
+ ['notnull', ['field', 'gnue_type']]]
+
+ for proc in find ('gnue_procedure', cond, [], pList):
+ # a calculated field must not have parameters
+ if len (find ('gnue_parameter', ['eq', ['field', 'gnue_procedure'],
+ ['const', proc.gnue_id]], [], [])):
+ continue
+
+ record = Property (proc, True)
+ result [record.fullName] = record
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Update a property dictionary with labels information
+ # ---------------------------------------------------------------------------
+
+ def __loadLabels (self, classname, pDict, refsOnly = False):
+ """
+ This function updates the given property dictionary with all available
+ labels of a given class.
+ @param classname: fully qualified name of the class
+ @param pDict: dictionary with property instances
+ @param refsOnly: if TRUE, all non-reference properties will be removed from
+ the property dictionary pDict after loading the labels.
+ """
+ (module, klass) = Namespace.splitName (classname)
+ pList = ['gnue_label', 'gnue_position', 'gnue_search', 'gnue_info',
+ 'gnue_page']
+
+ for locale in self.languages:
+ cond = ['and', ['eq', ['field', 'gnue_language'], ['const', locale]],
+ ['eq', ['field', 'gnue_property.gnue_class.gnue_name'],
+ ['const', klass]],
+ ['eq', ['field', 'gnue_property.gnue_class.gnue_module.gnue_name'],
+ ['const', module]]]
+
+ if refsOnly:
+ cond.append (['or', ['notnull', ['field', 'gnue_search']],
+ ['notnull', ['field', 'gnue_info']]])
+
+ for label in find ('gnue_label', cond, [], pList):
+
+ full = Namespace.createName (label.gnue_property.module.name,
+ label.gnue_property.name)
+ pDict [full].updateLabel (label)
+
+ # Add labels for calculated properties
+ cond = ['and', ['eq', ['field', 'gnue_language'], ['const', locale]],
+ ['eq', ['field', 'gnue_procedure.gnue_class.gnue_name'],
+ ['const', klass]],
+ ['eq', ['field',
'gnue_procedure.gnue_class.gnue_module.gnue_name'],
+ ['const', module]]]
+
+ if refsOnly:
+ cond.append (['or', ['notnull', ['field', 'gnue_search']],
+ ['notnull', ['field', 'gnue_info']]])
+
+ for label in find ('gnue_label', cond, [], pList):
+ full = Namespace.createName (label.gnue_procedure.module.name,
+ label.gnue_procedure.name)
+
+ pDict [full].updateLabel (label)
+
+ if refsOnly:
+ for (key, item) in pDict.items ():
+ if item.search is None and item.info is None:
+ del pDict [key]
+
+
+ # ---------------------------------------------------------------------------
+ # Make sure all references have a valid set of reference items
+ # ---------------------------------------------------------------------------
+
+ def __fillupReferences (self):
+ """
+ This function populates all reference properties. Afterwards the member
+ 'ref' is set to a property-dictionary with all reference-parts. The member
+ 'refOrder' is an ordered sequence with all reference-parts.
+ """
+ for item in self.properties.values ():
+ if '_' in item.type:
+ result = self.__getPropertyDict (item.type)
+ self.__loadLabels (item.type, result, True)
+
+ if len (result.keys ()):
+ item.ref = result
+ item.orderReferences ()
+
+ if item.isLookup ():
+ drops = []
+ hasInfo = False
+ for refItem in item.refOrder:
+ if refItem.search is not None and refItem.search:
+ drops.append (refItem)
+ elif refItem.info is not None:
+ hasInfo = True
+
+ for dropdown in drops:
+ dropdown.needTrigger = hasInfo
+
+
+ # ---------------------------------------------------------------------------
+ # Update the property-dictionary with entry-style information
+ # ---------------------------------------------------------------------------
+
+ def __updateEntryStyle (self):
+ """
+ This function iterates over all properties of a class and determines their
+ entry-style. A style 'None' means default. All items of a reference
+ properties are set as well. Lookup-references are treated as dropdowns, if
+ they are flagged as searchable, otherwise they're labels. For
+ search-dialogs the first field get's an entry all others are labels.
+ After this function is finished all properties have a valid member 'style'
+ """
+ for prop in self.properties.values ():
+ prop.style = None
+
+ if prop.ref is None:
+ if prop.type == 'boolean':
+ prop.style = 'checkbox'
+ else:
+ if prop.isLookup ():
+ for refItem in prop.refOrder:
+ if refItem.search is not None:
+ refItem.style = 'dropdown'
+ else:
+ refItem.style = 'label'
+ else:
+ prop.refOrder [0].style = None
+
+ for refItem in prop.refOrder [1:]:
+ refItem.style = 'label'
+
+
+ # ---------------------------------------------------------------------------
+ # Update the sources- and blocks-dictionary and their field sequences
+ # ---------------------------------------------------------------------------
+
+ def __updateSources (self):
+ """
+ This function updates the datasource- and blocks-dictionaries.
+ """
+ self.__addToSources ('dtsMaster', self.fullName)
+
+ for prop in self.properties.values ():
+ if prop.ref is None:
+ dtsName = "dtsMaster"
+ blkName = "blkMaster"
+ prop.block = blkName
+
+ self.__addToBlocks (blkName, dtsName, prop)
+
+ else:
+ table = prop.type
+ if prop.isLookup ():
+ self.__addToBlocks ('blkMaster', 'dtsMaster', prop)
+ prop.block = 'blkMaster'
+
+
+ for refItem in prop.refOrder:
+ if refItem.style == 'dropdown':
+ dtsName = "dts%s" % prop.refName
+ refItem.block = 'blkMaster'
+ self.__addToSources (dtsName, prop.type, {'prequery': 'Y'})
+
+ if refItem.needTrigger:
+ trigger = self.__addToTriggers ('POST-CHANGE', refItem)
+ co = [saxutils.escape ("fId = %s.%s.get ()" \
+ % (refItem.block, refItem.fieldName))]
+ co.append (saxutils.escape ("%s.simpleQuery ({'gnue_id': fId})" %
+ "dtsLookup%s%s" % (prop.dbField, prop.refName)))
+ attrs = {'type': 'POST-CHANGE',
+ 'contents': co}
+
+ trigger.extend (self._getXMLTag ('trigger', attrs))
+
+ else:
+ dtsName = "dtsLookup%s%s" % (prop.dbField, prop.refName)
+ blkName = "blkLookup%s%s" % (prop.dbField, prop.refName)
+ refItem.block = blkName
+
+ self.__addToBlocks (blkName, dtsName, refItem)
+ self.__addToSources (dtsName, prop.type, {'master': 'dtsMaster',
+ 'masterlink': prop.dbField, 'detaillink': 'gnue_id'})
+
+
+
+ # ---------------------------------------------------------------------------
+ # Add a property to the given block dictionary
+ # ---------------------------------------------------------------------------
+
+ def __addToBlocks (self, blockName, datasource, item):
+ """
+ This function appends the given property (item) to the requested block's
+ fieldlist.
+ @param blockName: the name of the block to be extended
+ @param datasource: the name of the datasource the block is bound to
+ @param item: the property to be added to the block
+ """
+ if not self.blocks.has_key (blockName):
+ self.blocks [blockName] = {'source': datasource,
+ 'fields': []}
+ self.blocks [blockName]['fields'].append (item)
+
+
+ # ---------------------------------------------------------------------------
+ # Add a datasource to the datasource dictionary
+ # ---------------------------------------------------------------------------
+
+ def __addToSources (self, sourceName, tableName, attrs = {}):
+ """
+ Add a datasource to the datasource-dictionary or update it.
+ @param sourceName: name of the datasource
+ @param tableName: name of the table the datasource is bound to
+ @param attrs: dictionary with additional attributes for the datasource
+ """
+ if not self.sources.has_key (sourceName):
+ self.sources [sourceName] = {}
+
+ self.sources [sourceName].update (attrs)
+ self.sources [sourceName]['name'] = sourceName
+ self.sources [sourceName]['table'] = tableName
+ self.sources [sourceName]['connection'] = self.connection
+
+
+ # ---------------------------------------------------------------------------
+ # Add a trigger to a propertie's trigger dictionary
+ # ---------------------------------------------------------------------------
+
+ def __addToTriggers (self, name, item):
+ """
+ This function makes sure a properties trigger dictionary has a given key
+ @param name: name of the trigger
+ @param item: the property to add the trigger to
+ @return: code-sequence of the requested trigger
+ """
+ if not item.triggers.has_key (name):
+ item.triggers [name] = []
+ return item.triggers [name]
+
+
+ # ---------------------------------------------------------------------------
+ # Build up the virtual pages
+ # ---------------------------------------------------------------------------
+
+ def __buildVirtualPages (self):
+ """
+ This function returns a dictionary of virtual pages. Such a page contains
+ all fields in the proper order as requested by gnue_lables. Additionally
+ all items get a property 'minHeight' set, which determines the minimum
+ height needed by a field. If minHeight is None, a field can be stretched
+ vertically to consume the available space left.
+ @return: dictionary with all virtual pages, where the page-names act as
+ keys and the values are sequences with the properties per page. The
+ property sequences are already ordered.
+ """
+ result = {}
+
+ # add fields to their virtual pages
+ for item in self.properties.values ():
+ if not result.has_key (item.page):
+ result [item.page] = []
+
+ item.addHeight = 0
+ # specify a minimum height required for a field
+ if item.type == 'string' and item.length is None:
+ item.minHeight = None
+ else:
+ item.minHeight = 1
+
+
+ result [item.page].append (item)
+
+ # now order all fields per virtual page
+ for page in result.keys ():
+ pOrder = []
+ nOrder = []
+
+ for item in result [page]:
+ if item.pos is None:
+ nOrder.append ((item.label, item))
+ else:
+ pOrder.append ((item.pos, item))
+
+ nOrder.sort ()
+ pOrder.sort ()
+
+ result [page] = [p [1] for p in pOrder] + [n [1] for n in nOrder]
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Create the visual pages
+ # ---------------------------------------------------------------------------
+
+ def __buildVisualPages (self):
+ """
+ This function transforms the virtual pages into visible pages. Available
+ space is distributed to all stretchable widgets. After this function is
+ finished all properties have their row- and height-member set. This
+ function also set's the maximum page height for the form.
+
+ @return: dictionary with the visible pages, where page-names act as keys
+ and the values are the ordered properties per page.
+ """
+ result = {}
+ self.maxPageHeight = 0
+
+ for (pageName, virtPage) in self.pages.items ():
+ needed = self._START_ROW
+ stretchable = []
+ for item in virtPage:
+ if item.minHeight is None:
+ needed += self._MIN_HEIGHT
+ stretchable.append (item)
+ else:
+ needed += item.minHeight
+
+ if needed <= self.maxHeight:
+ nPages = 1
+ else:
+ nPages = int (math.ceil (float (needed) / self.maxHeight))
+ availLines = nPages * self.maxHeight - needed
+
+ if len (stretchable) and availLines / len (stretchable):
+ avgAdd = availLines / len (stretchable)
+
+ for sIndex in range (len (stretchable)):
+ sItem = stretchable [sIndex]
+ sItem.addHeight = avgAdd
+
+ if sIndex == len (stretchable) - 1:
+ avgAdd = availLines
+ availLines = 0
+ else:
+ availLines -= avgAdd
+ avgAdd = availLines / len (stretchable) - sIndex - 1
+
+
+ # create the visual page(s)
+ row = self._START_ROW
+ pageNum = 1
+ cPage = []
+ result [pageName] = cPage
+
+ for item in virtPage:
+ item.height = item.minHeight or self._MIN_HEIGHT + item.addHeight
+
+ if row + item.height - 1 > self.maxHeight:
+ pageNum += 1
+ cPage = []
+ result ["%s-%d" % (pageName, pageNum)] = cPage
+ row = self._START_ROW
+
+ item.row = row
+ cPage.append (item)
+
+ row += item.height
+ self.maxPageHeight = max (self.maxPageHeight, row)
+
+ self.maxPageHeight += 1
+ return result
+
+
+
+ # ---------------------------------------------------------------------------
+ # Horizontally arrange all widgets on their visual pages
+ # ---------------------------------------------------------------------------
+
+ def __arangePages (self):
+ """
+ This function horizontally arranges all widgets on their visual page. After
+ this function is finished all properties have their left-, labelWidth- and
+ widgetSpace-members set. This function also sets the maximum page width for
+ the form.
+ """
+ self.maxPageWidth = 0
+
+ for page in self.visPages.values ():
+ maxLabel = 0
+ for item in page:
+ maxLabel = max (maxLabel, len (item.label))
+
+ for item in page:
+ item.labelWidth = maxLabel
+ item.placeWidgets (self.maxWidth)
+
+ size = item.left + item.widgetSpace + 1
+ self.maxPageWidth = max (self.maxPageWidth, size)
+
+
+ # ---------------------------------------------------------------------------
+ # Generate the form
+ # ---------------------------------------------------------------------------
+
+ def generateForm (self):
+ """
+ This function creates the XML-code for the form.
+ @return: string containing the XML-code of the form
+ """
+ self.code = [u'<?xml version="1.0" encoding="utf-8"?>']
+ self.code.extend (self._getXMLTag ('form',
+ {'title': "%s %s" % (self.aClass.module.name.title (),
+ self.aClass.name.title ())}, "", True))
+
+ # datasources and blocks
+ indent = " "
+ for source in self.sources.values ():
+ self.code.extend (self._getXMLTag ('datasource', source, indent))
+
+ self.__addBlocks ()
+
+ # layout
+ attrs = {'xmlns:c' : 'GNUe:Layout:Char',
+ 'c:width' : self.maxPageWidth,
+ 'c:height': self.maxPageHeight}
+
+ if len (self.visPages.keys ()) > 1:
+ attrs ['tabbed'] = 'top'
+
+ self.code.extend (self._getXMLTag ('layout', attrs, indent, True))
+
+ focusOrder = 1
+ for page in self.visPages.keys ():
+ ind = indent + " "
+ attrs = {'name': page}
+ self.code.extend (self._getXMLTag ('page', attrs, ind, True))
+ find = ind + " "
+
+ for item in self.visPages [page]:
+ # labels
+ attrs = {'c:x' : 1,
+ 'c:y' : item.row,
+ 'c:width' : item.labelWidth,
+ 'c:height': 1,
+ 'text' : item.label}
+ self.code.extend (self._getXMLTag ('label', attrs, find))
+
+ for item in self.visPages [page]:
+ if item.ref is None:
+ attrs = {'c:x' : item.left,
+ 'c:y' : item.row,
+ 'c:width' : item.width,
+ 'c:height': item.height,
+ 'block' : item.block,
+ 'field' : item.fieldName}
+
+ if focusOrder == 1:
+ attrs ['focusorder'] = 1
+
+ focusOrder += 1
+
+ if item.displayMask is not None:
+ attrs ['displaymask'] = item.displayMask
+
+ if item.inputMask is not None:
+ attrs ['inputmask'] = item.inputMask
+
+ if item.style is not None:
+ attrs ['style'] = item.style
+
+ self.code.extend (self._getXMLTag ('entry', attrs, find))
+
+ else:
+ for refItem in item.refOrder:
+ if refItem.width is None:
+ continue
+
+ attrs = {'c:x' : refItem.left,
+ 'c:y' : item.row,
+ 'c:width' : refItem.width,
+ 'c:height': item.height,
+ 'block' : refItem.block,
+ 'field' : refItem.fieldName}
+ if focusOrder == 1:
+ attrs ['focusorder'] = 1
+
+ focusOrder += 1
+
+ if refItem.style is not None:
+ attrs ['style'] = refItem.style
+
+ self.code.extend (self._getXMLTag ('entry', attrs, find))
+
+ self.code.append ('%s</page>' % ind)
+
+ self.code.append ('%s</layout>' % indent)
+ self.code.append ('</form>')
+
+ #f = open ('gencode.gfd', 'w')
+ #for i in self.code:
+ #data = "%s\n" % i
+ #f.write (data.encode ('utf-8'))
+ #f.close ()
+
+ return string.join (self.code, "\n")
+
+
+
+ # ---------------------------------------------------------------------------
+ # Add blocks to the form code
+ # ---------------------------------------------------------------------------
+
+ def __addBlocks (self):
+ """
+ This function adds the logic-section to the forms code sequence
+ """
+ indLogic = " "
+ indBlock = indLogic + " "
+
+ self.code.append ("%s<logic>" % indLogic)
+
+ for (blockName, block) in self.blocks.items ():
+ attrs = {'name' : blockName,
+ 'datasource': block ['source']}
+ self.code.extend (self._getXMLTag ('block', attrs, indBlock, True))
+
+ self.__addFields (block, indBlock)
+
+ self.code.append ("%s</block>" % indBlock)
+
+ self.code.append ("%s</logic>" % indLogic)
+
+
+ # ---------------------------------------------------------------------------
+ # Add all fields of a block to the code sequence
+ # ---------------------------------------------------------------------------
+
+ def __addFields (self, block, indent):
+ """
+ This function adds all fields of a block to the code sequence
+ """
+ indent += " "
+ for field in block ['fields']:
+ if field.dbField == 'gnue_id':
+ continue
+
+ if field.ref is not None:
+ for refItem in field.getRefBlockFields ():
+ attr = {'name' : refItem.fieldName,
+ 'field' : field.dbField,
+ 'fk_key': 'gnue_id',
+ 'fk_description': refItem.dbField,
+ 'fk_source': 'dts%s' % field.refName}
+
+ if len (refItem.triggers.keys ()):
+ attr ['contents'] = []
+ for trigger in refItem.triggers.values ():
+ attr ['contents'].extend (trigger)
+
+ self.code.extend (self._getXMLTag ('field', attr, indent))
+ else:
+ attr = {'name' : field.fieldName,
+ 'field': field.dbField}
+ if field.typecast is not None:
+ attr ['typecast'] = field.typecast
+ if field.typecast != 'number':
+ if field.length:
+ attr ['maxLength'] = field.length
+
+ self.code.extend (self._getXMLTag ('field', attr, indent))
+
+
+ # ---------------------------------------------------------------------------
+ # Create an XML sequence
+ # ---------------------------------------------------------------------------
+
+ def _getXMLTag (self, tag, attrs, indent = "", keep = False):
+ """
+ This function creates a code-sequence for the given XML tag.
+ @param tag: name of the XML tag
+ @param attrs: dictionary with attributes
+ @param indent: indentation for each line
+ @param keep: if TRUE the tag is not closed, although attrs has no contents
+ key.
+ """
+ result = []
+ parts = []
+ gap = " "
+
+ if attrs.has_key ('contents'):
+ contents = []
+ for element in attrs ['contents']:
+ contents.extend (element.splitlines ())
+ del attrs ['contents']
+ else:
+ contents = None
+
+ keys = attrs.keys ()
+ keys.sort ()
+ if 'name' in keys:
+ keys.remove ('name')
+ keys.insert (0, 'name')
+
+ close = (contents is None and not keep) and "/" or ""
+
+ xmlString = "%s<%s" % (indent, tag)
+ nextIndent = len (xmlString)
+
+ for key in keys:
+ add = '%s="%s"' % (key, attrs [key])
+ if len (xmlString) + len (add) > 76:
+ result.append (xmlString)
+ xmlString = " " * nextIndent
+
+ xmlString = "%s %s" % (xmlString, add)
+
+ xmlString = "%s%s>" % (xmlString, close)
+ result.append (xmlString)
+
+ if contents is not None:
+ iLen = len (indent) + len (gap)
+ cString = string.join (["%s%s" % (" " * iLen, i) for i in contents],
"\n")
+
+ result.append (cString)
+ result.append ("%s</%s>" % (indent, tag))
+
+ return result
Property changes on: trunk/gnue-appserver/src/labels.py
___________________________________________________________________
Name: svn:keywords
+ +Id
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r6165 - in trunk/gnue-appserver: . po samples scripts src src/gld,
johannes <=