Commit 016ff006 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Improve/make it work by thomas.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@4537 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 27269244
# This code is to be removed in near future, because we will migrate
# to a Python Script. This is put temporarily for a demo.
def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
portal_skins_folder=None, object_portal_type=None, object_title=None, module_id=None,
module_title=None, selection_index=None, selection_name=None, import_scribus_file=None,
import_pdf_file=None, **kw) :
import_pdf_file=None, option_html=None, import_image_1=None, import_image_2=None,
import_image_3=None, **kw) :
""" Creates a module, portal_type and ERP5Form from a scribus and
PDFForm file"""
context = self
......@@ -13,6 +17,13 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
from Products.ERP5Form.CreatePropertySheet import LocalGenerator
generator = LocalGenerator()
# importing module to get an access to the 'searchFolder' method
# needed to be able to list the objects in 'list_object_view' form
from Products.ERP5.ERP5Site import ERP5Site
from zLOG import LOG
#import Products.ERP5Form.Folder
# TODO
# - Allow in the module only the new document, we must activate the filter
# - handle an optionnal "description" parameter
......@@ -27,7 +38,10 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
portal_types = portal.portal_types
object_portal_type_id = object_portal_type
# Create a new portal_type for the module
#
portal_types.manage_addTypeInformation( 'ERP5 Type Information'
, typeinfo_name = 'ERP5Type: ERP5 Folder'
, id = module_portal_type
......@@ -38,15 +52,19 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
# Set allowed content types
module_portal_type_value.allowed_content_types = (object_portal_type_id, )
module_portal_type_value.filter_content_types = 1
# building a list of all the portal_type actions
action_list = module_portal_type_value.listActions()
# cleaning all portal_type informations
module_portal_type_value.deleteActions(selections=range(0, len(action_list)))
# declaring form names
form_view_pdf = object_portal_type_id.replace(' ','') + '_view' +\
object_portal_type_id.replace(' ','') + 'AsPdf'
form_view_list = object_title.replace(' ','') + 'Module_view' +\
object_portal_type_id.replace(' ','') + 'List'
# declaring css dtml name
form_css_id = object_portal_type_id.replace(' ','') + '.css'
# Parameters to addAction : id, name, action, condition, permission,
# category, visible=1, REQUEST=None
module_portal_type_value.addAction( "view"
......@@ -57,13 +75,13 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
, "object_view"
)
# SKIN PROCESSING
# Create the skin directory if does not exist yet
portal_skins_folder_name = portal_skins_folder
portal_skins = portal.portal_skins
if not portal_skins_folder_name in portal.portal_skins.objectIds():
portal_skins.manage_addFolder(portal_skins_folder_name)
skin_folder = portal.portal_skins[portal_skins_folder_name]
# Add new folders into skin paths.
for skin_name, selection in portal_skins.getSkinPaths():
selection = selection.split(',')
......@@ -75,30 +93,52 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
, add_skin = 1
)
# Create the default ERP5 Form in order to view the object
# ERP FORM PROCESSING
# Create the default ERP5 Form in order to view the objects
form_view_id = object_portal_type_id.replace(' ','') + '_view'
factory = skin_folder.manage_addProduct['ERP5Form']
factory.addERP5Form( form_view_id
, title = object_title
)
form_view_id_object = skin_folder[form_view_id]
form_view_id_object.rename_group('Default', 'left')
default_groups = ['right', 'center', 'bottom', 'hidden']
for group in default_groups:
form_view_id_object.add_group(group)
#if option_html != None :
# form_view_id_object.rename_group('Default')
#form_view_id_object.rename_group('Default', 'left')
if option_html != 1:
# using default ERP5 positioning convention
# creating groups
form_view_id_object.rename_group('Default','left')
default_groups = ['right', 'center', 'bottom', 'hidden']
for group in default_groups:
form_view_id_object.add_group(group)
# page groups corresponding to graphic view are defined on the flyn
# when parsing pages to get fields.
# default field will be removed at the end
# Define CSS file and object informations
# first CSS file name
form_css_id = object_portal_type_id.replace(' ','') + '_css.css'
# then CSS content object (string)
form_css_content = ""
#properties_css_dict is used to store class informations
properties_css_dict = {}
# Create Module ERP5 Form in order to view the module
object_title_view = object_title + ' Module View'
factory = skin_folder.manage_addProduct['ERP5Form']
factory.addERP5Form( form_view_list
, title = object_title_view
)
)
form_view_list_object = skin_folder[form_view_list]
form_list_id = form_view_list_object.id
form_list = form_view_list_object.restrictedTraverse(form_list_id)
#defining groups for objects listing
form_view_list_object.rename_group('Default', 'left')
#default_groups = ['right', 'center', 'bottom', 'hidden']
default_groups = ['right', 'center', 'bottom', 'hidden']
# adding groups
for group in default_groups:
form_view_list_object.add_group(group)
......@@ -106,17 +146,14 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
for word in module_title.split():
title_module += str(word.capitalize() + ' ')
# Add ListBox Field
# Add ListBox Field to list the created objects
id = 'listbox'
title = title_module
field_type = 'ListBox'
form_view_list_object.manage_addField(id, title, field_type)
# manage ListBox settings
values_settings = {}
values_settings['pt'] = "form_list"
values_settings['action'] = "Base_doSelect"
......@@ -127,11 +164,24 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
# manage edit property of ListBox
field_attributes = getattr(form_view_list_object, id)
field_attributes.values['lines'] = 20
# adding field columns
field_attributes.values['columns'] = [('id', 'ID'), ('title', 'Title'), ('description', 'Description')]
field_attributes.values['list_action'] = 'list'
field_attributes.values['search'] = 1
field_attributes.values['select'] = 1
field_attributes.values['selection_name'] = '%s_selection' % module_id
# adding 'list_method' to be able to list the objects of a folder
# WARNING : this field does not contains the name of the method (as
# a string instance) but the method itself (as method instance)
list_method = getattr(ERP5Site,'searchFolder')
# a stange BUG occurs when saving method in field_attributes
# method adress is well get and saved in the listField
# but crashing when registrering new portal type inside
# erp5... I do not know why !
#field_attributes.values['list_method'] = list_method
print "METHOD : name = %s" % list_method.__name__
print "METHOD : type = %s" % list_method.__class__
print "METHOD : doc = %s" % list_method.__doc__
form_id = form_view_id_object.id
form = form_view_id_object.restrictedTraverse(form_id)
......@@ -139,93 +189,290 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
# import and manage Scribus File
xml_string = ScribusParser.getContentFile(import_scribus_file)
page_number_int = 0
if xml_string == None:
#print "no field was defined in the Scribus file"
LOG("ScribusParser",1,"Scribus file is empty !")
print "no field was defined in the Scribus file"
pass
else:
# get properties from Scribus File
output_string = str(xml_string)
#getting page objects with their attributes
#LOG("ScribusParser",0,"getXmlObjectProperties...")
print " createmodule > ScribusParser.getXmlObjectProperties"
text_field_list = ScribusParser.getXmlObjectsProperties(xml_string)
print " createmodule < ScribusParser.getXmlObjectProperties\n"
#splitting tooltip-text to recover usefull attributes
#LOG("ScribusParser",0,"getPropertiesConversion...")
print " createmodule > ScribusParser.getPropertiesConversion"
widget_properties = ScribusParser.getPropertiesConversion(text_field_list)
print " createmodule < ScribusParser.getPropertiesConversion\n"
# add field from OrderedWidgetProperties in ERP5 Module created
radiofield_widget_properties = {}
position = {}
# personal_properties is used to create PropertySheet
personal_properties_list = []
for index in range(len(widget_properties)):
id = str(widget_properties[index][0])
properties_field = widget_properties[index][1]
page_number_int = len(widget_properties)
# declaring dicts used to generate CSS file
# css_page is a class container. each class is composed in the css_page
# before being saved in a css_dict
properties_css_page = {}
# css_dict_head contains all the 'global' class, reffering to PAGE
properties_css_dict_head = {}
# css_dict_standard contains all the fields classes, when no error occurs
properties_css_dict_standard = {}
# css_dict_error contains the same thing, but in case error occurs.
# there background is different so that users can see where the problem
# is on the graphic view
properties_css_dict_error = {}
# css_dict_err_d contains coordinates and color to display text-error
properties_css_dict_err_d = {}
# declaring page size
# FIXME : this value has to be taken from the image size or the document size.
# to be dynamicly set
page_height = 850
page_width = 610
# DO NOT WORK !
# print "opening image"
# page_image = Image.open(import_image_1)
# print "getting properties"
# page_image_properties = page_image.size
# print page_image_properties
# print " getting width"
# page_width = int(page_image_properties[1])
# page_height = int(page_image_properties[0])
LOG("ScribusParser",0,"begining interpretation of data")
print " createmodule > begining data interpretation"
#iterating pages
for page_iterator in range(len(widget_properties)):
page_number = str(page_iterator)
page_content = widget_properties[page_number]
page_id = "page_" + page_number
if option_html == 1:
# Processing current page for CSS data
# getting properties
properties_css_page = {}
properties_css_page['position'] = 'relative'
if page_iterator == 0:
properties_css_page['margin-top'] = "0px"
else:
properties_css_page['margin-top']= "%spx" % (page_height + 20)
# adding properties dict to golbal dict
properties_css_dict_head[page_id] = properties_css_page
# creating image class for background
properties_css_background = {}
# making background id
properties_css_background_id = page_id + '_background'
#getting properties
properties_css_background['position'] = 'absolute'
properties_css_dict_head[properties_css_background_id] = properties_css_background
#creating corresponding page group to form
if page_number == '0':
# if first page, renaming 'default' group into 0 group
form_view_id_object.rename_group('Default',page_id)
print " > renamed 'default' group to %s" % page_id
else :
# adding bandt new group for page
form_view_id_object.add_group(page_id)
print " > added new group %s " % page_id
if properties_field.has_key('type'):
field_type = str(properties_field['type'])
title = str(properties_field['title'])
form_view_id_object.manage_addField(id, title, field_type)
context = skin_folder[form_view_id]
form_id = context.id
# modify value of property
form = context.restrictedTraverse(form_id)
field_attributes = getattr(form, id)
type = 'string'
if field_type == 'DateTimeField':
type = 'date'
field_attributes.values['input_order'] = properties_field['input_order']
field_attributes.values['date_only'] = properties_field['date_only']
field_attributes.values['required'] = properties_field['required']
elif field_type == 'RelationStringField':
portal_type_item = properties_field['portal_type'].capitalize()
field_attributes.values['portal_type'] = [(portal_type_item, portal_type_item)]
field_attributes.values['base_category'] = properties_field['base_category']
field_attributes.values['catalog_index'] = properties_field['catalog_index']
field_attributes.values['default_module'] = properties_field['default_module']
elif field_type == 'RadioField':
radiofield_widget_properties[id] = {'description' : ''}
items = []
for word_item in properties_field['items']:
items.append((word_item, word_item.capitalize()))
field_attributes.values['items'] = items
position[id] = properties_field['order']
# check that the property is local ...
if id.startswith('my') and not (
# ... and not in black list
# FIXME: this list must be configurable outside this script
id.startswith('my_source') or
id.startswith('my_destination') or
id in ('my_start_date', 'my_stop_date') ) :
personal_properties = { 'id' : id[3:],
'description' : '',
'type' : type,
'mode': 'w' }
personal_properties_list.append(personal_properties)
#iterating pageobjects in page
for index in range(len(page_content)):
(id, properties_field) = page_content[index]
if properties_field.has_key('type'):
field_type = str(properties_field['type'])
title = str(properties_field['title'])
form_view_id_object.manage_addField(id, title, field_type)
context = skin_folder[form_view_id]
form_id = context.id
if option_html ==1:
# Processing object for CSS data
#declaring dict containing all css data
# _stand for general display
properties_css_object_stand = {}
# _error when an error occurs
properties_css_object_error = {}
# _err_d to diplay the text error
properties_css_object_err_d = {}
#defining global properties
properties_css_object_stand['position'] = 'absolute'
properties_css_object_error['position'] = 'absolute'
properties_css_object_err_d['position'] = 'absolute'
properties_css_object_stand['padding'] = '0px'
properties_css_object_error['padding'] = '0px'
properties_css_object_err_d['padding'] = '0px'
#getting position and size
properties_css_object_stand['width'] = str(properties_field['size_x']) + 'px'
properties_css_object_error['width'] = str(properties_field['size_x']) + 'px'
properties_css_object_stand['height'] = str(properties_field['size_y']) + 'px'
properties_css_object_error['height'] = str(properties_field['size_y']) + 'px'
properties_css_object_stand['margin-left'] = str(properties_field['position_x']) + 'px'
properties_css_object_error['margin-left'] = str(properties_field['position_x']) + 'px'
properties_css_object_err_d['margin-left'] = str(page_width + 20 ) + 'px'
properties_css_object_stand['margin-top'] = str(properties_field['position_y']) + 'px'
properties_css_object_error['margin-top'] = str(properties_field['position_y']) + 'px'
properties_css_object_err_d['margin-top'] = str(properties_field['position_y']) + 'px'
# adding special text_color for text error
properties_css_object_err_d['color'] = 'rgb(255,0,0)'
# adding properties to relatives dicts
properties_css_dict_standard[id] = properties_css_object_stand
properties_css_dict_error[id] = properties_css_object_error
properties_css_dict_err_d[id] = properties_css_object_err_d
# then getting additional properties
if properties_field['required'] ==1:
# field is required: using special color
# color is specified as light-blue when standard
# color = 'green' when error
properties_css_dict_standard[id]['background'] = 'rgb(192,192,255)'
properties_css_dict_error[id]['background'] = 'rgb(128,128,255)'
else:
properties_css_dict_standard[id]['background'] = '#F6FFFF'
properties_css_dict_error[id]['background'] = 'rgb(255,64,64)'
#adding field to the corresponding page group
position[id] = page_id
form_view_id_object.move_field_group(id,'page_0',position[id])
#print " > added %s to %s (graphic mode) " % (id,position[id])
#print properties_css_dict_error[id]['background']
#print properties_css_dict_standard[id]['background']
else:
# no graphic view
# position is defined corresponding to ERP5 view
position[id] = properties_field['order']
form_view_id_object.move_field_group(id,'left',position[id])
#print " > added %s to %s (ERP mode)" % (id,position[id])
# modify value of property
form = context.restrictedTraverse(form_id)
field_attributes = getattr(form, id)
type = 'string'
# Order field
for field in form.get_fields():
key = str(field.id)
if position.has_key(key) == 1 and position[key] == 'right':
field.move_field_group(key, 'left', 'right')
if field_type == 'DateTimeField':
type = 'date'
field_attributes.values['input_order'] = properties_field['input_order']
field_attributes.values['date_only'] = properties_field['date_only']
field_attributes.values['required'] = properties_field['required']
elif field_type == 'RelationStringField':
portal_type_item = properties_field['portal_type'].capitalize()
field_attributes.values['portal_type'] = [(portal_type_item, portal_type_item)]
field_attributes.values['base_category'] = properties_field['base_category']
field_attributes.values['catalog_index'] = properties_field['catalog_index']
field_attributes.values['default_module'] = properties_field['default_module']
elif field_type == 'RadioField':
radiofield_widget_properties[id] = {'description' : ''}
items = []
for word_item in properties_field['items'].split('|'):
items.append((word_item, word_item.capitalize()))
field_attributes.values['items'] = items
elif field_type in ['StringField','IntegerField','Floatfield']:
field_attributes.values['maximum_input'] = properties_field['maximum_input']
#print " => saved 'maximum_input' value"
# check that the property is local ...
if id.startswith('my') and not (
# ... and not in black list
# FIXME: this list must be configurable outside this script
id.startswith('my_source') or
id.startswith('my_destination') or
id in ('my_start_date', 'my_stop_date') ) :
personal_properties = { 'id' : id[3:],
'description' : '',
'type' : type,
'mode': 'w' }
personal_properties_list.append(personal_properties)
# adding 'page_end' class to add a div at the end of the last page
# in order to display the full last page under Konqueror
properties_css_page = {}
properties_css_page['position'] = 'relative'
properties_css_page['margin-top'] = "%spx" % str( page_height)
properties_css_dict_head['page_end'] = properties_css_page
print " createmodule < end of data interpretation"
print "\n"
# CSS CLASS
if option_html ==1:
print " createmodule > printing output from css_class_generator"
form_css_content = "/*-- special css form generated through ScribusUtils module --*/"
form_css_content += "/*-- to have a graphic rendering with 'form_html' page template --*/\n"
form_css_content += "/* head : classes declared for general purpose */\n"
# iterating classes in document's head
for class_name in properties_css_dict_head.keys():
# getting class properties_dict
class_properties = properties_css_dict_head[class_name]
# joining exerything
output_string = "." + str(class_name) + " {" \
+ "; ".join(["%s:%s" % (id, val) for id, val in class_properties.items()]) \
+ "}"
# adding current line to css_content_object
form_css_content += output_string + "\n"
form_css_content += "\n/* standard field classes */ \n"
# adding standard classes
for class_name in properties_css_dict_standard.keys():
class_properties = properties_css_dict_standard[class_name]
output_string = "." + str(class_name) + " {" \
+ "; ".join(["%s:%s" % (id,val) for id,val in class_properties.items()]) \
+ "}"
form_css_content += output_string + "\n"
form_css_content += "\n/* error field classes */\n"
#adding error classes
for class_name in properties_css_dict_error.keys():
class_properties = properties_css_dict_error[class_name]
output_string = "." + str(class_name) + "_error {" \
+ "; ".join(["%s:%s" % (id,val) for id, val in class_properties.items()]) \
+ "}"
form_css_content += output_string + "\n"
form_css_content += "\n/* text_error field classes */ \n"
# adding field error classes
for class_name in properties_css_dict_err_d.keys():
class_properties = properties_css_dict_err_d[class_name]
output_string = "." + str(class_name) + "_error_display {" \
+ "; ".join(["%s:%s" % (id,val) for id,val in class_properties.items()]) \
+ "}"
form_css_content += output_string + "\n"
#print form_css_content
print " createmodule < end output \n"
print " createmodule > creating output CSS file"
factory.addDTMLDocument(form_css_id,"css",form_css_content)
print " createmodule < CSS file creation\n"
# manage_settings
print " createmodule > managing Form settings"
# manage global form settings
values = {}
values['title'] = str(object_portal_type)
values['row_length'] = 4
values['name'] = str(form_view_id)
values['pt'] = "form_view"
# the 'pt' field has to be changed from 'form_view' to 'form_html'
# when generating graphic interface.
if option_html ==1:
values['pt'] = "form_html"
else:
values['pt'] = "form_view"
values['action'] = "Base_edit"
values['update_action'] = ""
values['method'] = 'POST'
......@@ -233,29 +480,119 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
values['encoding'] = "UTF-8"
values['stored_encoding'] = 'UTF-8'
values['unicode_mode'] = 0
# set the form settings
for key, value in values.items():
setattr(form, key, value)
print " createmodule < settings managed\n"
print " createmodule > managing PDF settings"
# Import and manage PDF File before filling of default TALES expressions in cells
# first import the PDFForm in the skin folder
factory.addPDFForm(form_view_pdf, object_title, pdf_file = import_pdf_file)
for c in skin_folder.objectValues():
if c.getId() == form_view_pdf :
for cell_name in c.getCellNames():
print " %s selected" % c.getId()
cell_name_list = c.getCellNames()
print " %s" % cell_name_list
for cell_name in cell_name_list:
if cell_name[0:3] == 'my_':
cellName = []
cellName_list = []
for word in cell_name[3:].split('_'):
word = word.capitalize()
cellName.append(word)
if cellName[-1] == 'List' :
TALES = 'python: ", ".join(here.get' + "".join(cellName) + '())'
cellName_list.append(word)
if cellName_list[-1] == 'List' :
TALES = 'python: ", ".join(here.get' + "".join(cellName_list) + '())'
else :
TALES = 'python: here.get' + "".join(cellName) + '()'
TALES = 'python: here.get' + "".join(cellName_list) + '()'
print " cell : %s => TALES expression : %s " % (cell_name,TALES)
c.setCellTALES(cell_name, TALES)
print " createmodule < PDF settings managed\n"
print " createmodule > importing background pictures"
# Import and register background images for HTML display
if option_html == 1:
# saving pdf content to aspecific file on hard disk
temp_pdf = open('/tmp/ScribusUtilsTempPDF.tmp','w')
# moving cursor to begining of file
import_pdf_file.seek(0)
# reading content
temp_content = import_pdf_file.read()
print " > inputfile read : %sb" % len(temp_content)
# writing content to outputfile
temp_pdf.write(temp_content)
print " > inputfile written"
# closing outputfile
temp_pdf.close()
# running first conversion from PDF to PPM
import commands
result = commands.getstatusoutput('pdftoppm -r 72 /tmp/ScribusUtilsTempPDF.tmp /tmp/ScribusUtilsTempPPM')
print " > pdftoppm result(%s) : %s" % (result[0],result[1])
# running second conversion from PPM to JPEG
result = commands.getstatusoutput('convert /tmp/ScribusUtilsTempPPM* jpg:/tmp/ScribusUtilsTempJPG')
print " > convert result(%s) : %s" % (result[0],result[1])
# getting list of resulting pictures
result = commands.getstatusoutput('ls /tmp/ | grep ScribusUtilsTempJPG')
print " > getting list of final pictures"
image_number = 0
for image in result[1].split('\n'):
# result[1] contains the output string
# splitting this output string in lines to get
# the string parameters
# opening resulting pictures
temp_jpg = open('/tmp/%s' % image,'r')
print " > open picture : len=%sb" % len(temp_jpg.read())
# saving content to zope folder
form_page_id = object_portal_type_id.replace(' ','')+ "_background_" + str(image_number)
add_image = skin_folder.manage_addProduct['OFSP'].manage_addImage
add_image(form_page_id,temp_jpg,"background image")
# incrementing image number before going to next one
image_number +=1
# deleting temporary files
result = commands.getstatusoutput('rm -f /tmp/ScribusUtilsTemp*')
print " > remove temp files"
#factory = skin_folder.manage_addProduct['Images']
"""
if page_number_int > 0 :
# image specified for first page_element
form_page_id = object_portal_type_id.replace(' ','') + "_background_" + "0"
add_image = skin_folder.manage_addProduct['OFSP'].manage_addImage
add_image(form_page_id,import_image_1,"background image")
if page_number_int > 1 :
form_page_id = object_portal_type_id.replace(' ','') + "_background_" + "1"
add_image = skin_folder.manage_addProduct['OFSP'].manage_addImage
add_image(form_page_id,import_image_2,"background image 2")
if page_number_int > 2:
form_page_id = object_portal_type_id.replace(' ','') + "_background_" + "2"
add_image = skin_folder.manage_addProduct['OFSP'].manage_addImage
add_image(form_page_id,import_image_3,"background image 3")
"""
print " createmodule < background pictures imported\n"
# get background picture size.
#skin_folder
# Create PropertySheet and Document
print " createmodule > PropertySheet and Document creation"
name_file = ''
title_module = ''
for word in object_portal_type.split():
......@@ -263,15 +600,21 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
title_module += str(word.capitalize() + ' ')
generator.generateLocalPropertySheet(name_file, personal_properties_list)
print " PropertySheet : %s" % name_file
generator.generateLocalDocument(name_file, object_portal_type)
print " Document : %s" % name_file
# Reload register local property sheets
from Products.ERP5Type.Utils import initializeLocalPropertySheetRegistry
initializeLocalPropertySheetRegistry()
# Reload register local classes
from Products.ERP5Type.Utils import initializeLocalDocumentRegistry
initializeLocalDocumentRegistry()
print " createmodule < PropertyShett and Document imported\n"
# Then add the portal_type corresponding to the new object
typeinfo_name_ERP5Type = str('ERP5Type: ERP5 ' + object_portal_type)
......@@ -340,5 +683,3 @@ def ERP5Site_createModuleScribus(self, form_id=None, module_portal_type=None,
portal.REQUEST.RESPONSE.redirect( redirect_url )
......@@ -2,6 +2,7 @@
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Guy Oswald OBAMA <guy@nexedi.com>
# thomas <thomas@nexedi.com>
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
......@@ -19,6 +20,11 @@
#
##############################################################################
# This code is under refactoring. This code will change in near future
# with a lot of cleanups. This is stored only for a temporary purpose.
# Do not rely on the real implementation. It is assumed that the code is
# improved and modified significantly by thomas.
from Products.PythonScripts.Utility import allow_class
from ZPublisher.HTTPRequest import FileUpload
from xml.dom.ext.reader import PyExpat
......@@ -30,98 +36,535 @@ from StringIO import StringIO
from zLOG import LOG
import imghdr
import random
import getopt, sys, os, string
import getopt, sys, os
from urllib import quote
class ScribusParser:
"""
Parses a Scribus file
Parses a Scribus file with PDF-elements inside
"""
# Declarative security
#declare security
security = ClassSecurityInfo()
security.declarePublic('getObjectTooltipProperty')
def getObjectTooltipProperty(self, check_key, default_value, object_name, object_dict):
"""
check if 'check_key' exists in 'object_dict' and has a value
if true, then returns this value, else returns 'default_value' and log 'object_name'
"""
#return object_dict.get(check_key, None) or default_value
if object_dict.has_key(check_key):
# 'check_key' exists
if len(object_dict[check_key]) != 0:
# check_key corresponding value is not null
# returning this value
return object_dict[check_key]
else:
# check_key is null, logging and asigning default value
print " > " + str(object_name) + " has an invalid '" + str(check_key) \
+ "' : using default = " + str(default_value)
LOG("WARNING : " + str(object_name),0,"invalid " + str(check_key) \
+ ": using " + str(default_value))
return default_value
else:
# check_key is null, logging and asigning default value
print " > " + str(object_name) + " has no '" + str(check_key) \
+ "' : using default = " + str(default_value)
LOG("WARNING : " + str(object_name),0,"no " + str(check_key) \
+ ": using " + str(default_value))
return default_value
security.declarePublic('getXmlObjectsProperties')
security.declarePublic('getStringInt')
def getStringInt(self,input_string):
"""
convert a string containing an integer or a long number
into an integer, as should do the int() function (if it
was not crashing when trying to do such a convertion).
This function is used to convert position and size values
to integers to prevent script from crashing.
"""
return int(input_string.split('.')[0])
security.declarePublic('getXmlObjectProperties')
def getXmlObjectsProperties(self, xml_string):
# Create the PyExpat reader
"""
takes a string containing a whole document and returns
a full dict of 'PAGE', containing a dict of 'PAGEOBJECT',
containing a dict of all the relative attributes
"""
#ERP5 access_type
#Create the PyExpat reader
print "\n => ScibusParser.getXmlObjectProperties"
print " > create reader"
LOG("ScribusUtils",1,"create reader")
reader = PyExpat.Reader()
# Create DOM tree from the xml string
print " > create DOM tree"
dom_tree = reader.fromString(xml_string)
text_field_list = {}
#dom_tree = minidom.parse(xml_string)
##External script acces_type
## testing procedure outside erp5. Put these lines in comment if this
## module is called inside erp5.
#print " => opening socket..."
#sock = open(xml_string)
#print " => reading the whole file..."
#dom_tree = minidom.parse(sock)
#print " => closing socket..."
#sock.close()
# creating the root from the input file
# does not depend on the kind of access (w or w/o erp5)
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)
#making a listing of all the PAGE object
print " > making listing of all PAGE objects"
page_list = dom_root.getElementsByTagName("PAGE")
returned_page_dict = {}
#for each PAGE object, searching for PAGEOBJECT
for page in page_list:
# getting page number
# parsing method from the previous ScribusUtils
page_number = -1
for attribute in page.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
if node_name == 'NUM':
page_number = node_value
print " > PAGE NUM=" + str(page_number)
# making a listing of all PAGEOBJECT in a specified PAGE
page_object_list = page.getElementsByTagName("PAGEOBJECT")
# initialising global output dictionary containing pages of elements
returned_page_object_dict = {}
# for each PAGEOBJECT, building dict with atributes
for page_object in page_object_list:
# initialising
returned_page_object = {}
field_name = None
#iterating PAGEOBJECT attributes
#old parsing method emlployed also here
for attribute in page_object.attributes:
node_name = str(attribute.nodeName)
node_value = str(attribute.nodeValue)
#iterating through PAGEOBJECT attributes
#for attribute in page_object.attributes.keys():
# node_name = str(attribute)
# node_value = str(page_object.attributes[attribute].value)
if node_name == 'ANNAME':
if node_value != '':
#if 'PAGEOBJECT' contains an attribute 'ANNAME' not null then
#this value is considered as the 'PAGEOBJECT' name
field_name = node_value.replace(' ','_')
else:
#for others attributes, just adding them to the dictionary as
#standard attributes
returned_page_object[node_name] = node_value
if field_name != None:
#if 'PAGEOBJECT' has a valid name, then adding it to the global
#dictionary containing all the 'PAGEOBJECT' of the 'PAGE'
returned_page_object_dict[field_name] = returned_page_object
print " > PAGEOBJECT = " + str(field_name)
#after having scanned all 'PAGEOBJECT' from a 'PAGE', adding the
#relatives information to the list of 'PAGE' before going to the next one
#in case the page is not empty
if len(returned_page_object_dict) != 0:
returned_page_dict[page_number] = returned_page_object_dict
print "=> end ScribusParser.getXmlObjectProperties"
return returned_page_dict
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))
def getPropertiesConversion(self, text_page_dict):
"""
takes a dict generated from 'getXmlObjectsProperties' method and returns a
dict of PAGE including a list with usefull 'PAGEOBJECT' attributes updated
with standard attributes and special informations contained in the
'ANTOOLTIP' attribute.
usefull attributes are
- position & size
- type & inputformat (for erp5 and html)
- creation order (using 'nb' property)
- erp5 relative position (left, right, etc.)
- title information
- other properties (read_only, multiline, etc.)
- etc.
for each PAGE, all PAGEOBJECT are sorted according to their creation order
'nb'
"""
print "\n => ScribusParser.getPropertiesConversion"
returned_page_dict = {}
# declaring ScribusParser object to run other functions
sp = ScribusParser()
return widget_properties_list
for page_number in text_page_dict.keys():
# iterating through 'PAGE' object of the document
# id = page_number
# content = page_content
page_content = text_page_dict[page_number]
print " => PAGE = " + str(page_number)
# declaring special lists used to generate nb for all objects
# this 'nb' property is usefull to define the object creation order
# all objects are sorted (has nb / has no nb) and all objects without
# nb attribte are added t othe end of the 'has nb' list
nb_property_nbkey_list = []
nb_property_nonbkey_list = []
# declaring output object
returned_object_dict = {}
# if page_content.haskey('my_fax_field')
# print "my_fax_field"
for object_name in page_content.keys():
# iterating through 'PAGEOBJECT' of the page
# id = object_name
# content = object_content
object_content = page_content[object_name]
print " => PAGEOBJECT = " + str(object_name)
# recovering other attributes from 'ANTOOLTIP'
text_tooltipfield_properties = object_content['ANTOOLTIP']
#declaring output file
tooltipfield_properties_dict = {}
#splitting the different attributes
tooltipfield_properties_list = text_tooltipfield_properties.split('#')
print " " + str(tooltipfield_properties_list)
# test if first argument is nb according to previous naming-conventions
# i.e composed of three digits without id 'nb:' written
if str(tooltipfield_properties_list[0]).isdigit():
# first value of tooltilfield is digit : assuming this is an creation-order
# information compliant with the previous naming convention
# modifying this field to make it compatible with new convention
print " => first element = " + str(tooltipfield_properties_list[0] + " is digit...")
LOG("WARNING : " + str(object_name),0,"out-of-date naming convention found" \
+ "for tooltipfield, please check naming_conventions")
temp_nb = tooltipfield_properties_list[0]
# deleting actual entry
tooltipfield_properties_list.remove(temp_nb)
# adding new entry to the list
temp_nb_text = "nb:" + str(temp_nb)
tooltipfield_properties_list.append(temp_nb_text)
# end of translating work to get new standard compliant code
for tooltipfield_property in tooltipfield_properties_list:
#printing each property before spliting
print " " + str(tooltipfield_property)
# splitting attribute_id / attribute_value
tooltipfield_properties_split = tooltipfield_property.split(':')
if len(tooltipfield_properties_split) == 2:
tooltipfield_id = tooltipfield_properties_split[0]
tooltipfield_value = tooltipfield_properties_split[1]
# making dictionary from 'ANTOOLTIP' attributes
tooltipfield_properties_dict[tooltipfield_id] = tooltipfield_value
# end of 'ANTOOLTIP' parsing
# getting usefull attributes from scribus 'PAGEOBJECT' and 'ANTOOLTIP'
# --------------------------------------------------------------------
object_properties = {}
# getting object position and size
object_properties['position_x'] = sp.getObjectTooltipProperty('XPOS','0',object_name,object_content)
object_properties['position_y'] = sp.getObjectTooltipProperty('YPOS','0',object_name,object_content)
object_properties['size_x'] = sp.getObjectTooltipProperty('WIDTH','100',object_name,object_content)
object_properties['size_y'] = sp.getObjectTooltipProperty('HEIGHT','17',object_name,object_content)
# converting values to integer-compliant to prevent errors when using them
object_properties['position_x'] = str(float(object_properties['position_x']))
object_properties['position_x'] = str(sp.getStringInt(object_properties['position_x']))
object_properties['position_y'] = str(sp.getStringInt(object_properties['position_y']))
object_properties['size_x'] = str(sp.getStringInt(object_properties['size_x']))
object_properties['size_y'] = str(sp.getStringInt(object_properties['size_y']))
# getting object title
# object title can only be user-specified in the 'tooltip' dict
object_properties['title'] = sp.getObjectTooltipProperty('title', object_name, object_name, tooltipfield_properties_dict)
# getting object order position for erp5 form
temp_order = sp.getObjectTooltipProperty('order','none',object_name,tooltipfield_properties_dict)
if temp_order not in ['left','right']:
# temp_order invalid
# trying to get it from document
if sp.getStringInt(object_properties['position_x']) > 280.0 :
temp_order = 'right'
else :
temp_order = 'left'
object_properties['order'] = temp_order
# getting special ANFLAG sub-properties
temp_ANFLAG = long(sp.getObjectTooltipProperty('ANFLAG','0',object_name,object_content))
# initialising results
anflag_properties = {}
anflag_properties['noScroll'] = 0
anflag_properties['noSpellCheck'] = 0
anflag_properties['editable'] = 0
anflag_properties['password'] = 0
anflag_properties['multiline'] = 0
anflag_properties['noExport'] = 0
anflag_properties['required'] = 0
anflag_properties['readOnly'] = 0
# analysing result
print " => ANFLAG = " + str(object_content['ANFLAG'])
if temp_ANFLAG - 8388608 >= 0:
# substracting value
temp_ANFLAG = temp_ANFLAG - long(8388608)
# 'do not scroll' field
# adding property
anflag_properties['noscroll'] = 1
if temp_ANFLAG - 4194304 >= 0:
temp_ANFLAG = temp_ANFLAG - 4194304
# 'do not spell check' field
anflag_properties['noSpellCheck'] = 1
if temp_ANFLAG - 262144 >= 0:
temp_ANFLAG = temp_ANFLAG - 262144
# 'editable' field
anflag_properties['editable'] = 1
if temp_ANFLAG - 8192 >= 0:
temp_ANFLAG = temp_ANFLAG - 8192
# 'password' field
anflag_properties['password'] = 1
if temp_ANFLAG - 4096 >= 0:
temp_ANFLAG = temp_ANFLAG - 4096
# 'multiline' field
anflag_properties['multiline'] = 1
if temp_ANFLAG - 4 >= 0:
temp_ANFLAG = temp_ANFLAG - 4
# 'do not export data' field
anflag_properties['noExport'] = 1
if temp_ANFLAG - 2 >= 0:
temp_ANFLAG = temp_ANFLAG - 2
# 'required field
anflag_properties['required'] = 1
if temp_ANFLAG == 1:
# 'read only" field
anflag_properties['readOnly'] = 1
# getting maximum number of caracters the field can hold
# note : only for textfields
object_properties['maximum_input'] = sp.getObjectTooltipProperty('ANMC','0',object_name,object_content)
print " => MaxInput = %s" % object_properties['maximum_input']
# getting object type :
# first checking for user-specified type in 'tooltip' properties
if tooltipfield_properties_dict.has_key('type'):
# 'type' id in tooltip : using it and ignoring other 'type' information
# in scribus properties
object_properties['type'] = tooltipfield_properties_dict['type']
# if no user-specified type has been found, trying to find scribus-type
elif object_content.has_key('ANTYPE'):
# from scribus type (selected in the scribus PDF-form properties)
object_type = str(object_content['ANTYPE'])
if object_type == '2':
#type 2 = PDF-Button
object_properties['type'] = 'Button'
elif object_type == '3':
#type 3 = PDF-Text : Stringfield by default
object_properties['type'] = 'StringField'
if anflag_properties['multiline'] == 1:
# Stringfield is multiline, converting to TextAreaField
object_properties['type'] = 'TextAreaField'
elif object_content.has_key('ANFORMAT'):
object_format = str(object_content['ANFORMAT'])
# checking kind of Stringfield
if object_format == '1':
#type is number
object_properties['type'] = 'IntegerField'
elif object_format == '2':
#type is percentage
object_properties['type'] = 'FloatField'
elif object_format == '3':
#type is date
object_properties['type'] = 'DateTimeField'
elif object_format == '4':
#type is time
object_properties['type'] = 'DateTimeField'
elif object_type == '4':
# type 4 = PDF-Checkbox
object_properties['type'] = 'CheckBoxField'
elif object_type == '5':
# type 5 = PDF-Combobox
object_properties['type'] = 'ComboBox'
elif object_type == '6':
# type 6 = PDF-ListBox
object_properties['type'] = 'ListBox'
else:
# object type not found in user-properties neither in document-properties
# logging and initialising with default type
LOG("WARNING : " + str(object_name),0,"no 'type' found, please check your document properties or use 'tooltips' properties")
print " => no type specified : assuming default = StringField"
object_properties['type'] = 'StringField'
print " type = " + str(object_properties['type'])
# getting 'required' property
# first checking from user data in 'tooltip'
temp_required = sp.getObjectTooltipProperty('required','none',object_name,tooltipfield_properties_dict)
if temp_required == 'none':
# no 'required' property in 'tooltip'
# cheking global PAGEOBJECT properties for 'required' (found in anflag)
temp_required = anflag_properties['required']
object_properties['required'] = temp_required
# getting type properties for special types
# checkbox objects belongs to a group of checkbox
if str(object_properties['type']) == 'CheckBox' :
# checking if THIS checkbox is in a group
object_properties['group'] = sp.getObjectTooltipProperty('group', '0', object_name, tooltipfield_properties_dict)
print " group = " + str(object_properties['group'])
#object is listbox, and listbox have several possible values
if str(object_properties['type']) == 'ListBox' :
#checking if this listbox has different possible values
object_properties['items'] = sp.getObjectTooltipProperty('items', '', object_name, tooltipfield_properties_dict)
#object is datetimefield and need several informations
if str(object_properties['type']) == 'DateTimeField':
#checking if field has inpu_order property
object_properties['input_order'] = sp.getObjectTooltipProperty('input_order','day/month/year',object_name,tooltipfield_properties_dict)
#
#checking if field has date_only property
object_properties['date_only'] = sp.getObjectTooltipProperty('date_only','1',object_name,tooltipfield_properties_dict)
# object is relationstringfield and ned some informations
# FIXME : quelle est la valeur par defaut pour des champs de ce type ?
if str(object_properties['type']) == 'RelationStringField':
object_properties['base_category'] = sp.getObjectTooltipProperty('base_category','0',object_name,tooltipfield_properties_dict)
object_properties['catalog_index'] = sp.getObjectTooltipProperty('catalog_index','0',object_name,tooltipfield_properties_dict)
object_properties['default_module'] = sp.getObjectTooltipProperty('default_module','0',object_name,tooltipfield_properties_dict)
# getting creation order from 'tooltip' properties
# used to create ERP5 objects in a special order
if tooltipfield_properties_dict.has_key('nb') and str(tooltipfield_properties_dict['nb']).isdigit():
# object has a nb properties containing its creation position
# adding the object in the ordered list
nb_value = int(tooltipfield_properties_dict['nb'])
print " =>'nb' property specified : using it to order PAGEOBJECT elements"
# iterating through existing list to find right position
# before inserting value
if len(nb_property_nbkey_list) == 0:
print " => 'nb' list empty : adding without sorting"
# list is empty : adding value without sort
nb_property_nbkey_list.insert(0,(nb_value,object_name))
elif nb_property_nbkey_list[len(nb_property_nbkey_list)-1][0] <= nb_value:
print " => 'nb' end : adding at the end"
# last element is smaller than new element : adding at the end
nb_property_nbkey_list.append((nb_value,object_name))
else:
print " => checking for place to add the element"
# searching where to insert the element in the ordered list
for temp_key in range(len(nb_property_nbkey_list)):
temp_value = nb_property_nbkey_list[temp_key][0]
temp_content = nb_property_nbkey_list[temp_key][1]
print " @" + str(temp_key) + " temp=" + str(temp_value) + "/" + str(nb_value)
if nb_value < temp_value:
#first position where actual 'nb' is smaller than temp 'nb'
# inserting new couple (nb_value,object_name) here
print " inserting here : " + str(temp_value) + "/" + str(nb_value)
nb_property_nbkey_list.insert(temp_key,(nb_value,object_name))
# element has been insered , no need to continue the search => breaking
break
else:
# object has no nb property. logging and adding it to the list of
# nb-less objects. Script will automatically find a 'nb' value for this element
LOG("WARNING : " + str(object_name),0,"no 'nb' defined : finding a free slot")
print " => no 'nb' property specified : post-processing will try to define one"
nb_property_nonbkey_list.append(object_name)
# adding current object with its relative properties to the dict
# before going to the next page_object
returned_object_dict[object_name] = object_properties
# final processing before returning full page with modified
# page_object_properties : setting 'nb' property to all objects
# without user-specified 'nb' property
for object_name in nb_property_nonbkey_list:
# listing all objects with no 'nb' declared
# defining final position in output list : absolute pos + relative pos
object_position = len(nb_property_nbkey_list) + 1
# and addind it to the end of the final nb-list
# to give them a 'nb' property
nb_property_nbkey_list.append((object_position,object_name))
print " => final sorting before returning value, " + str(len(nb_property_nbkey_list)) + " elements"
# now all page_object are referenced in the list, we just need to sort
# the elements in the good order. for that a new list of objects is needed
returned_object_list = []
for nb_ind in range(len(nb_property_nbkey_list)):
# iterating through final nb-list
# getting list-object information
(nb_key, nb_value) = nb_property_nbkey_list[nb_ind]
# setting object's 'nb' property
returned_object_dict[nb_value]['nb'] = nb_ind + 1
# add the object at the end of the new list
returned_object_list.append((nb_value,returned_object_dict[nb_value]))
LOG("INFO : " + str(nb_value),0,"creation order =" + str(nb_ind))
print " > " + str(nb_value) + " has nb:" + str(nb_ind)
# adding returned list of object to the page dict
# before going to the next page
returned_page_dict[page_number] = returned_object_list
# returning final dict containing all the modified data
print " => end ScribusParser.getPropertiesConversion"
return returned_page_dict
security.declareProtected('Import/Export objects', 'getContentFile')
def getContentFile(self, file_descriptor):
""" Get file content """
return file_descriptor.read()
InitializeClass(ScribusParser)
allow_class(ScribusParser)
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment