ERP5Site_createModuleScribus.py 16.4 KB
Newer Older
Romain Courteaud's avatar
Romain Courteaud committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
#
# 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.
#
##############################################################################

def ERP5Site_createModuleScribus(self,
                                 module_id=None,
                                 module_portal_type=None,
                                 module_title=None,
                                 import_pdf_file=None,
                                 import_scribus_file=None,
                                 option_html=None,
                                 desired_width=None,
                                 desired_height=None,
                                 object_title=None,
                                 object_portal_type=None,
                                 portal_skins_folder=None,
                                 form_id=None,
                                 selection_index=None,
                                 selection_name=None,
                                 **kw):
Kevin Deldycke's avatar
Kevin Deldycke committed
44 45 46
  """ Creates a module, portal_type and ERP5Form from a scribus and
      PDFForm file"""
  context = self
Romain Courteaud's avatar
Romain Courteaud committed
47

48
  # IMPORTING MODULES
Kevin Deldycke's avatar
Kevin Deldycke committed
49 50
  from Products.Formulator.Errors import ValidationError, FormValidationError
  from Products.ERP5Form.ScribusUtils import ScribusParser
51 52 53
  from Products.ERP5Form.ScribusUtils import ManageModule
  from Products.ERP5Form.ScribusUtils import ManageFiles
  from Products.ERP5Form.ScribusUtils import ManageCSS
Kevin Deldycke's avatar
Kevin Deldycke committed
54
  from Products.ERP5Form.CreatePropertySheet import LocalGenerator
55 56 57
  # 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
Fabien Morin's avatar
Fabien Morin committed
58
  from zLOG import LOG, TRACE, WARNING, ERROR, INFO
59

60 61 62 63 64 65 66 67
  # CREATING MODULES INSTANCES
  ScribusParser = ScribusParser()
  ManageModule = ManageModule()
  ManageFiles = ManageFiles()
  ManageCSS = ManageCSS()
  generator = LocalGenerator()

  # DECLARING VARIABLES
68 69 70 71 72
  def_lineNumberInList = 20 # JPS-XXX - hardcoded
  def_colorRequired = 'rgb(192,192,255)' # JPS-XXX - hardcoded
  def_colorRequiredError = 'rgb(128,128,255)' # JPS-XXX - hardcoded
  def_color = '#F6FFFF' # JPS-XXX - hardcoded
  def_colorError = 'rgb(255,64,64)' # JPS-XXX - hardcoded
73 74

  # recovering objects
Kevin Deldycke's avatar
Kevin Deldycke committed
75 76 77
  portal = context.getPortalObject()
  portal_types = portal.portal_types
  object_portal_type_id = object_portal_type
78 79 80
  desired_height = desired_height
  desired_width = desired_width
  resolution = 300 # JPS-XXX - hardcoded
81 82
  background_format = 'jpg' # XXX - hardcoded
  space_between_pages = 20 # XXX - hardcoded
83
  option_html = option_html
84

85 86 87 88 89
  # DECLARING NAMES
  # declaring names for ERP5 objects, such as Form, DTML Document, etc.
  # these names are stored in a dict (object_names)
  object_names = ManageModule.setObjectNames(object_portal_type_id,
                                             object_title)
90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
  # CREATING NEW PORTAL TYPE FOR THE MODULE
  # Manage the creation of a ne portal_type for the module
  # (module is not saved for the moment, but properties can be
  # updated)
  ManageModule.setModulePortalType(portal_types,
                                   object_portal_type_id,
                                   module_portal_type,
                                   object_names
                                  )

  # PROCESSING SKIN FOLDER
  # Process and create if necessary the skins_folder defined by the user.
  # return the skin_folder object
  skin_folder = ManageModule.setSkinFolder(portal,
                                           portal_skins_folder)
Romain Courteaud's avatar
Romain Courteaud committed
106 107


108 109 110
  # ERP FORM LIST PROCESSING
  # Create ERP5 Form in order to view the module
  # set up the factory based on skin_folder
Kevin Deldycke's avatar
Kevin Deldycke committed
111
  factory = skin_folder.manage_addProduct['ERP5Form']
Romain Courteaud's avatar
Romain Courteaud committed
112

113 114 115
  # run the factory to create the new object (ERP5Form)
  ManageFiles.setERP5Form(factory,
                          str(object_names['view_list']),
Romain Courteaud's avatar
Romain Courteaud committed
116 117
                          '%s Module View' % object_title)

118 119 120 121 122 123 124 125 126
  # manage the module form and set up the list inside
  # update form properties with generic module values
  # and implement the objects' listing inside the form
  ManageModule.setModuleForm(object_title,
                             skin_folder,
                             object_names['view_list'],
                             module_title,
                             module_id,
                             def_lineNumberInList)
Romain Courteaud's avatar
Romain Courteaud committed
127

128 129 130 131 132 133 134 135

  # INIT ATTRIBUTES DICT
  # global_properties is a special dict destinated to
  # keep all the field and page data safe during the
  # parsing, allowing them to be updated when needed
  # and used if necessary.
  global_properties = ScribusParser.initFieldDict()

Romain Courteaud's avatar
Romain Courteaud committed
136

137 138 139 140 141 142 143 144 145
  # PARSER VARIABLES DECLARATION
  # the following variable will recover the final CSS
  # file's content object (string) before saving it
  # onto the hard disk
  form_css_content = ""
  # properties_css_dict is used to store class informations
  properties_css_dict = {}
  # init page number
  page_number_int = 0
Romain Courteaud's avatar
Romain Courteaud committed
146
  scale_factor = 0
147 148 149
  # import scribus file
  # take the input ScribusFile and read the content
  xml_string = ScribusParser.getContentFile(import_scribus_file)
Kevin Deldycke's avatar
Kevin Deldycke committed
150
  if xml_string == None:
Fabien Morin's avatar
Fabien Morin committed
151
    LOG('ERP5Site_createModuleScribus', WARNING,
Fabien Morin's avatar
Fabien Morin committed
152
        'no field was defined in the Scribus file')
Kevin Deldycke's avatar
Kevin Deldycke committed
153 154
    pass
  else:
Romain Courteaud's avatar
Romain Courteaud committed
155

156 157
    # GETTING FULL SCRIBUS DOCUMENT PROPERTIES
    # get string from ScribusFile content
Kevin Deldycke's avatar
Kevin Deldycke committed
158
    output_string = str(xml_string)
Romain Courteaud's avatar
Romain Courteaud committed
159

Fabien Morin's avatar
Fabien Morin committed
160
    LOG('ERP5Site_createModuleScribus', INFO, 
Fabien Morin's avatar
Fabien Morin committed
161
        'createmodule > ScribusParser.getXmlObjectPropertiesDict')
162 163 164 165 166 167 168 169 170
    # building a tree from the output string elaborated from the
    # original Scribus file.
    # create a list of pages containing a dict of all the page_objects
    # elements with their attributes 'as they are' (so without any check
    # for data integrity or unuseful values).
    # This procedure already makes a selection of parameters and take all the
    # unnecessary page_objects off.
    #import pdb
    #pdb.set_trace()
Romain Courteaud's avatar
Romain Courteaud committed
171 172
    (text_field_list, keep_page, page_gap) = \
        ScribusParser.getXmlObjectsPropertiesDict(xml_string)
Fabien Morin's avatar
Fabien Morin committed
173
    LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
174
        'createmodule < ScribusParser.getXmlObjectPropertiesDict')
Romain Courteaud's avatar
Romain Courteaud committed
175 176


Fabien Morin's avatar
Fabien Morin committed
177
    LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
178
        'createmodule > ScribusParser.getPropertiesConversionDict')
179 180 181 182
    # parsing text_field_list created from the getXmlObjectsPropertiesDict
    # to extract all the usefull properties and organize elements. Then check
    # attributes to get properties values.
    # This represents the main process of the script.
Romain Courteaud's avatar
Romain Courteaud committed
183 184
    widget_properties = \
        ScribusParser.getPropertiesConversionDict(text_field_list)
185

Fabien Morin's avatar
Fabien Morin committed
186
    LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
187
        'createmodule < ScribusParser.getPropertiesConversionDict')
Romain Courteaud's avatar
Romain Courteaud committed
188

189 190

    # testing if final rendering is PDF-like
Romain Courteaud's avatar
Romain Courteaud committed
191
    if option_html == 1:
Fabien Morin's avatar
Fabien Morin committed
192
      LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
193
          'createmodule > generating background')
194 195 196 197 198
      ## BACKGROUND GENERATOR
      # extract background pictures from the PDF document, convert them in the right
      # format (JPG) and add them to the skin folder as Image objects.
      # used only with option_html == 1
      # recover image_size
199
      image_size = ManageFiles.setBackgroundPictures(import_pdf_file,
200
          object_names, skin_folder, desired_width, desired_height,
Romain Courteaud's avatar
Romain Courteaud committed
201 202
          resolution, background_format)

203
      new_width, new_height = image_size
Romain Courteaud's avatar
Romain Courteaud committed
204

Fabien Morin's avatar
Fabien Morin committed
205
      LOG('ERP5Site_createModuleScribus', INFO,
206
          '   height = %s' % str(new_height))
Fabien Morin's avatar
Fabien Morin committed
207
      LOG('ERP5Site_createModuleScribus', INFO,
208
          '   width = %s' % str(new_width))
Fabien Morin's avatar
Fabien Morin committed
209
      LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
210
          'createmodule < background generated')
Romain Courteaud's avatar
Romain Courteaud committed
211

Kevin Deldycke's avatar
Kevin Deldycke committed
212
    # add field from OrderedWidgetProperties in ERP5 Module created
213
    # radiofield_widget_properties = {}
Kevin Deldycke's avatar
Kevin Deldycke committed
214
    position = {}
215
    # personal_properties_list is used to create PropertySheet
Kevin Deldycke's avatar
Kevin Deldycke committed
216
    personal_properties_list = []
217

218
    # recovering number of pages
Romain Courteaud's avatar
Romain Courteaud committed
219
    global_properties['page'] = len(widget_properties)
220

221 222 223 224 225 226 227
    # CSS FILE INIT
    # init the CSS dict by creating sub-dicts to store various information
    # i.e : 'head', 'standard' ,'error', etc.
    # these sub-dicts are stored in the properties_css_dict
    properties_css_dict = ManageCSS.setInit()

    # BEGINING DATA INTERPRETATION
Fabien Morin's avatar
Fabien Morin committed
228
    LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
229
        'createmodule > begining data interpretation')
230
    #iterating pages
231 232
    #print "   %s" % int(global_properties['page'])
    for page_iterator in range(int(global_properties['page'])):
233 234 235
      page_number = str(page_iterator)
      page_content = widget_properties[page_number]
      page_id = "page_" + page_number
236

237
      if option_html == 1:
238 239 240 241
        # CSS PAGE DEFINITION (PAGE AND BACKGROUND IMAGE)
        # get CSS class properties relative to the actual page
        # (background picture position, picture size, etc.)
        # and add them to the css dict
242
        old_width, old_height = ManageFiles.getPageAttributes(
243 244
                                              global_properties,
                                              import_pdf_file)
245
        properties_css_dict, properties_page = \
Romain Courteaud's avatar
Romain Courteaud committed
246 247 248
            ManageCSS.setPageProperties(properties_css_dict,
                                        page_iterator,
                                        page_id,
249 250 251 252
                                        new_width,
                                        new_height,
                                        old_width,
                                        old_height)
253

254 255
      # RESUME DATA INTERPRETATION
      # iterating pageobjects in page
256 257
      for index in range(len(page_content)):
        (id, properties_field) = page_content[index]
258
        # testing each page_content
259
        if properties_field.has_key('type'):
260

261
          if option_html == 1:
262 263 264 265 266
            # CSS FIELD PROPERTIES
            # get CSS class properties related to the actual page_object
            # in the page (position, size, color, etc.) and add them to
            # the css_dict
            properties_css_dict = ManageCSS.setFieldProperties(
267 268
                                            properties_css_dict,
                                            page_content[index],
269 270
                                            new_width,
                                            new_height,
271 272 273
                                            page_iterator,
                                            page_gap,
                                            keep_page,
274 275
                                            properties_page,
                                            space_between_pages)
276

277 278 279 280

          # recover useful page_object attributes from scribus dict
          # to be able to create and update correctly the fields
          # composing the form
281

282 283 284 285
          ScribusParser.getFieldAttributes(page_content[index],
                                           option_html,
                                           page_id,
                                           global_properties)
286

287
    # CSS CLASS (generateOutputContent)
288
    if option_html == 1:
289

290 291
      # add last properties to css dict, including implementation
      # of a n+1 page to prevent bug when rendering under Konqueror
292
      ManageCSS.setFinalProperties(properties_css_dict, new_height,
Romain Courteaud's avatar
Romain Courteaud committed
293
                                   space_between_pages)
Kevin Deldycke's avatar
Kevin Deldycke committed
294

295 296
      # generate output string from dict
      form_css_content = ManageCSS.generateOutputContent(properties_css_dict)
297

298
      # save CSS string content into ERP5
Romain Courteaud's avatar
Romain Courteaud committed
299
      ManageFiles.setCSSFile(factory, object_names['css'], form_css_content)
300 301


302
  # CREATING OBJECT FORM AND MANAGING GROUPS
Fabien Morin's avatar
Fabien Morin committed
303
  LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
304
      'createmodule > generate fields in ERP Form')
305 306 307 308 309
  # CREATING ERP5 OBJECT FORM
  # create ERP5 Form to handle object view
  ManageFiles.setERP5Form(factory,
                          object_names['view_id'],
                          object_title)
310

311 312 313 314 315 316 317 318 319 320
  # update Form groups to have right number of groups with
  # corresponding names (depending on the kind of display)
  default_groups = ManageModule.setObjectForm(skin_folder,
                                              object_names,
                                              option_html,
                                              global_properties,
                                              object_portal_type)

  # create fields corresponding to the page_objects
  # recovered from the scribus file
Romain Courteaud's avatar
Romain Courteaud committed
321

322 323 324 325 326 327
  ManageModule.setFieldsInObjectForm(skin_folder,
                                     object_names,
                                     default_groups,
                                     global_properties,
                                     option_html
                                     )
Romain Courteaud's avatar
Romain Courteaud committed
328

Fabien Morin's avatar
Fabien Morin committed
329
  LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
330
      'createmodule < fields created in ERP5 Form')
331

Romain Courteaud's avatar
Romain Courteaud committed
332 333


334
  # PDF IMPORTATION AND TALES GENERATION
Fabien Morin's avatar
Fabien Morin committed
335
  LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
336
      'createmodule > managing PDF settings')
337 338 339 340 341 342 343
  # read all the content of the PDF document and save it in the skin_folder
  # as a PDFForm. then iterate the fields to get the corresponding TALES
  # expressions and save them in the PDFForm.
  ManageFiles.setPDFForm(factory,
                         skin_folder,
                         object_names,
                         object_title,
Romain Courteaud's avatar
Romain Courteaud committed
344
                         pdf_file=import_pdf_file
345
                         )
Fabien Morin's avatar
Fabien Morin committed
346 347
  LOG('ERP5Site_createModuleScribus', INFO, 
      'createmodule < PDF settings managed')
Romain Courteaud's avatar
Romain Courteaud committed
348

349 350


351
  # PROPERTYSHEET AND DOCUMENT CREATION
Romain Courteaud's avatar
Romain Courteaud committed
352

Fabien Morin's avatar
Fabien Morin committed
353
  LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
354
      'createmodule > PropertySheet and Document creation')
355 356 357 358 359 360 361 362 363
  # recover personal properties and save them in a PropertySheet
  # then create the Document related to the object
  ManageFiles.setPropertySheetAndDocument(global_properties,
                                          object_portal_type,
                                          generator,
                                          skin_folder,
                                          object_names)
  # as new document and PropertySheet are created, it is needed to reload the
  # registry.
Kevin Deldycke's avatar
Kevin Deldycke committed
364 365 366 367
  from Products.ERP5Type.Utils import initializeLocalPropertySheetRegistry
  initializeLocalPropertySheetRegistry()
  from Products.ERP5Type.Utils import initializeLocalDocumentRegistry
  initializeLocalDocumentRegistry()
Fabien Morin's avatar
Fabien Morin committed
368
  LOG('ERP5Site_createModuleScribus', INFO,
Fabien Morin's avatar
Fabien Morin committed
369
      'createmodule < PropertySheet and Document imported')
Romain Courteaud's avatar
Romain Courteaud committed
370

371 372 373 374 375 376 377 378 379

  # OBJECT PORTAL TYPE
  # create PortalType for the object
  ManageModule.setObjectPortalType(portal_types,
                                   object_portal_type_id,
                                   object_portal_type,
                                   object_names
                                   )

Romain Courteaud's avatar
Romain Courteaud committed
380

Kevin Deldycke's avatar
Kevin Deldycke committed
381
  # Finally add the module to the site
382 383 384
  ManageModule.registerModule(portal,
                              module_id,
                              module_portal_type,
385 386
                              object_portal_type,
                              module_title)
Kevin Deldycke's avatar
Kevin Deldycke committed
387

388 389
  # Clear caches so that module is immediatly visible
  portal.portal_caches.clearAllCache()
390 391

  # manage redirection URL
Kevin Deldycke's avatar
Kevin Deldycke committed
392
  if not selection_index:
Romain Courteaud's avatar
Romain Courteaud committed
393 394 395
    redirect_url = '%s/view?%s' % (portal.absolute_url(),
                                   'portal_status_message=Module+Created.'
                                  )
Kevin Deldycke's avatar
Kevin Deldycke committed
396 397
  else:
    redirect_url = '%s/view?selection_index=%s&selection_name=%s&%s' % (
Romain Courteaud's avatar
Romain Courteaud committed
398 399 400 401
                            portal.absolute_url(),
                            selection_index,
                            selection_name,
                            'portal_status_message=Module+Created.'
Kevin Deldycke's avatar
Kevin Deldycke committed
402 403
                            )

404
  # redirect
405
  portal.REQUEST.RESPONSE.redirect(redirect_url )