ERP5Site_updateModuleScribus.py 16.8 KB
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
#               Fabien Morin <fabien@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.
#
##############################################################################

def ERP5Site_updateModuleScribus(self,
                                 import_pdf_file=None,
                                 import_scribus_file=None,
                                 option_html=None,
                                 desired_width=None,
                                 desired_height=None,
                                 object_portal_type=None,
                                 selection_index=None,
                                 selection_name=None,
                                 **kw):
  """ Update the ERP5Form, scribus, PDFForm, css and background picture created 
      from scribus and PDFForm file"""
  context = self

  # IMPORTING MODULES
  from Products.Formulator.Errors import ValidationError, FormValidationError
  from Products.ERP5Form.ScribusUtils import ScribusParser
  from Products.ERP5Form.ScribusUtils import ManageModule
  from Products.ERP5Form.ScribusUtils import ManageFiles
  from Products.ERP5Form.ScribusUtils import ManageCSS
  from Products.ERP5Form.CreatePropertySheet import 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 Products.CMFCore.utils import getToolByName
  from zLOG import LOG, TRACE, WARNING, ERROR, INFO

  # CREATING MODULES INSTANCES
  ScribusParser = ScribusParser()
  ManageModule = ManageModule()
  ManageFiles = ManageFiles()
  ManageCSS = ManageCSS()
  generator = LocalGenerator()

  # DECLARING VARIABLES
  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

  # recovering objects
  portal = context.getPortalObject()
  portal_types = portal.portal_types
  object_portal_type_id = object_portal_type
  desired_height = desired_height
  desired_width = desired_width
  resolution = 300 # JPS-XXX - hardcoded
  background_format = 'jpg' # XXX - hardcoded
  space_between_pages = 20 # XXX - hardcoded
  option_html = option_html

  # get object_title and portal_skin object using the object_portal_type
  # to search the view in portal_skins folder
  search_param = {
                  'obj_metatypes': 'ERP5 Form',
                  'obj_searchterm': '%s_view' % object_portal_type,
                  'search_sub': 1
                 }
  result = portal.portal_skins.PrincipiaFind( portal.portal_skins, 
                                              **search_param)
  
  # keep only the object in the "good" skinFolder
  good_result = {}
  for path, ob in result:
    if portal.portal_skins.isFirstInSkin(path):
      good_result[path]=ob

  # We should have only one result
  if len(good_result) > 1:
    raise ValueError, "Error: There is more than one result for the "\
                            "view '%s_view'" % object_portal_type
  elif len(good_result) < 1:
    raise ValueError, "Error: There is no result for the view "\
                            "'%s_view'" % object_portal_type

  # use the result to get the object_title and portal_skin folder
  object_result = good_result.items()[0][1]
  object_path = object_result.absolute_url_path().replace(object_result.id, '')
  portal_skins_folder = object_result.aq_parent.getId()
  object_title = object_result.getId()

  # 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)

  # PROCESSING SKIN FOLDER
  # get the skin_folder object
  if not portal_skins_folder in portal.portal_skins.objectIds():
    # the skin folder should exists
    raise ValueError, "Error: portal_skins %s not found" % \
        portal_skins_folder 
  skin_folder = ManageModule.setSkinFolder(portal,
                                           portal_skins_folder)

  # all object in the skin_folder should be re-generated to be updated
  # except the module form view (because it don't change)
  object_id_list = []
  for object in skin_folder._objects:
    if 'Module_view' not in object['id']:
      object_id_list.append(object['id'])

  # move the old objects in portal_trash
  trash = getToolByName(self.getPortalObject(), 'portal_trash', None)
  if trash is None: 
    raise AttributeError, 'Trash Tool is not installed'

  trashbin = trash.newTrashBin(bt_title='scribus_skin_folder_%s' % \
      skin_folder.getId())
  container_path = list(skin_folder.getPhysicalPath()[1:])
  # backup all objects before delete them
  for object_id in object_id_list:
    trash.backupObject(trashbin, container_path,
      object_id, save=1, keep_subobjects=1)
  # delete objects after backup
  skin_folder.manage_delObjects(object_id_list)

  # ERP FORM LIST PROCESSING
  # Create ERP5 Form in order to view the module
  # set up the factory based on skin_folder
  factory = skin_folder.manage_addProduct['ERP5Form']

  # 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()


  # 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
  scale_factor = 0
  # import scribus file
  # take the input ScribusFile and read the content
  xml_string = ScribusParser.getContentFile(import_scribus_file)
  if xml_string == None:
    LOG('ERP5Site_updateModuleScribus', WARNING, 
        'no field was defined in the Scribus file')
    pass
  else:

    # GETTING FULL SCRIBUS DOCUMENT PROPERTIES
    # get string from ScribusFile content
    output_string = str(xml_string)

    LOG('ERP5Site_updateModuleScribus', INFO, 
        'createmodule > ScribusParser.getXmlObjectPropertiesDict')
    # 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()
    (text_field_list, keep_page, page_gap) = \
        ScribusParser.getXmlObjectsPropertiesDict(xml_string)
    LOG('ERP5Site_updateModuleScribus', INFO, 
        'createmodule < ScribusParser.getXmlObjectPropertiesDict')


    LOG('ERP5Site_updateModuleScribus', INFO, 
        'createmodule > ScribusParser.getPropertiesConversionDict')
    # 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.
    widget_properties = \
        ScribusParser.getPropertiesConversionDict(text_field_list)

    LOG('ERP5Site_updateModuleScribus', INFO, 
        'createmodule < ScribusParser.getPropertiesConversionDict')


    # testing if final rendering is PDF-like
    if option_html == 1:
      LOG('ERP5Site_updateModuleScribus', INFO, 
          'createmodule > generating background')
      ## 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
      image_size = ManageFiles.setBackgroundPictures(import_pdf_file,
          object_names, skin_folder, desired_height, desired_width,
          resolution, background_format)

      page_width, page_height = image_size

      LOG('ERP5Site_updateModuleScribus', INFO,
          '   height = %s' % str(page_height))
      LOG('ERP5Site_updateModuleScribus', INFO,
          '   width = %s' % str(page_width))
      LOG('ERP5Site_updateModuleScribus', INFO, 
          'createmodule < background generated')

    # add field from OrderedWidgetProperties in ERP5 Module created
    # radiofield_widget_properties = {}
    position = {}
    # personal_properties_list is used to create PropertySheet
    personal_properties_list = []

    # recovering number of pages
    global_properties['page'] = len(widget_properties)

    # 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
    LOG('ERP5Site_updateModuleScribus', INFO, 
        'createmodule > begining data interpretation')
    #iterating pages
    #print "   %s" % int(global_properties['page'])
    for page_iterator in range(int(global_properties['page'])):
      page_number = str(page_iterator)
      page_content = widget_properties[page_number]
      page_id = "page_" + page_number

      if option_html == 1:
        # 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
        width_groups, height_groups = ManageFiles.getPageattributes(
                                              global_properties,
                                              import_pdf_file)
        properties_css_dict, properties_page = \
            ManageCSS.setPageProperties(properties_css_dict,
                                        page_iterator,
                                        page_id,
                                        page_height,
                                        page_width,
                                        width_groups,
                                        height_groups)

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

          if option_html == 1:
            # 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(
                                            properties_css_dict,
                                            page_content[index],
                                            page_width,
                                            page_height,
                                            page_iterator,
                                            page_gap,
                                            keep_page,
                                            properties_page,
                                            space_between_pages)


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

          ScribusParser.getFieldAttributes(page_content[index],
                                           option_html,
                                           page_id,
                                           global_properties)

    # CSS CLASS (generateOutputContent)
    if option_html == 1:

      # add last properties to css dict, including implementation
      # of a n+1 page to prevent bug when rendering under Konqueror
      ManageCSS.setFinalProperties(properties_css_dict, page_height,
                                   space_between_pages)

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

      # save CSS string content into ERP5
      ManageFiles.setCSSFile(factory, object_names['css'], form_css_content)


  # CREATING OBJECT FORM AND MANAGING GROUPS
  LOG('ERP5Site_updateModuleScribus', INFO,
      'createmodule > generate fields in ERP Form')
  # CREATING ERP5 OBJECT FORM
  # create ERP5 Form to handle object view
  ManageFiles.setERP5Form(factory,
                          object_names['view_id'],
                          object_title)

  # 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

  ManageModule.setFieldsInObjectForm(skin_folder,
                                     object_names,
                                     default_groups,
                                     global_properties,
                                     option_html
                                     )

  LOG('ERP5Site_updateModuleScribus', INFO, 
      'createmodule < fields created in ERP5 Form')



  # PDF IMPORTATION AND TALES GENERATION
  LOG('ERP5Site_updateModuleScribus', INFO, 
      'createmodule > managing PDF settings')
  # 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,
                         pdf_file=import_pdf_file
                         )
  LOG('ERP5Site_updateModuleScribus', INFO, 
      'createmodule < PDF settings managed')



  # PROPERTYSHEET AND DOCUMENT CREATION

  LOG('ERP5Site_updateModuleScribus', INFO, 
      'createmodule > PropertySheet and Document creation')
  # 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.
  from Products.ERP5Type.Utils import initializeLocalPropertySheetRegistry
  initializeLocalPropertySheetRegistry()
  from Products.ERP5Type.Utils import initializeLocalDocumentRegistry
  initializeLocalDocumentRegistry()
  LOG('ERP5Site_updateModuleScribus', INFO, 
      'createmodule < PropertySheet and Document imported')


  # manage redirection URL
  if not selection_index:
    redirect_url = '%s/view?%s' % (portal.absolute_url(),
                                   'portal_status_message=Module+Updated.'
                                  )
  else:
    redirect_url = '%s/view?selection_index=%s&selection_name=%s&%s' % (
                            portal.absolute_url(),
                            selection_index,
                            selection_name,
                            'portal_status_message=Module+Updated.'
                            )

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