[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r6555 - trunk/gnue-reports/src/client
From: |
johannes |
Subject: |
r6555 - trunk/gnue-reports/src/client |
Date: |
Sun, 24 Oct 2004 04:14:08 -0500 (CDT) |
Author: johannes
Date: 2004-10-24 04:14:07 -0500 (Sun, 24 Oct 2004)
New Revision: 6555
Modified:
trunk/gnue-reports/src/client/GRRunUI.py
Log:
Added first version of a RunUI implementation
Modified: trunk/gnue-reports/src/client/GRRunUI.py
===================================================================
--- trunk/gnue-reports/src/client/GRRunUI.py 2004-10-23 18:19:25 UTC (rev
6554)
+++ trunk/gnue-reports/src/client/GRRunUI.py 2004-10-24 09:14:07 UTC (rev
6555)
@@ -1,6 +1,9 @@
+# GNU Enterprise Reports - Run/create a user interface for starting a report
#
-# This file is part of GNU Enterprise.
+# 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
@@ -16,96 +19,537 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2004 Free Software Foundation
-#
-# FILE:
-# GRRunUI.py
-#
-# DESCRIPTION:
-# Utilities that present a UI to the reader
-#
-# NOTES:
-#
+# $Id$
+import string
+import StringIO
-from StringIO import StringIO
+from gnue.common.apps import errors
from gnue.common.utils.FileUtils import dyn_import
+
+# =============================================================================
+# This class handles an UI for a report
+# =============================================================================
+
class GRRunUI:
- def __init__(self, client, reportInfo,ui='text',
- userParameters={},destination='-',
- destinationType='file',filter='raw',
- sortoption=None):
+ # --------------------------------------------------------------------------
+ # Constructor
+ # --------------------------------------------------------------------------
+ def __init__ (self, client, reportInfo, ui = 'text', userParameters = {},
+ destination = '-', destinationType = 'file', filter = 'raw',
+ sortoption = None):
self.client = client
if ui != 'text':
try:
- self.uimodule = dyn_import('gnue.forms.uidrivers.%s' % ui)
+ self.uimodule = dyn_import ('gnue.forms.uidrivers.%s' % ui)
# Nasty hackery
from gnue.forms.GFConfig import ConfigOptions as FormConfigOptions
-
client.configurationManager.loadApplicationConfig(section="forms",defaults=FormConfigOptions)
- client.configurationManager.registerAlias('gConfigForms', 'forms')
+ client.configurationManager.loadApplicationConfig (section = "forms",
+ defaults = FormConfigOptions)
+ client.configurationManager.registerAlias ('gConfigForms', 'forms')
+ self.gfinstance = dyn_import ('gnue.forms.GFInstance')
+
except ImportError:
ui = 'text'
if ui == 'text':
- self.uimodule = None
- self.loginhandler = LoginHandler()
+ self.uimodule = None
+ self.loginhandler = LoginHandler ()
else:
- self.loginhandler = self.uimodule.UILoginHandler()
+ self.loginhandler = self.uimodule.UILoginHandler ()
- self.reportInfo = reportInfo
- self.userParameters = userParameters
- self.ui = ui
- self.destination = destination
+ self.reportInfo = reportInfo
+ self.userParameters = userParameters
+ self.ui = ui
+ self.destination = destination
self.destinationType = destinationType
- self.filter = filter
- self.sortoption = sortoption
+ self.filter = filter
+ self.sortoption = sortoption
- def getLoginHandler(self):
- return self.loginhandler
+ # ---------------------------------------------------------------------------
+ # create a user interface and run it
+ # ---------------------------------------------------------------------------
+ def run (self):
+ """
+ """
- def run(self):
if self.uimodule:
- pass
+ # First add some internal parameters to the userparams-dictionary
+ self.userParameters ['filter'] = self.filter
+ self.userParameters ['destination'] = self.destination
+ self.userParameters ['destinationType'] = self.destinationType
+ self.userParameters ['canceled'] = False
+ # Create the form's code on the fly and put it into an instance
+ formBuffer = self.__buildForm ()
+ instance = self.gfinstance.GFInstance (self, self.client.connections,
+ self.uimodule, True, self.userParameters)
+ instance.addFormFromFilehandle (formBuffer)
+ instance.addDialogs ()
+ instance.activate ()
- def getParameters(self):
+ # Now iterate through the parameters dictionary and fetch our 'private'
+ # values, also remove them from userParameters
+ if self.userParameters ['canceled']:
+ raise errors.UserError, u_("Report canceled")
+
+ self.filter = self.userParameters ['filter']
+ self.destination = self.userParameters ['destination']
+ self.destinationType = self.userParameters ['destinationType']
+
+ del self.userParameters ['filter']
+ del self.userParameters ['destination']
+ del self.userParameters ['destinationType']
+ del self.userParameters ['canceled']
+
+
+ # ---------------------------------------------------------------------------
+ # Get the current login handler
+ # ---------------------------------------------------------------------------
+
+ def getLoginHandler (self):
+ """
+ """
+
+ return self.loginhandler
+
+
+ # ---------------------------------------------------------------------------
+ # Get the user parameter dictionary
+ # ---------------------------------------------------------------------------
+
+ def getParameters (self):
+ """
+ """
+
return self.userParameters
- def getDestination(self):
+ # ---------------------------------------------------------------------------
+ # Get the current destination
+ # ---------------------------------------------------------------------------
+
+ def getDestination (self):
+ """
+ """
+
return self.destination
- def getDestinationType(self):
+ # ---------------------------------------------------------------------------
+ # Get the destination type
+ # ---------------------------------------------------------------------------
+
+ def getDestinationType (self):
+ """
+ """
+
return self.destinationType
- def getFilter(self):
+ # ---------------------------------------------------------------------------
+ # Get the current filter
+ # ---------------------------------------------------------------------------
+
+ def getFilter (self):
+ """
+ """
+
return self.filter
- def getSortOption(self):
+ # ---------------------------------------------------------------------------
+ # Get the current sort option
+ # ---------------------------------------------------------------------------
+
+ def getSortOption (self):
+ """
+ """
+
return self.sortoption
+ # ---------------------------------------------------------------------------
+ # Generate a form for entering parameters and filter/destination
+ # ---------------------------------------------------------------------------
+ def __buildForm (self):
+ """
+ This function generates a GNU Enterprise Form Definition for the report as
+ described by our reportInfo property.
-def buildForm(reportParameters, userParameters):
- buffer = StringIO()
+ @return: filehandle to read the form from
+ """
+ code = ['<?xml version="1.0" encoding="utf-8"?>', '<form>']
+ fields = self.__translateParameters ()
+ # Add all parameters as 'user parameters' to the form definition
+ for item in fields:
+ code.extend (self._getXMLTag ('parameter', \
+ {'name': item ['name'], 'default': item ['default']}, " "))
+ # Add fields for the filter
+ self.__addOtherFields (fields)
+
+ # Get some positioning information from all fields
+ formHeight = len (fields) + 3
+ self.labelWidth = 0
+ formWidth = 0
+
+ for item in fields:
+ self.labelWidth = max (self.labelWidth, len (item ['label']))
+ formWidth = max (formWidth, self.labelWidth + 2 + item ['dLength'])
+
+ # Add datasources and blocks
+ code.extend (self.__addDataSources ())
+ code.extend (self._getXMLTag ('logic', \
+ {'contents': self.__addBlocks (fields)}, " "))
+
+ code.extend (self.__addTriggers (fields))
+
+ # Layout
+ code.extend (self._getXMLTag ('layout', \
+ {'xmlns:c' : 'GNUe:Layout:Char',
+ 'c:width' : formWidth,
+ 'c:height': formHeight,
+ 'contents': self.__addLabelsAndEntries (u_("Parameters"), fields)},
+ " "))
+
+ code.append ("</form>")
+
+ # this is for debugging atm
+ x = open ('test.gfd', 'w')
+ for item in code:
+ x.write ("%s\n" % item)
+ x.close ()
+
+ # Prepare a buffer with the form's code and set it's position to the start
+ result = StringIO.StringIO ()
+ result.writelines (code)
+ result.seek (0, 0)
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Translate the report parameters dictionary into a sequence
+ # ---------------------------------------------------------------------------
+
+ def __translateParameters (self):
+ """
+ This function maps all report parameters to a sequence of field
+ definitions.
+
+ @return: sequence of dictionaries, one per parameter
+ """
+
+ result = []
+
+ for param in self.reportInfo.getParameters ():
+ name = param ['name']
+
+ current = {'name' : name,
+ 'default' : self.userParameters.get (name, param ['default']),
+ 'style' : None,
+ 'format' : None,
+ 'typecast': None,
+ 'dLength' : 35,
+ 'pType' : param.get ('type', 'char'),
+ 'skip' : False,
+ 'fieldDef': []}
+
+ pType = current ['pType']
+
+ if pType == ['boolean']:
+ current ['style'] = 'checkbox'
+ current ['dLength'] = 1
+
+ elif pType == ['date', 'time', 'datetime']:
+ current ['typecast'] = 'date'
+ masks = ['%x', '%X', '%x %X']
+ current ['format'] = masks [['date', 'time', 'datetime'].index
(pType)]
+ current ['dLength'] = len (mx.DateTime.now ().strftime (format))
+
+ current ['label'] = param.get ('description', name)
+ result.append (current)
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Add all other form fields to the field-sequecnce
+ # ---------------------------------------------------------------------------
+
+ def __addOtherFields (self, fields):
+ """
+ This function extends the given field-sequence with all outstanding fields
+ of the form, which are not given as paramter.
+
+ @param fields: sequence of field dictionaries to be extended.
+ """
+
+ fields.append ({'name' : 'filter',
+ 'label' : u_("Output filter"),
+ 'style' : 'dropdown',
+ 'format' : None,
+ 'typecast': None,
+ 'dLength' : 35,
+ 'pType' : 'char',
+ 'skip' : False,
+ 'fieldDef': [{'fk_source': 'dtsFilters'},
+ {'fk_key': 'key'},
+ {'fk_description': 'descr'}]})
+
+
+ # ---------------------------------------------------------------------------
+ # Create the XML code for all datasources needed by the form
+ # ---------------------------------------------------------------------------
+
+ def __addDataSources (self):
+ """
+ This function generates a XML code sequence with all datasources needed by
+ the form.
+
+ @return: sequence of XML code lines
+ """
+
+ filters = [('raw', u_("Raw XML"))]
+ for item in self.reportInfo.getFilters ():
+ filters.append ((item [1]['formatter'], item [1]['description']))
+
+ rows = []
+ for (key, descr) in filters:
+ rows.extend (self._getXMLTag ('staticsetrow',
+ {'contents': \
+ self._getXMLTag ('staticsetfield', \
+ {'name': 'key', 'value': key}, "") + \
+ self._getXMLTag ('staticsetfield', \
+ {'name': 'descr', 'value': descr}, "")}, ""))
+
+ return self._getXMLTag ('datasource', {'name': 'dtsFilters',
+ 'type': 'static', 'prequery': 'Y',
+ 'contents': self._getXMLTag ('staticset', {'fields': 'key,descr',
+ 'contents': rows}, "")}, " ")
+
+
+ # ---------------------------------------------------------------------------
+ # Add the XML code for all blocks needed
+ # ---------------------------------------------------------------------------
+
+ def __addBlocks (self, fields):
+ """
+ This function generates all block definitions.
+
+ @return: XML code sequence with block definitions
+ """
+
+ # First build the block with all input fields
+ inpBlock = []
+
+ for item in fields:
+ attrs = {'name': item ['name']}
+ for additional in item ['fieldDef']:
+ attrs.update (additional)
+ if item ['typecast'] is not None:
+ attrs ['typecast'] = item ['typecast']
+
+ inpBlock.extend (self._getXMLTag ('field', attrs, ""))
+
+ result = self._getXMLTag ('block', {'name': 'blkInput', 'autoCommit': 'Y',
+ 'contents': inpBlock})
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Add the XML code for all triggers
+ # ---------------------------------------------------------------------------
+
+ def __addTriggers (self, fields):
+ """
+ This function creates the global triggers.
+
+ @return: XML code sequence with trigger code
+ """
+
+ onActivate = []
+ onExit = []
+
+ for item in fields:
+ if item ['skip']:
+ continue
+
+ onActivate.append ("blkInput.%s.set (getParameter ('%s'))" \
+ % (item ['name'], item ['name']))
+
+ onExit.append ("setParameter ('%s', blkInput.%s.get ())" \
+ % (item ['name'], item ['name']))
+
+
+ result = []
+
+ if len (onActivate):
+ result.extend (self._getXMLTag ('trigger', {'type': 'ON-ACTIVATION',
+ 'contents': onActivate}, " "))
+ if len (onExit):
+ result.extend (self._getXMLTag ('trigger', {'type': 'ON-EXIT',
+ 'contents': onExit}, " "))
+
+ # Button-Triggers
+ result.extend (self._getXMLTag ('trigger', {'type': 'NAMED',
+ 'name': 'trgOk', 'contents': ["close ()"]}, " "))
+
+ result.extend (self._getXMLTag ('trigger', {'type': 'NAMED',
+ 'name': 'trgCancel',
+ 'contents': ["setParameter ('canceled', True)", "close ()"]}, " "))
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Add all entries and labels to the given page
+ # ---------------------------------------------------------------------------
+
+ def __addLabelsAndEntries (self, page, fields):
+ """
+ This function creates a page with all the fields listed.
+
+ @param page: Name of the page to add the fields to
+ @param fields: sequence of field dictionaries to be added to the page
+
+ @return: XML code sequence with all fields including an Ok and Cancel
+ button.
+ """
+
+ result = []
+
+ labels = []
+ entries = []
+ row = 0
+
+ for item in fields:
+ row += 1
+
+ # Label
+ attrs = {'c:x' : 1,
+ 'c:y' : row,
+ 'c:width' : len (item ['label']),
+ 'c:height': 1,
+ 'text' : "%s:" % item ['label']}
+ labels.extend (self._getXMLTag ('label', attrs))
+
+ # Entry
+ attrs = {'c:x' : 1 + self.labelWidth,
+ 'c:y' : row,
+ 'c:width' : item ['dLength'],
+ 'c:height': 1,
+ 'block' : 'blkInput',
+ 'field' : item ['name']}
+
+ if item ['style'] is not None:
+ attrs ['style'] = item ['style']
+
+ if item ['format'] is not None:
+ attrs ['displaymask'] = item ['format']
+ attrs ['inputmask'] = item ['format']
+
+ entries.extend (self._getXMLTag ('entry', attrs))
+
+ row += 2
+ buttons = [('Ok', u_("Ok")), ('Cancel', u_("Cancel"))]
+ maxbWidth = 0
+ for b in buttons:
+ maxbWidth = max (maxbWidth, len (b [1]) + 4)
+
+ left = self.labelWidth + 1
+
+ for b in buttons:
+ attrs = {'c:x' : left,
+ 'c:y' : row,
+ 'c:width' : maxbWidth,
+ 'c:height': 1,
+ 'label' : b [1],
+ 'contents': self._getXMLTag ('trigger', {'src': "trg%s" % b [0],
+ 'type': 'ON-ACTION'})}
+
+ entries.extend (self._getXMLTag ('button', attrs))
+ left += (maxbWidth + 1)
+
+ return self._getXMLTag ('page', \
+ {'name': page, 'contents': labels + entries})
+
+ # ---------------------------------------------------------------------------
+ # 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.
+
+ @return: sequence with XML code, one element per line
+ """
+ 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
+
+
#
# This is a (temporary?) solution to getting a login
#
Property changes on: trunk/gnue-reports/src/client/GRRunUI.py
___________________________________________________________________
Name: svn:keywords
+ Id
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r6555 - trunk/gnue-reports/src/client,
johannes <=