bin/rom.py
author hgs
Tue, 13 Jul 2010 20:12:19 +0300
changeset 9 a03989fb355a
parent 8 02a1dd166f2b
permissions -rw-r--r--
201027

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# ============================================================================
#  Name        : rom.py
#  Part of     : Hb
#  Description : Hb themes script for generating IBY files
#  Version     : %version: %
#
#  Copyright (c) 2008-2010 Nokia.  All rights reserved.
#  This material, including documentation and any related computer
#  programs, is protected by copyright controlled by Nokia.  All
#  rights are reserved.  Copying, including reproducing, storing,
#  adapting or translating, any or all of this material requires the
#  prior written consent of Nokia.  This material also contains
#  confidential information which may not be disclosed to others
#  without the prior written consent of Nokia.
# ============================================================================

import os
import sys
import fnmatch
import zipfile
import optparse
import posixpath
import ConfigParser

# ============================================================================
# Globals
# ============================================================================
VERBOSE = False
INCLUDE = None
EXCLUDE = None
INPUT_DIR = os.getcwd()
OUTPUT_DIR = os.getcwd()
SOURCE_PREFIX = "ZRESOURCE/hb/themes"
TARGET_PREFIX = "RESOURCE_FILES_DIR/hb/themes"
EXIT_STATUS = 0

# ============================================================================
# OptionParser
# ============================================================================
class OptionParser(optparse.OptionParser):
    def __init__(self):
        optparse.OptionParser.__init__(self)
        self.add_option("-v", "--verbose", action="store_true", dest="verbose",
                        help="print verbose information about each step of the sync process")
        self.add_option("-q", "--quiet", action="store_false", dest="verbose",
                        help="do not print information about each step of the sync process")

        group = optparse.OptionGroup(self, "Input/output options")
        group.add_option("-i", "--input", dest="input", metavar="dir",
                         help="specify the input <dir> (default %s)" % INPUT_DIR)
        group.add_option("-o", "--output", dest="output", metavar="dir",
                         help="specify the output <dir> (default %s)" % OUTPUT_DIR)
        group.add_option("--include", dest="include", action="append", metavar="pattern",
                         help="specify the include <pattern> (default %s)" % INCLUDE)
        group.add_option("--exclude", dest="exclude", action="append", metavar="pattern",
                         help="specify the exclude <pattern> (default %s)" % EXCLUDE)
        self.add_option_group(group)

        group = optparse.OptionGroup(self, "Prefix options")
        group.add_option("--source-prefix", dest="sourceprefix", metavar="prefix",
                         help="specify the source <prefix> (default %s)" % SOURCE_PREFIX)
        group.add_option("--target-prefix", dest="targetprefix", metavar="prefix",
                         help="specify the target <prefix> (default %s)" % TARGET_PREFIX)
        self.add_option_group(group)

# ============================================================================
# Utils
# ============================================================================
if not hasattr(os.path, "relpath"):
    def relpath(path, start=os.curdir):
        abspath = os.path.abspath(path)
        absstart = os.path.abspath(start)
        if abspath == absstart:
            return "."
        i = len(absstart)
        if not absstart.endswith(os.path.sep):
            i += len(os.path.sep)
        if not abspath.startswith(absstart):
            i = 0
        return abspath[i:]
    os.path.relpath = relpath

def zip_filelist(filepath):
    files = list()
    archive = zipfile.ZipFile(filepath)
    for entry in archive.namelist():
        if not entry.endswith("/"):
            files.append(entry)
    return files

class Theme:
    def __init__(self, name):
        self.name = name
        self.paths = []
        self.files = {}
        self.archives = {}

    def add_file(self, filepath):
        if self._include(filepath):
            filepath = filepath.replace("\\", "/")
            path = os.path.split(filepath)[0]
            extension = os.path.splitext(filepath)[1]
            if extension == ".zip":
                if path not in self.archives:
                    self.archives[path] = list()
                if filepath not in self.archives[path]:
                    self.archives[path].append(filepath)
            else:
                if path not in self.files:
                    self.files[path] = list()
                if filepath not in self.files[path]:
                    self.files[path].append(filepath)

    def initialize(self):
        for path in self.paths:
            for root, dirs, files in os.walk(path):
                for file in files:
                    self.add_file(os.path.join(root, file))

    def write_iby(self, ibypath):
        global SOURCE_PREFIX, TARGET_PREFIX, EXIT_STATUS
        outpath = os.path.dirname(ibypath)
        if not os.path.exists(outpath):
            os.makedirs(outpath)
        out = open(ibypath, "w")
        out.write("#ifndef __%s_IBY__\n" % self.name.upper())
        out.write("#define __%s_IBY__\n" % self.name.upper())
        out.write("\n")
        out.write("#include <bldvariant.hrh>\n")
        out.write("\n")
        out.write("data=%s/%s.themeindex\t%s/%s.themeindex\n" % (SOURCE_PREFIX, self.name, TARGET_PREFIX, self.name))
        written_entries = list()
        for path, files in self.files.iteritems():
            relpath = os.path.relpath(path, INPUT_DIR).replace("\\", "/")
            for filepath in files:
                filename = os.path.basename(filepath)
                entry = posixpath.join(relpath, filename)
                if entry not in written_entries:
                    written_entries.append(filepath)
                    out.write("data=%s/%s\t%s/%s\n" % (SOURCE_PREFIX, entry, TARGET_PREFIX, entry))
                else:
                    print "ERROR: %s duplicate entry %s" % (ibypath, entry)
                    EXIT_STATUS = -1
        for path, archives in self.archives.iteritems():
            relpath = os.path.relpath(path, INPUT_DIR).replace("\\", "/")
            for archive in archives:
                files = zip_filelist(archive)
                for filepath in files:
                    entry = posixpath.join(relpath, filepath)
                    if entry not in written_entries:
                        written_entries.append(entry)
                        out.write("data=%s/%s\t%s/%s\n" % (SOURCE_PREFIX, entry, TARGET_PREFIX, entry))
                    else:
                        print "ERROR: %s duplicate entry %s" % (ibypath, entry)
                        EXIT_STATUS = -1
        out.write("\n")
        out.write("#endif __%s_IBY__\n" % self.name.upper())
        out.close()

    def write_thx(self, thxpath):
        global SOURCE_PREFIX, TARGET_PREFIX, EXIT_STATUS
        outpath = os.path.dirname(thxpath)
        if not os.path.exists(outpath):
            os.makedirs(outpath)
        archive = zipfile.ZipFile(thxpath, "w")
        os.chdir(INPUT_DIR)
        written_entries = list()
        for path, files in self.files.iteritems():
            relpath = os.path.relpath(path, INPUT_DIR).replace("\\", "/")
            for filepath in files:
                filename = os.path.basename(filepath)
                entry = posixpath.join(relpath, filename)
                if entry not in written_entries:
                    written_entries.append(entry)
                    archive.write(entry)
                else:
                    print "ERROR: %s duplicate entry %s" % (thxpath, entry)
                    EXIT_STATUS = -1
        archive.close()

    def hidden(self):
        result = False
        config = ConfigParser.ConfigParser()
        indexthemepath = INPUT_DIR + '/icons/' + self.name + '/index.theme'
        if os.path.exists(indexthemepath):
            config.read(indexthemepath)
            result = config.getboolean('Icon Theme', 'Hidden')
        return result

    def _include(self, filepath):
        result = True
        if INCLUDE != None:
            for pattern in INCLUDE:
                if not fnmatch.fnmatch(filepath, pattern):
                    result = False
        if EXCLUDE != None:
            for pattern in EXCLUDE:
                if fnmatch.fnmatch(filepath, pattern):
                    result = False
        return result

def lookup_themes(path):
    themes = {}
    if os.path.exists(path):
        # base: effects, icons...
        for base in os.listdir(path):
            basepath = posixpath.join(path, base)
            if os.path.isdir(basepath):
                # theme: footheme, bartheme...
                for theme in os.listdir(basepath):
                    themepath = posixpath.join(basepath, theme)
                    if os.path.isdir(themepath):
                        if theme not in themes:
                            themes[theme] = Theme(theme)
                        themes[theme].paths.append(themepath)
                        # special case: themeindex
                        themeindex = os.path.join(path, theme + ".themeindex")
                        if os.path.exists(themeindex):
                            themes[theme].add_file(themeindex)
    return themes

# ============================================================================
# main()
# ============================================================================
def main():
    global VERBOSE, INPUT_DIR, OUTPUT_DIR, INCLUDE, EXCLUDE, SOURCE_PREFIX, TARGET_PREFIX

    parser = OptionParser()
    (options, args) = parser.parse_args()

    if options.verbose != None:
        VERBOSE = options.verbose
    if options.input != None:
        INPUT_DIR = options.input
    if options.output != None:
        OUTPUT_DIR = options.output
    if options.include != None:
        INCLUDE = options.include
    if options.exclude != None:
        EXCLUDE = options.exclude
    if options.sourceprefix != None:
        SOURCE_PREFIX = options.sourceprefix
    if options.targetprefix != None:
        TARGET_PREFIX = options.targetprefix

    themes = lookup_themes(INPUT_DIR)
    for name, theme in themes.iteritems():
        theme.initialize()
        if theme.hidden():
            print "Generating: %s.iby" % name
            theme.write_iby(posixpath.join(OUTPUT_DIR, "%s.iby" % name))
        else:
            print "Generating: %s.thx" % name
            theme.write_thx(posixpath.join(OUTPUT_DIR, "%s.thx" % name))

    return EXIT_STATUS

if __name__ == "__main__":
    sys.exit(main())