commit-gnue
[Top][All Lists]
Advanced

[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





reply via email to

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