diff -r 000000000000 -r 2e8eeb919028 configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/maketheme.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/maketheme.py Thu Mar 11 17:04:37 2010 +0200 @@ -0,0 +1,298 @@ +# +# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# + +import re +import os +import sys +import logging +import xml.parsers.expat +import unzip +import shutil + +try: + from cElementTree import ElementTree +except ImportError: + try: + from elementtree import ElementTree + except ImportError: + try: + from xml.etree import cElementTree as ElementTree + except ImportError: + from xml.etree import ElementTree + + +from cone.public import exceptions,plugin,utils,api +from themeplugin import theme_function +from theme_resource import ThemeResource +from theme_container import ThemeContainer, ActiveTheme + +class ThemeImpl(plugin.ImplBase): + """ + This class provides converting *.tpf files to target device + + + Building process: + 1. All tpf files are founded in the cpf file according to "preinstalled directories" + and "CVC settings" which are defined in the thememl file. + + 2. The tpf files are extracted to temporary directories. Every tpf file has self temporary directory + + 3. *.tdf, *.svg files are builded to *.mbm, *.skn,... by using Carbide.UI command-line. + The path of Carbide.UI is defined in the thememl file. + + Here is two possible cases: + 3a) The theme has defined UID number in thememl file. + The Carbide.UI is run with parameter -uid %number%. + Then this UID number (after converting to decimal format) is saved to + platform setting in the step 5 + + 3b) The theme has not defined UID number + The Carbide.UI is run without parameter -uid %number% and then + the PID number is getted from *.pkg file and setted to platform setting in the decimal format + in the step 5 + + 4. *.mbm, *.skn,... are copied to output directory according to content of the pkg file. + The *.pkg file contains the record where the *.mbm, *.skn,... are be copied. + Sample: "themepackage.mbm" - "private\10207114\import\99d49b086e6097b8\themepackage.mbm" + + 5. UID or PID number are saved to platform setting which is defined in the thememl file + 6. Temporary directories are removed + """ + + + IMPL_TYPE_ID = "thememl" + DEFAULT_INVOCATION_PHASE = 'pre' + + + def __init__(self,ref,configuration): + """ + Overloading the default constructor + """ + plugin.ImplBase.__init__(self,ref,configuration) + self.logger = logging.getLogger('cone.thememl') + + def build(self): + """ + Building process of themes + """ + # Get absolute path so that copying works correctly + # despite working directory changing + abs_output = os.path.abspath(os.path.join(self.output, "content")) + + # get *.tpf files from the configuration + list_tpf = self.list_tpf_files(self.list_active_theme, self.list_theme_dir) + + theme_container = ThemeContainer(list_tpf,self.configuration) + theme_container.carbide = self.carbide + theme_container.create_themes() + theme_container.prepare_active_themes(self.list_active_theme) + theme_container.build_theme(self.theme_version) + theme_container.copy_resources_to_output(abs_output) + theme_container.set_active_PID_to_model() + theme_container.removeTempDirs() + + + + def list_tpf_files(self,list_active_theme, list_theme_dir): + """ + returns the list of tpf files which are in the configuration + """ + list_tpf=[] + default_view = self.configuration.get_default_view() + + for active_theme in list_active_theme: + path=active_theme.get_setting_ref().replace("/",".") + feature = default_view.get_feature(path+".localPath") + setting = feature.get_data() + if setting != None: + list_tpf.append(setting.get_value()) + + for theme_dir in list_theme_dir: + theme_dir=theme_dir.replace("/",".") + feature = default_view.get_feature(theme_dir+".localPath") + setting = feature.get_data() + if setting != None: + list_tpf.append(setting.get_value()) + + + return self.find_tpf_files(list_tpf) + + + def find_tpf_files(self, list_tpf_path): + """ + finds *.tpf files in the data container + """ + list_tpf={} + + datacontainer = self.configuration.layered_content() + contentfiles = datacontainer.flatten() + for reskey in contentfiles.keys(): + respath = contentfiles[reskey] + + if respath.endswith(".tpf"): + # Strip file name from the resource path + respath_basename = os.path.split(respath)[0] + + for tpf_path in list_tpf_path: + # os.path.split() strips trailing slash, so do that here too + + tpf_path = "/content/" + tpf_path + if tpf_path.endswith(".tpf"): + if respath.endswith(tpf_path): + list_tpf[respath]=0 + break + + if tpf_path.endswith('/'): + tpf_path = tpf_path.rstrip('/') + if respath_basename.endswith(tpf_path): + list_tpf[respath]=0 + break + + + + + + return list_tpf.keys() + + + def generate(self, context=None): + """ + Generate the given implementation. + """ + self.parse_impl() + self.build() + + return + + def generate_layers(self,layers): + """ + Generate the given Configuration layers. + """ + self.logger.info('Generating layers %s' % layers) + self.create_output(layers) + return + + def has_ref(self,ref): + """ + @returns True if the implementation uses the given ref as input value. + Otherwise return False. + """ + return None + + def parse_impl(self): + if self.configuration: + resource =self.configuration.get_resource(self.ref) + reader = ThemeImplReader() + try: + self.logger.info('Parses %s' % self.ref) + reader.fromstring(resource.read()) + self.carbide = reader.carbide + except (SyntaxError),e: + logging.getLogger('cone.thememl(%s)' % resource.get_path()).error('Invalid xml in layer root file. Exception: %s' % (e)) + raise exceptions.ParseError('Invalid xml in layer root file (%s). Exception: %s' % (resource.get_path(),e)) + self.list_theme_dir=reader.list_theme_dir + self.list_active_theme=reader.list_active_theme + self.theme_version = reader.theme_version + resource.close() + + return + + def list_output_files(self): + """ + Return a list of output files as an array. + """ + # What to return if the output files cannot be known in advance? + return [] + + +class ThemeImplReader(plugin.ReaderBase): + """ + Parses a single thememl file + """ + NAMESPACE = 'http://www.s60.com/xml/thememl/1' + FILE_EXTENSIONS = ['thememl'] + + def __init__(self): + self.namespaces = [self.NAMESPACE] + self.list_theme_dir = [] + self.list_active_theme = [] + self.theme_version = "" + self.logger = logging.getLogger('cone.thememl') + self.carbide = r"C:\Program Files\Nokia\Carbide.ui Theme Edition 3.4" + + @classmethod + def read_impl(cls, resource_ref, configuration, etree): + reader = ThemeImplReader() + reader.parse_thememl(etree) + + impl = ThemeImpl(resource_ref, configuration) + impl.list_theme_dir = reader.list_theme_dir + impl.list_active_theme = reader.list_active_theme + impl.theme_version = reader.theme_version + return impl + + def fromstring(self, xml_as_string): + etree = ElementTree.fromstring(xml_as_string) + self.parse_thememl(etree) + + def parse_thememl(self,etree): + + list_setting_uid={} + + #parses the version of the theme + el_theme_version= etree.find("{%s}themeVersion" % self.namespaces[0]) + if el_theme_version != None: + self.theme_version = el_theme_version.text + + car= etree.find("{%s}carbideuiPath" % self.namespaces[0]) + envpattern = ".*(%(.*)%).*" + if car != None: + mo = re.match(envpattern, car.text) + if mo: + if os.environ.has_key(mo.group(2)): + self.carbide = car.text.replace(mo.group(1), os.environ[mo.group(2)]) + else: + self.carbide = car.text + else: + self.carbide = car.text + + + #parses the path of directories where are tpf files + el_list_theme_dir = etree.findall("{%s}themeDir" % self.namespaces[0]) + for el_theme_dir in el_list_theme_dir: + if el_theme_dir != None: + self.list_theme_dir.append(el_theme_dir.text) + + #parses the active themes and theirs ref setting and platform settings + el_list_active_theme = etree.findall("{%s}activeTheme" % self.namespaces[0]) + for el_active_theme in el_list_active_theme: + uid = el_active_theme.get("uid") + active_theme = ActiveTheme() + + active_theme.set_uid(uid) + for el_ref_setting in el_active_theme.getiterator("{%s}refSetting" % self.namespaces[0]): + active_theme.set_setting_ref(el_ref_setting.text) + + + for el_setting_uid in el_active_theme.getiterator("{%s}platformUID" % self.namespaces[0]): + setting_uid = el_setting_uid.text + if list_setting_uid.has_key(setting_uid): + raise exceptions.ParseError('The file contains duplicate setting uid: %s' % setting_uid) + else: + list_setting_uid[setting_uid]=0 + active_theme.set_setting_uids(setting_uid) + + self.list_active_theme.append(active_theme)