From 8082be66d2be78497859f52371a29d615019f72a Mon Sep 17 00:00:00 2001 From: Kevin Deldycke <kevin@nexedi.com> Date: Tue, 25 Oct 2005 19:48:17 +0000 Subject: [PATCH] First release of guy's work. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@4128 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5OOo/CreatePropertySheet.py | 323 +++++++++++++++++++++++++ product/ERP5OOo/FieldHelpTopic.py | 35 +++ product/ERP5OOo/FieldRegistry.py | 175 ++++++++++++++ product/ERP5OOo/ScribusUtils.py | 139 +++++++++++ 4 files changed, 672 insertions(+) create mode 100755 product/ERP5OOo/CreatePropertySheet.py create mode 100755 product/ERP5OOo/FieldHelpTopic.py create mode 100755 product/ERP5OOo/FieldRegistry.py create mode 100755 product/ERP5OOo/ScribusUtils.py diff --git a/product/ERP5OOo/CreatePropertySheet.py b/product/ERP5OOo/CreatePropertySheet.py new file mode 100755 index 0000000000..ae0f56554a --- /dev/null +++ b/product/ERP5OOo/CreatePropertySheet.py @@ -0,0 +1,323 @@ +############################################################################# +# +# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved. +# Jean-Paul Smets-Solanes <jp@nexedi.com> +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program 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 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + + +from Products.PythonScripts.Utility import allow_class +from ZPublisher.HTTPRequest import FileUpload +from xml.dom.ext.reader import PyExpat +from xml.dom import Node, minidom +from AccessControl import ClassSecurityInfo +from Globals import InitializeClass, get_request +from zipfile import ZipFile, ZIP_DEFLATED +from StringIO import StringIO +from zLOG import LOG +import imghdr +import random +import getopt, sys, os +from urllib import quote + +ZOPE_INSTANCE_HOME = os.environ.get("INSTANCE_HOME", "/var/lib/zope/") + +class Getter_Setter: + """ + Create PropertySheet of module + """ + + # Declarative security + security = ClassSecurityInfo() + + + security.declarePublic('create_PropertySheet') + def create_PropertySheet(self, name_file = None, personnal_properties = []): + """ + create PropertySheet in /var/lib/zope/Products/ERP5/PropertySheet/ + """ + path_name_file = os.path.join(ZOPE_INSTANCE_HOME, 'PropertySheet', str(name_file) + '.py') + file = open(path_name_file,'w') + file.seek(0) + + string = """ +############################################################################# +# +# Copyright (c) 2002-2005 Nexedi SARL and Contributors. All Rights Reserved. +# Jean-Paul Smets-Solanes <jp@nexedi.com> +# Kevin Deldycke <kevin@nexedi.com> +# Guy Oswald OBAMA <guy@nexedi.com> +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program 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 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + """ + + file.write(string) + + string = '\n\nclass ' + str(name_file) + ' :\n' + file.write(string) + string = 2*' ' + '"""\n' + file.write(string) + string = 6*' ' + str(name_file) + ' properties and categories\n' + file.write(string) + string = 2*' ' + '"""\n\n' + file.write(string) + string = 2*' ' + '_properties = (\n' + file.write(string) + string = 6*' ' + '# Personal properties\n' + file.write(string) + + for i in range(len(personnal_properties)): + string = 6*' ' + "{ 'id' : '" + personnal_properties[i][0][3:] + "' \n" + file.write(string) + + string = 6*' ' + ", 'description' : '" + personnal_properties[i][1] + "' \n" + file.write(string) + + string = 6*' ' + ", 'type' : '" + personnal_properties[i][2] + "' \n" + file.write(string) + + string = 6*' ' + ", 'mode' : '" + personnal_properties[i][3] + "' \n" + file.write(string) + + string = 6*' ' + "}, \n" + file.write(string) + + string = 2*' ' + ')\n' + file.write(string) + + string = '\n\n' + 2*' ' + str("_categories = ( 'source_section', 'destination_section')") + '\n' + file.write(string) + + file.close() + + # get text to create a new PropertySheet in portal_classes + file1 = open(path_name_file, 'r') + lines_list = file1.readlines() + text = '' + for line in lines_list: + text = text + line + file1.close() + + path_name_file_1 = '/var/lib/zope/Products/ERP5/PropertySheet/' + str(name_file) + '.py' + file2 = open(path_name_file_1, 'w') + file2.seek(0) + file2.write(text) + file2.close() + + return text + + security.declarePublic('create_Document') + def create_Document(self, name_file = None, object_portal_type = None): + """ + create PropertySheet in /var/lib/zope/Products/ERP5/Document/ + """ + path_name_file = os.path.join(ZOPE_INSTANCE_HOME, 'Document', str(name_file) + '.py') + #print path_name_file + file = open(path_name_file,'w') + file.seek(0) + + + string = '############################################################################# \n' + file.write(string) + string = '# \n' + file.write(string) + string = '# Copyright (c) 2002-2005 Nexedi SARL and Contributors. All Rights Reserved. \n' + file.write(string) + string = '# Jean-Paul Smets-Solanes <jp@nexedi.com> \n' + file.write(string) + string = '# Kevin Deldycke <kevin@nexedi.com> \n' + file.write(string) + string = '# Guy Oswald OBAMA <guy@nexedi.com> \n' + file.write(string) + string = '# \n' + file.write(string) + string = '# WARNING: This program as such is intended to be used by professional \n' + file.write(string) + string = '# programmers who take the whole responsability of assessing all potential \n' + file.write(string) + string = '# consequences resulting from its eventual inadequacies and bugs \n' + file.write(string) + string = '# End users who are looking for a ready-to-use solution with commercial \n' + file.write(string) + string = '# garantees and support are strongly adviced to contract a Free Software \n' + file.write(string) + string = '# Service Company \n' + file.write(string) + string = '# \n' + file.write(string) + string = '# This program is Free Software; you can redistribute it and/or \n' + file.write(string) + string = '# modify it under the terms of the GNU General Public License \n' + file.write(string) + string = '# as published by the Free Software Foundation; either version 2 \n' + file.write(string) + string = '# of the License, or (at your option) any later version. \n' + file.write(string) + string = '# \n' + file.write(string) + string = '# This program is distributed in the hope that it will be useful, \n' + file.write(string) + string = '# but WITHOUT ANY WARRANTY; without even the implied warranty of \n' + file.write(string) + string = '# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n' + file.write(string) + string = '# GNU General Public License for more details. \n' + file.write(string) + string = '# \n' + file.write(string) + string = '# You should have received a copy of the GNU General Public License \n' + file.write(string) + string = '# along with this program; if not, write to the Free Software \n' + file.write(string) + string = '# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \n' + file.write(string) + string = '# \n' + file.write(string) + string = '############################################################################## \n\n\n\n' + file.write(string) + + string = 'from AccessControl import ClassSecurityInfo \n\n' + file.write(string) + string = 'from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface \n' + file.write(string) + string = 'from Products.ERP5Type.Utils import assertAttributePortalType \n' + file.write(string) + string = 'from Products.ERP5Type.XMLObject import XMLObject \n\n' + file.write(string) + string = 'from Products.ERP5.Core.Node import Node \n\n' + file.write(string) + string = 'from Products.ERP5.Document.Entity import Entity \n\n' + file.write(string) + string = '#from Products.ERP5Type.Base import Base \n\n' + file.write(string) + string = 'class ' + str(name_file) + '(Node, XMLObject): \n' + file.write(string) + + + string = 2*' ' + '""" \n' + file.write(string) + string = 2*' ' + ' An ' + str(name_file) + ' object holds the information about \n' + file.write(string) + string = 2*' ' + ' an ' + str(name_file) + '. \n\n' + file.write(string) + + string = 2*' ' + ' ' + str(name_file) + ' objects can contain Coordinate objects \n' + file.write(string) + string = 2*' ' + ' as well a documents of various types. \n' + file.write(string) + + string = 2*' ' + ' ' + str(name_file) + ' objects can be synchronized accross multiple \n' + file.write(string) + string = 2*' ' + ' sites. \n' + file.write(string) + + string = 2*' ' + ' ' + str(name_file) + ' objects inherit from the Node base class \n' + file.write(string) + string = 2*' ' + ' (one of the 5 base classes in the ERP5 universal business model) \n' + file.write(string) + string = 2*' ' + '""" \n\n\n' + file.write(string) + + + string = 2*' ' + "meta_type = 'ERP5 " + str(name_file) + "' \n" + file.write(string) + string = 2*' ' + "portal_type = '" + str(object_portal_type) + "' \n" + file.write(string) + string = 2*' ' + "add_permission = Permissions.AddPortalContent \n" + file.write(string) + string = 2*' ' + "isPortalContent = 1 \n" + file.write(string) + string = 2*' ' + "isRADContent = 1 \n\n" + file.write(string) + + string = 2*' ' + "# Declarative security \n" + file.write(string) + string = 2*' ' + "security = ClassSecurityInfo() \n" + file.write(string) + string = 2*' ' + "security.declareObjectProtected(Permissions.View) \n\n" + file.write(string) + + string = 2*' ' + "# Declarative properties \n" + file.write(string) + string = 2*' ' + "property_sheets = ( PropertySheet.Base \n" + file.write(string) + string = 2*' ' + " , PropertySheet.XMLObject \n" + file.write(string) + string = 2*' ' + " , PropertySheet.CategoryCore \n" + file.write(string) + string = 2*' ' + " , PropertySheet.DublinCore \n" + file.write(string) + string = 2*' ' + " , PropertySheet.Arrow \n" + file.write(string) + string = 2*' ' + " , PropertySheet.Task \n" + file.write(string) + string = 2*' ' + " , PropertySheet." + str(name_file) + " \n" + file.write(string) + string = 2*' ' + " ) \n\n" + file.write(string) + + file.close() + + # get text to create a new Document in portal_classes + file1 = open(path_name_file,'r') + lines_list = file1.readlines() + text = '' + for line in lines_list: + text = text + line + file1.close() + + path_name_file_1 = '/var/lib/zope/Products/ERP5/Document/' + str(name_file) + '.py' + file2 = open(path_name_file_1,'w') + file2.seek(0) + file2.write(text) + file2.close() + + return text + +InitializeClass(Getter_Setter) +allow_class(Getter_Setter) + + + diff --git a/product/ERP5OOo/FieldHelpTopic.py b/product/ERP5OOo/FieldHelpTopic.py new file mode 100755 index 0000000000..77a47ecf61 --- /dev/null +++ b/product/ERP5OOo/FieldHelpTopic.py @@ -0,0 +1,35 @@ +from Globals import DTMLFile +from HelpSys import HelpTopic + +class FieldHelpTopic(HelpTopic.HelpTopic): + """A special help topic for fields. + """ + meta_type = 'Help Topic' + + def __init__(self, id, title, field_class, + permissions=None, categories=None): + self.id = id + self.title = title + self.field_class = field_class + + if permissions is not None: + self.permissions = permissions + if categories is not None: + self.categories = categories + + index_html = DTMLFile('dtml/FieldHelpTopic', globals()) + + def SearchableText(self): + """Full text of the Help Topic, for indexing purposes.""" + return "" # return self.index_html() + + def get_groups(self): + """Get form groups of this field. + """ + return self.field_class.form.get_groups() + + def get_fields_in_group(self, group): + """Get the fields in the group. + """ + return self.field_class.form.get_fields_in_group(group) + diff --git a/product/ERP5OOo/FieldRegistry.py b/product/ERP5OOo/FieldRegistry.py new file mode 100755 index 0000000000..e9b924438f --- /dev/null +++ b/product/ERP5OOo/FieldRegistry.py @@ -0,0 +1,175 @@ +import os +import OFS +from Globals import ImageFile +from FieldHelpTopic import FieldHelpTopic +from AccessControl import ClassSecurityInfo +from Products.PythonScripts.Utility import allow_class +from ZPublisher.HTTPRequest import FileUpload +from Globals import InitializeClass, get_request +from StringIO import StringIO +from zLOG import LOG +import getopt, sys, os +from urllib import quote + + +class FieldRegistry: + """A registry of fields, maintaining a dictionary with + the meta_type of the field classes as key and the field class as + values. Updates the Form as necessary as well. + """ + + # Declarative security + security = ClassSecurityInfo() + + def __init__(self): + """Initializer of FieldRegistry. + """ + self._fields = {} + + def get_field_class(self, fieldname): + """Get a certain field class by its name (meta_type) + fieldname -- the name of the field to get from the registry + """ + return self._fields[fieldname] + + def get_field_classes(self): + """Return all fields. + """ + return self._fields + + def registerField(self, field_class, icon=None): + """Register field with Formulator. + field_class -- the class of the field to be registered + icon -- optional filename of the icon + """ + # put it in registry dictionary + self._fields[field_class.meta_type] = field_class + # set up dummy fields in field's form + initializeFieldForm(field_class) + # set up the icon if a filename is supplied + if icon: + setupIcon(field_class, icon, 'Formulator') + + def registerFieldHelp(self, context): + """Register field help topics. + context -- product registration context object + """ + # get help folder for product + help = context.getProductHelp() + + for field_name, field_class in self._fields.items(): + # don't register help for internal fields + if (hasattr(field_class, 'internal_field') and + getattr(field_class, 'internal_field')): + continue + + # unregister any help topic already registered + if field_name in help.objectIds('Help Topic'): + help._delObject(field_name) + + # register help topic + ht = FieldHelpTopic(field_name, + "Formulator Field - %s" % field_name, + field_class) + + context.registerHelpTopic(field_name, ht) + + def initializeFields(self): + """Initialize all field classes in field forms to use actual field + objects so we can finally eat our own dogfood. + """ + # for each field, realize fields in form + # this is finally possible as all field classes are now + # fully defined. + for field_class in self._fields.values(): + field_class.form._realize_fields() + field_class.override_form._realize_fields() + field_class.tales_form._realize_fields() + +# initialize registry as a singleton +FieldRegistry = FieldRegistry() + +def initializeFieldForm(field_class): + """Initialize the properties (fields and values) on a particular + field class. Also add the tales and override methods. + """ + from Form import BasicForm + from DummyField import fields + + form = BasicForm() + override_form = BasicForm() + tales_form = BasicForm() + for field in getPropertyFields(field_class.widget): + form.add_field(field, "widget") + tales_field = fields.TALESField(field.id, + title=field.get_value('title'), + description="", + default="", + display_width=40, + required=0) + tales_form.add_field(tales_field, "widget") + + method_field = fields.MethodField(field.id, + title=field.get_value("title"), + description="", + default="", + required=0) + override_form.add_field(method_field, "widget") + + for field in getPropertyFields(field_class.validator): + form.add_field(field, "validator") + tales_field = fields.TALESField(field.id, + title=field.get_value('title'), + description="", + default="", + display_with=40, + required=0) + tales_form.add_field(tales_field, "validator") + + method_field = fields.MethodField(field.id, + title=field.get_value("title"), + description="", + default="", + required=0) + override_form.add_field(method_field, "validator") + + field_class.form = form + field_class.override_form = override_form + field_class.tales_form = tales_form + +def getPropertyFields(obj): + """Get property fields from a particular widget/validator. + """ + fields = [] + for property_name in obj.property_names: + fields.append(getattr(obj, property_name)) + return fields + +def setupIcon(klass, icon, repository): + """Load icon into Zope image object and put it in Zope's + repository for use by the ZMI, for a particular class. + klass -- the class of the field we're adding + icon -- the icon + """ + # set up misc_ respository if not existing yet + if not hasattr(OFS.misc_.misc_, repository): + setattr(OFS.misc_.misc_, + repository, + OFS.misc_.Misc_(repository, {})) + + # get name of icon in the misc_ directory + icon_name = os.path.split(icon)[1] + + # set up image object from icon file + icon_image = ImageFile(icon, globals()) + icon_image.__roles__ = None + + # put icon image object in misc_/Formulator/ + getattr(OFS.misc_.misc_, repository)[icon_name] = icon_image + + # set icon attribute in field_class to point to this image obj + setattr(klass, 'icon', 'misc_/%s/%s' % + (repository, icon_name)) + +InitializeClass(FieldRegistry) +allow_class(FieldRegistry) diff --git a/product/ERP5OOo/ScribusUtils.py b/product/ERP5OOo/ScribusUtils.py new file mode 100755 index 0000000000..f2ef4695c2 --- /dev/null +++ b/product/ERP5OOo/ScribusUtils.py @@ -0,0 +1,139 @@ +############################################################################## +# +# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved. +# Guy Oswald OBAMA <guy@nexedi.com> +# +# This program 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 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from Products.PythonScripts.Utility import allow_class +from ZPublisher.HTTPRequest import FileUpload +from xml.dom.ext.reader import PyExpat +from xml.dom import Node, minidom +from AccessControl import ClassSecurityInfo +from Globals import InitializeClass, get_request +from zipfile import ZipFile, ZIP_DEFLATED +from StringIO import StringIO +from zLOG import LOG +import imghdr +import random +import getopt, sys, os, string +from urllib import quote + + + +class ScribusParser: + """ + Parses a Scribus file + """ + + # Declarative security + security = ClassSecurityInfo() + + + security.declarePublic('getXmlObjectsProperties') + def getXmlObjectsProperties(self, xml_string): + # Create the PyExpat reader + reader = PyExpat.Reader() + + # Create DOM tree from the xml string + dom_tree = reader.fromString(xml_string) + + text_field_list = {} + + dom_root = dom_tree.documentElement + page_object_list = dom_root.getElementsByTagName("PAGEOBJECT") + + # Take Xml objects properties + for page_object in page_object_list: + text_field_properties = {} + field_name = None + for attribute in page_object.attributes: + node_name = str(attribute.nodeName) + node_value = str(attribute.nodeValue) + if node_name == 'ANNAME': + if node_value != '': + field_name = node_value + else: + text_field_properties[node_name] = node_value + if field_name != None: + text_field_list[field_name] = text_field_properties + + return text_field_list + + + security.declarePublic('getPropertiesConversion') + def getPropertiesConversion(self, text_field_list): + # Get Scribus field properties + + field_scribus_properties_dict = {} + + for field_name in text_field_list.keys(): + text_field_properties = text_field_list[field_name] + field_scribus_properties_dict[field_name] = text_field_properties['ANTOOLTIP'] + + widget_properties_list = [] + index = 1 + + while index < len(field_scribus_properties_dict): + for key, item in field_scribus_properties_dict.items(): + if string.atoi(item[:3]) == index: + property_field_list = item[4:].split('#') + widget_properties_buffer = {} + for property_field in property_field_list: + property_field_split = property_field.split(':') + if property_field_split[0] == 'items': + property_field_split[1] = property_field_split[1].split('|') + widget_properties_buffer[property_field_split[0]] = property_field_split[1] + widget_properties_list.append((key, widget_properties_buffer)) + break + index = index + 1 + + for key, item in field_scribus_properties_dict.items(): + if string.atoi(item[:3]) == 999: + property_field_list = item[4:].split('#') + widget_properties_buffer = {} + for property_field in property_field_list: + property_field_split = property_field.split(':') + widget_properties_buffer[property_field_split[0]] = property_field_split[1] + widget_properties_list.append((key, widget_properties_buffer)) + + return widget_properties_list + + + security.declareProtected('Import/Export objects', 'getContentFile') + def getContentFile(self, file_descriptor): + """ Get file content """ + return file_descriptor.read() + """ + def getContentFile(self, file_path): + # Verify that the file exist + if not os.path.isfile(file_path): + output("ERROR: " + file_path + " doesn't exist.") + return None + + # Get file content + file_path = os.path.abspath(file_path) + file_object = open(file_path, 'r') + + return file_object.read() + """ + +InitializeClass(ScribusParser) +allow_class(ScribusParser) + + + \ No newline at end of file -- 2.30.9