diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:16:46 +0000 | 
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:16:46 +0000 | 
| commit | a7af74e75730559f7f9661e449eb269e356d9907 (patch) | |
| tree | 72026b40b3a513aa21d630fb09ae10edab7f9e18 /src | |
| download | pytdeextensions-a7af74e75730559f7f9661e449eb269e356d9907.tar.gz pytdeextensions-a7af74e75730559f7f9661e449eb269e356d9907.zip | |
Added KDE3 version of pykdeextensions
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/pykdeextensions@1097589 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
| -rw-r--r-- | src/kdedesigner.py | 25 | ||||
| -rw-r--r-- | src/kdedistutils.py | 2209 | ||||
| -rw-r--r-- | src/pythonize.cpp | 238 | ||||
| -rw-r--r-- | src/pythonize.h | 104 | ||||
| -rw-r--r-- | src/qtdesigner.py | 26 | ||||
| -rw-r--r-- | src/qtuicompiler.py | 111 | 
6 files changed, 2713 insertions, 0 deletions
| diff --git a/src/kdedesigner.py b/src/kdedesigner.py new file mode 100644 index 0000000..7a2b898 --- /dev/null +++ b/src/kdedesigner.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +############################################################################ +# kdedesigner - description                                               # +# ------------------------------                                          # +# begin     : Thu Apr 21 2005                                             # +# copyright : (C) 2005 by Simon Edwards                                   # +# email     : simon@simonzone.com                                         # +#                                                                         # +########################################################################### +#                                                                         # +#   This program is free software; you can redistribute it and/or modify  # +#   it under the terms of the GNU Library General Public License as       # +#   published by the Free Software Foundation; either version 2 of the    # +#   License, or (at your option) any later version.                       # +#                                                                         # +########################################################################### + +import __builtin__ +import qtuicompiler + +python_import = __builtin__.__import__ +def load(*args): +    qtuicompiler.DynamicImport(args,True) +    return apply(python_import,args) +__builtin__.__import__ = load diff --git a/src/kdedistutils.py b/src/kdedistutils.py new file mode 100644 index 0000000..b6e2458 --- /dev/null +++ b/src/kdedistutils.py @@ -0,0 +1,2209 @@ +#!/usr/bin/python +########################################################################### +# kdedistutils - description                                              # +# ------------------------------                                          # +# begin     : Thu Apr 21 2005                                             # +# copyright : (C) 2005 by Simon Edwards                                   # +# email     : simon@simonzone.com                                         # +#                                                                         # +########################################################################### +#                                                                         # +#   This program is free software; you can redistribute it and/or modify  # +#   it under the terms of the GNU Library General Public License as       # +#   published by the Free Software Foundation; either version 2 of the    # +#   License, or (at your option) any later version.                       # +#                                                                         # +########################################################################### + +import distutils.core +from distutils.core import Extension +from distutils.cmd import Command +from distutils.dist import Distribution +from distutils.command.build import build +from distutils.command.install import install +from distutils.command.install_scripts import install_scripts +from distutils.command.install_data import install_data +from distutils.command.install_lib import install_lib +from distutils.util import change_root, convert_path +from distutils.spawn import find_executable,spawn +from distutils import sysconfig  +from distutils import log +from distutils import file_util +from distutils import dir_util +from distutils.util import byte_compile +import qtuicompiler +import stat +import os,os.path,imp,glob +import sys +from types import StringType + +INSTALL_LIST = 'install_log.txt' + +########################################################################### +def setup(**arg_dict): + +    if 'cmdclass' not in arg_dict: +        arg_dict['cmdclass'] = {} + +    cmdclass = arg_dict['cmdclass'] +     +    arg_dict.setdefault('data_files',[]) +     +    kdecmdclass = {'install' : InstallKDE, +        'install_executable_links' : InstallExecutableLinks, +        'install_application_data' : InstallApplicationDataAndLinks, +        'build_messages' : BuildI18NMessages, +        'install_messages' : InstallI18NMessages, +        'update_messages' : UpdateI18NMessages, +        'checkpyqt' : CheckPyQt, +        'checkpykde' : CheckPyKDE, +        'uninstall' : Uninstall, +        'build' : BuildKDE, +        'build_kcm' : BuildKControlModule, +        'install_kcm' : InstallKControlModule, +        'build_html' : BuildDocbookHTML, +        'install_html' : InstallDocbookHTML, +        'install_lib' : InstallLibWithRoot, +        'build_kioslave' : BuildKioslave, +        'install_kioslave' : InstallKioslave} + +    for key in kdecmdclass.iterkeys(): +        cmdclass.setdefault(key,kdecmdclass[key]) + +    arg_dict.setdefault('distclass',KDEDistribution) + +    apply(distutils.core.setup,[],arg_dict) + +########################################################################### +class KDEDistribution(Distribution): +    def __init__(self,attrs=None): +        self.min_kde_version = None +        self.min_qt_version = None +        self.kcontrol_modules = None +        self.kioslaves = None +        self.executable_links = None +        self.docbooks = None +        self.application_data = None +        self.i18n = None +        Distribution.__init__(self,attrs) + +########################################################################### +def has_kcms(self): +    if self.distribution.kcontrol_modules is None: +        return 0 +    return  len(self.distribution.kcontrol_modules)!=0 + +def has_docbook_html(self): +    if self.distribution.docbooks is None: +        return 0 +    return  len(self.distribution.docbooks)!=0 + +def has_messages(self): +    if self.distribution.i18n is None: +        return 0 +    return  len(self.distribution.i18n)!=0 + +def has_application_data(self): +    if self.distribution.application_data is None: +        return 0 +    return  len(self.distribution.application_data)!=0 + +def has_kioslaves(self): +    if self.distribution.kioslaves is None: +        return 0 +    return  len(self.distribution.kioslaves)!=0 + +########################################################################### +# Our slightly extended build command. This also does kcontrol modules. +class BuildKDE(build): + +    user_options = build.user_options[:] +    user_options.append( ('msgfmt-exe=',None,'Path to the msgfmt executable') ) +    user_options.append( ('meinproc-exe=',None,'Path to the meinproc executable') ) + +    sub_commands = build.sub_commands[:] +    sub_commands.append( ('build_kcm',has_kcms) ) +    sub_commands.append( ('build_kioslave',has_kioslaves) ) +    sub_commands.append( ('build_html',has_docbook_html) ) +    sub_commands.append( ('build_messages',has_messages) ) +     +    def __init__(self,dist): +        build.__init__(self,dist) +        self.has_kcms = has_kcms +        self.has_kioslaves = has_kioslaves +        self.has_docbook_html = has_docbook_html +        self.has_messages = has_messages + +    def initialize_options(self): +        self.msgfmt_exe = None +        self.meinproc_exe = None +        build.initialize_options(self) +         +    def finalize_options(self): +        build.finalize_options(self) +         +        if self.msgfmt_exe is None: +            # Find msgfmt +            canidatepaths = [] +            canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() ) +            self.msgfmt_exe = FindExeOnPath('msgfmt',canidatepaths) +            if self.msgfmt_exe is None: +                raise SystemExit, "Unable to find 'msgfmt', needed to build i18n messages." +         +        if self.meinproc_exe is None: +            # Find meinproc +            canidatepaths = [] +            canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() ) +            self.meinproc_exe = FindExeOnPath('meinproc',canidatepaths) +            if self.meinproc_exe is None: +                raise SystemExit, "Unable to find 'meinproc', needed to generate Docbook HTML documentation." + +########################################################################### +def has_executable_links(self): +    if self.distribution.executable_links is None: +        return 0 +    return  len(self.distribution.executable_links)!=0 + +########################################################################### +class InstallKDE(install): +    user_options = install.user_options[:] +    user_options.append( ('kde-prefix=',None,"KDE installation prefix") ) +    user_options.append( ('install-messages=',None,"installation directory for i18n message files") ) +    user_options.append( ('install-html=',None,"installation directory for Docbook HTML files") ) +    user_options.append( ('install-cmd=',None,"Command to use to install the files") ) +    user_options.append( ('install-xdg-apps=',None,"directory for XDG app files") ) +    user_options.append( ('install-kcm=',None,"directory for kcm library files") ) +    user_options.append( ('install-kioslave',None,"directory for kioslave library files") ) +    user_options.append( ('install-protocol',None,"directory for kioslave protocol files") ) +     +    sub_commands = install.sub_commands[:] +    sub_commands.insert(0, ('checkpykde',None) ) +    sub_commands.insert(0, ('checkpyqt',None) ) +    sub_commands.append( ('install_executable_links',has_executable_links) ) +    sub_commands.append( ('install_messages',has_messages) ) +    sub_commands.append( ('install_html',has_docbook_html) ) +    sub_commands.append( ('install_kcm',has_kcms) ) +    sub_commands.append( ('install_kioslave',has_kioslaves) ) +    sub_commands.append( ('install_application_data',has_application_data) ) +         +    def initialize_options(self): +        self.kde_prefix = None +        self.install_messages = None +        self.install_html = None +        self.install_cmd = None +        self.install_xdg_apps = None +        self.install_kcm = None +        self.install_kioslave = None +        self.install_protocol = None +        self.install_application_data = None +        install.initialize_options(self) +         +    def finalize_options(self): +        # If no install prefix was provided, then we try to detect the KDE install prefix. +        self.user_supplied_kde_prefix = True +         +        if self.install_scripts is None: +            if self.kde_prefix is not None: +                self.install_scripts = os.path.join(self.kde_prefix,'bin') +            else: +                self.announce("Detecting KDE 'bin' directory...") +                self.install_scripts = ask_kde_config('--install exe --expandvars').strip() +                self.announce("   ...KDE 'bin' directory is %s" % self.install_scripts) +             +        if self.install_application_data is None: +            if self.kde_prefix is not None: +                self.install_application_data = os.path.join(self.kde_prefix,'share/apps',self.distribution.metadata.name) +            else: +                self.announce("Detecting KDE application directory...") +                kdeappdir = ask_kde_config('--install data --expandvars').strip() +                self.announce("  ...KDE application directory is %s" % self.install_application_data) +                self.install_application_data = os.path.join(kdeappdir,self.distribution.metadata.name) + +        if self.install_messages is None: +            if self.kde_prefix is not None: +                self.install_messages = os.path.join(self.kde_prefix,'share/locale') +            else: +                self.announce("Detecting KDE messages directory...") +                self.install_messages = ask_kde_config('--install locale --expandvars').strip() +                self.announce("  ...KDE messages directory is %s" % self.install_messages) + +        if self.install_html is None: +            if self.kde_prefix is not None: +                self.install_html = os.path.join(self.kde_prefix,'share/doc/HTML') +            else: +                self.announce("Detecting KDE HTML directory...") +                self.install_html = ask_kde_config('--install html --expandvars').strip() +                self.announce("  ...KDE HTML directory is %s" % self.install_html) + +        if self.kde_prefix is None: +            self.announce("Detecting KDE install prefix...") +            self.kde_prefix = ask_kde_config('--prefix').strip() +            self.announce("  ...KDE install prefix is %s" % self.kde_prefix) +            self.user_supplied_kde_prefix = False +             +        if self.install_cmd is None: +            self.announce("Detecting 'install' command...") +            # Ok, time to find the install command. +            self.install_cmd = find_executable('install') +            if self.install_cmd is None: +                raise SystemExit, "Unable to find the 'install' command, needed to install libraries." +            self.announce("  ...'install' command is %s" % self.install_cmd) +         +        if self.install_xdg_apps is None: +            self.announce("Detecting XDG apps directory...") +            self.install_xdg_apps = ask_kde_config('--install xdgdata-apps --expandvars').strip() +            self.announce("  ...XDG apps directory is %s" % self.install_xdg_apps) + +        if self.install_kcm is None: +            self.announce("Detecting kcm library  directory...") +            self.install_kcm = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'kde3') +            self.announce("  ...kcm library directory is %s" % self.install_kcm) +     +        if self.install_kioslave is None: +            self.announce("Detecting kioslave library  directory...") +            self.install_kioslave = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'kde3') +            self.announce("  ...kioslave library directory is %s" % self.install_kioslave) +     +        if self.install_protocol is None: +            self.announce("Detecting kioslave protocol directory...") +            self.install_protocol = ask_kde_config('--install services --expandvars').strip() +            self.announce("  ...kioslave protocol directory is %s" % self.install_protocol) +     +        install.finalize_options(self) +         +        if self.root is not None: +            self.change_roots('application_data','html','messages','xdg_apps','kcm') +         +    def get_command_name(self): +        return 'install' +         +    def run(self): +        global INSTALL_LIST +        install.run(self) +         +        # Write out the uninstall list. +        fhandle = open(INSTALL_LIST,'w') +        for item in self.get_outputs(): +            fhandle.write(item) +            fhandle.write('\n') +        fhandle.close() + +########################################################################### +class InstallApplicationDataAndLinks(install_data): +    def get_command_name(self): +        return 'install_application_data' +         +    def initialize_options(self): +        install_data.initialize_options(self) + +        self.data_files = self.distribution.application_data +         +    def finalize_options(self): +        self.set_undefined_options('install', +                                   ('install_application_data', 'install_dir'), +                                   ('root', 'root'), +                                   ('force', 'force'), +                                  ) +         +    def run(self): +        self.outfiles.extend(self.mkpath(self.install_dir)) +        for f in self.data_files: +            if type(f) is StringType: +                # it's a simple file, so copy it +                f = convert_path(f) +                if self.warn_dir: +                    self.warn("setup script did not provide a directory for " +                              "'%s' -- installing right in '%s'" % +                              (f, self.install_dir)) +                if os.path.isfile(f): +                    (out, _) = self.copy_file(f, self.install_dir) +                    self.outfiles.append(out) +                elif os.path.isdir(f): +                    out = self.copy_tree(f,os.path.join(self.install_dir,f)) +                    self.outfiles.extend(out) +                else: +                    self.warn("Setup script can't find file or directory %s needed for installation." % f) +            else: +                # it's a tuple with path to install to and a list of files +                dir = convert_path(f[0]) +                if not os.path.isabs(dir): +                    dir = change_root(self.install_dir, dir) +                elif self.root: +                    dir = change_root(self.root, dir) +                self.outfiles.extend(self.mkpath(dir)) + +                if f[1] == []: +                    # If there are no files listed, the user must be +                    # trying to create an empty directory, so add the +                    # directory to the list of output files. +                    self.outfiles.append(dir) +                else: +                    # Copy files, adding them to the list of output files. +                    for data in f[1]: +                        data = convert_path(data) +                        if os.path.islink(data): +                            # Transplant the link to the new location without changing +                            # where it points to. (ie it is _not_ relocated). +                            dest = os.path.join(dir, os.path.basename(data)) +                            if os.path.exists(dest): +                                os.remove(dest) +                            os.symlink(os.readlink(data),dest) +                            log.info("moving link %s -> %s" % (data,dest) ) +                            #os.chmod(dest, os.stat(data)[stat.ST_MODE]) +                        elif os.path.isdir(data): +                            out = self.copy_tree(data,dir) +                            self.outfiles.extend(out) +                        else: +                            (out, _) = self.copy_file(data, dir) +                            self.outfiles.append(out) +         +        # Compile the .ui files +        install_cmd = self.get_finalized_command('install') +        prefix = self.install_dir +        if prefix[-1] != os.sep: +            prefix = prefix + os.sep +        self.outfiles.extend(compile_qtdesigner(self.outfiles, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run)) +         +        # Byte compile the .py files +        from distutils.util import byte_compile +        byte_compile(self.outfiles, optimize=0, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run) + +        # Add the .pyc files to the list of outfiles. +        self.outfiles.extend( [item+'c' for item in self.outfiles if item.endswith('.py')] ) + +    def mkpath(self, name, mode=0777): +        return dir_util.mkpath(name, mode, dry_run=self.dry_run) +     +########################################################################### +class InstallExecutableLinks(Command): +    description = "Install symlinks" + +    user_options = [] + +    def initialize_options(self): +        self.outfiles = [] + +    def finalize_options(self): +        pass +         +    def get_command_name(self): +        return 'install_executable_links' +         +    def run(self): +        # FIXME add cmd options? +        install_script_cmd = self.get_finalized_command('install_scripts') +        install_data_cmd = self.get_finalized_command('install_application_data') +         +        destination_dir = install_data_cmd.install_dir +         +        if not os.path.exists(install_script_cmd.install_dir): +            self.outfiles.extend(self.mkpath(install_script_cmd.install_dir)) +         +        if self.distribution.executable_links is not None: +            for link in self.distribution.executable_links: +                symname = os.path.join(install_script_cmd.install_dir,link[0]) +                target = os.path.join(destination_dir,link[1]) +                log.info("symlinking %s -> %s", symname, target) +                if not self.dry_run: +                    if os.path.islink(symname): +                        os.remove(symname) +                    os.symlink(target,symname) +                self.outfiles.append(symname) + +    def get_outputs(self): +        return self.outfiles or [] +         +    def mkpath(self, name, mode=0777): +        return dir_util.mkpath(name, mode, dry_run=self.dry_run) +         +########################################################################### +# Fix the --root option for the install_lib command. +class InstallLibWithRoot(install_lib): +    user_options = install_lib.user_options[:] +    user_options.append( ('root=',None,"install everything relative to this alternate root directory") ) +         +    def initialize_options(self): +        install_lib.initialize_options(self) +        self.root = None +         +    def finalize_options(self): +        own_install_dir = self.install_dir is not None +         +        install_lib.finalize_options(self) +        self.set_undefined_options('install', ('root', 'root')) +         +        if self.root is not None and own_install_dir: +            self.install_dir = change_root(self.root, self.install_dir) +         +########################################################################### +class Uninstall(Command): +    description = "Remove all installed files" + +    user_options = [] + +    def initialize_options(self): +        pass + +    def finalize_options(self): +        pass +         +    def get_command_name(self): +        return 'uninstall' + +    def run(self): +        global INSTALL_LIST +         +        if not os.path.isfile(INSTALL_LIST): +            self.announce("Unable to uninstall, can't find the file list %s." % INSTALL_LIST) +            return +             +        # Suck in the file list. +        fhandle = open(INSTALL_LIST,'r') +        file_list = fhandle.readlines() +        fhandle.close() +         +        # Remove the files first. +        for item in file_list: +            item = item.strip() +            if os.path.isfile(item) or os.path.islink(item): +                self.announce("removing '%s'" % item) +                if not self.dry_run: +                    try: +                        os.remove(item) +                    except OSError, details: +                        self.warn("Could not remove file: %s" % details) +            elif not os.path.isdir(item): +                self.announce("skipping removal of '%s' (does not exist)" % item) + +        # Remove the directories. +        file_list.sort() +        file_list.reverse() +        # Starting with the longest paths first. +        for item in file_list: +            item = item.strip() +            if os.path.isdir(item): +                self.announce("removing '%s'" % item) +                if not self.dry_run: +                    try: +                        os.rmdir(item) +                    except OSError, details: +                        self.warn("Could not remove directory: %s" % details) + +########################################################################### +class BuildKControlModule(Command): +    description = "Build KControl extensions" + +    user_options = [('no-kcontrol',None,"Don't build kcontrol extensions"), +                    ('build-dir=','b', "build directory (where to install from)"), +                    ('python-dir=',None,'Directory containing the Python installation'), +                    ('python-inc-dir=',None,'Directory containing C Header files for Python'), +                    ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'), +                    ('kde-lib-dir=',None,'Directory containing library files for KDE'), +                    ('kde-kcm-lib-dir=',None,'Directory for KDE kcm library files'), +                    ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'), +                    ('qt-lib-dir=',None,'Directory containing library files for Qt'), +                    ('sip-dir=','/usr/lib/pyshared/python2.6','Directory containing the sip library files'), +                    ('clib=',None,'gcc library and path'), +                    ('pyqt-dir=','/usr/lib/pyshared/python2.6','PyQt module directory'), +                    ('pykde-dir=',None,'PyKDE module directory'), +                    ('data-dir=',None,'installation directory for data (script) files')] +     +    def initialize_options(self): +        self.no_kcontrol = 0 +        self.build_dir = None +        self.python_inc_dir = None +        self.python_dir = None +        self.kde_inc_dir = None +        self.kde_lib_dir = None +        self.kde_kcm_lib_dir = None +        self.qt_inc_dir = None +        self.qt_lib_dir = None +        self.sip_dir = "/usr/lib/pyshared/python2.6" +        self.clib = None +        self.pyqt_dir = "/usr/lib/pyshared/python2.6" +        self.pykde_dir = None +        self.data_dir = None +         +    def finalize_options(self): +        if self.no_kcontrol==0: +            self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir')) +         +            install = self.get_finalized_command('install') +            self.install_prefix = "/opt/kde3/" +     +            # KDE inc dir: find it! +            if self.kde_inc_dir is None: +                canidatepaths = [] +                kdedir = os.getenv("KDEDIR") +                if kdedir!=None: +                    canidatepaths.append(os.path.join(kdedir,"include")) +                canidatepaths.append(os.path.join(install.prefix,"include")) +                canidatepaths.append('/opt/kde3/include') +                canidatepaths.append('/opt/kde/include') +                self.kde_inc_dir = FindFileInPaths('kapplication.h',canidatepaths) +            if self.kde_inc_dir is None: +                raise SystemExit, "Failed to find the KDE header file directory." +            if FindFileInPaths('kapplication.h',[self.kde_inc_dir]) is None: +                raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir +            self.announce("Using %s for KDE header files" % self.kde_inc_dir) +     +            # KDE lib dir +            #if self.kde_lib_dir is None: +            #    self.kde_lib_dir = os.path.join(install.prefix,"lib") +            self.kde_lib_dir = "/opt/kde3/lib/" +            self.announce("Using %s for KDE library files" % self.kde_lib_dir) +     +            # KDE KCM lib dir +            #if self.kde_kcm_lib_dir is None: +            #    self.kde_kcm_lib_dir = os.path.join(self.kde_lib_dir,"kde3") +            self.kde_kcm_lib_dir = "/opt/kde3/lib/kde3/" +            if FindFileInPaths('*kcm*.so',[self.kde_kcm_lib_dir]) is None: +                raise SystemExit, "Failed to find KDE KCM files in: %s" % self.kde_kcm_lib_dir +            self.announce("Using %s for KDE KCM library files" % self.kde_kcm_lib_dir) +             +            # Qt inc dir +            if self.qt_inc_dir is None: +                canidatepaths = [] +                qtdir = os.getenv("QTDIR") +                if qtdir != None: +                    canidatepaths.append(os.path.join(qtdir,"include")) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include")) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include")) +                canidatepaths.append(os.path.join(install.prefix,"include")) +                canidatepaths.append("/opt/qt3/include") +                canidatepaths.append("/opt/qt/include") +                canidatepaths.append("/opt/qt/lib/include") +                canidatepaths.append("/opt/qt3/lib/include") +		canidatepaths.append("/usr/include/qt3") +                self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths) +            if self.qt_inc_dir is None: +                raise SystemExit,"Failed to find the Qt header file directory" +            if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None: +                raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir +            self.announce("Using %s for Qt header files" % self.qt_inc_dir) +     +            # Qt lib dir +            if self.qt_lib_dir is None: +                canidatepaths = [] +                qtdir = os.getenv("QTDIR") +                if qtdir != None: +                    canidatepaths.append(os.path.join(qtdir,get_libdir_name())) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name())) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name())) +                canidatepaths.append(os.path.join(install.prefix,get_libdir_name())) +                canidatepaths.append("/opt/qt3/"+get_libdir_name()) +                canidatepaths.append("/opt/qt/"+get_libdir_name()) +                canidatepaths.append("/opt/qt/lib/"+get_libdir_name()) +                canidatepaths.append("/opt/qt3/lib/"+get_libdir_name()) +                self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths) +            if self.qt_lib_dir is None: +                raise SystemExit, "Failed to find Qt library files" +            self.announce("Using %s for Qt library files" % self.qt_lib_dir) +                     +            # Python dir +            if self.python_dir is None: +                self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[0] +            self.announce("Using %s for the python directory" % self.python_dir) +             +            # Python include dir. +            if self.python_inc_dir is None: +                # Find the Python include directory. +                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY") +            self.announce("Using %s for Python header files" % self.python_inc_dir) +     +            # PyQt dir +            if self.pyqt_dir is None: +                self.pyqt_dir = sysconfig.get_python_lib() +            if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None): +                raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir +            self.announce("Using %s for PyQt modules" % self.pyqt_dir) +     +            # PyKDE dir +            if self.pykde_dir is None: +                self.pykde_dir = sysconfig.get_python_lib() +            if (FindFileInPaths("libkdecorecmodule*",[self.pykde_dir]) is None) and (FindFileInPaths("kdecore*",[self.pykde_dir]) is None): +                raise SystemExit, "Failed to find the PyKDE directory: %s" % self.pykde_dir +            self.announce("Using %s for PyKDE modules" % self.pykde_dir) +             +            # Sip dir +            if self.sip_dir is None: +                self.sip_dir = sysconfig.get_python_lib() +            if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None): +                raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir +            self.announce("Using %s for libsip files" % self.sip_dir) +                 +            # Find the C library (libgcc, libgcc_s or some other variation). +            if self.clib is None: +                canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name() ] +                self.clib = FindFileInPaths("libgcc*.so",canidatepaths) +                if self.clib!=None: +                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0] +                else: +                    self.clib = FindFileInPaths("libgcc*.a",canidatepaths) +                    if self.clib!=None: +                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0] +            if self.clib is None: +                raise SystemExit, "Failed to find a suitable libgcc library" +            self.announce("Using %s for clib" % self.clib) +     +            # Make a list of places to look for python .so modules +            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split() +            base = sysconfig.get_config_var("LIBP") +            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ] +            self.python_sub_dirs.append(base) + +    def get_command_name(self): +        return 'build_kcm' + +    def run(self): +        if self.no_kcontrol: +            self.announce("Skipping KControl modules") +            return +     +        if not os.path.isdir(self.build_dir): +            os.mkdir(self.build_dir) +         +        for moduletuple in self.distribution.kcontrol_modules: +            self.announce("Building KControl module from desktop file %s." % moduletuple[0]) +             +            # Read the desktop file +            factoryfunction = None +            libraryname = None +            cmodulecategory = None +            try: +                fhandle = open(moduletuple[0],'r') +                for line in fhandle.readlines(): +                    parts = line.strip().split('=') +                    try: +                        if parts[0]=="X-KDE-Library": +                            libraryname = parts[1] +                        elif parts[0]=="Exec": +                            shellcmd = parts[1].split() +                            modulepath = shellcmd[-1] +                            if '/' in modulepath: +                                cmodulecategory = os.path.dirname(modulepath) +                            else: +                                cmodulecategory = "" +                        elif parts[0]=="X-KDE-FactoryName": +                            factoryfunction = 'create_'+parts[1] +                    except IndexError: +                        pass +                fhandle.close() +            except IOError: +                raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0] +                 +            # Sanity check. +            if factoryfunction is None: +                raise SystemExit, "Failed to find factory name (Was there a X-KDE-FactoryName entry in the desktop file?)" +            if libraryname is None: +                raise SystemExit, "Failed to find library name (Was there a X-KDE-Library entry in the desktop file?)" +            if cmodulecategory is None: +                raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)" +             +            modulename = os.path.basename(moduletuple[1]) +            if modulename.endswith('.py'): +                modulename = modulename[:-3] +            desktopfilename = moduletuple[0] +             +            stub_cpp_name = 'kcm_'+libraryname+'.cpp' +            stub_so_name = 'kcm_'+libraryname+'.so' +            stub_la_name = 'kcm_'+libraryname+'.la' +            python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1]) +             +            # Build the 'stub' code. +            cppcode = self.cpptemplate % {"moduledir": self.data_dir, +                                            "modulename": modulename, +                                            "factoryfunction": factoryfunction, +                                            "python_version": python_version} +             +            # Put it on disk. +            cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name) +            try: +                fhandle = open(cppfile,'w') +                fhandle.write(cppcode) +                fhandle.close() +            except IOError: +                raise SystemExit, "Could not write the C++ stub: %s" % cppfile +                 +            # Compile the stub library. +            cmdlist = ['libtool'] + +            # Couldn't get it to pass without this ... +            cmdlist.append("--mode=compile") +            cmdlist.append("--tag=CXX") +             +            # Find the compiler flags and options +            # CXX is empty on some Systems, let's do it 'the hard way'. +            # FIXME :: get CXX from make.conf for Gentoo. +            if len(sysconfig.get_config_var("CXX").split()) >= 2: +                cmdlist.extend(sysconfig.get_config_var("CXX").split()) +            else: +                cmdlist.extend(['g++', '-pthread']) + +            #cmdlist.extend(sysconfig.get_config_var("CXX").split()) +             +            # cc_flags +            cmdlist.append("-c") +            cmdlist.append("-g") +             +            # The 4 is randomly chosen! +            # FIXME :: get CFLAGS from make.conf for Gentoo. +            if len(sysconfig.get_config_var("CFLAGS").split()) >=4: +                cmdlist.extend(sysconfig.get_config_var("CFLAGS").split()) +            else: +                # On Gentoo systems, CFLAGS are not in the environment. +                raw = os.popen('emerge info 2> /dev/null|grep CFLAGS') +                lines = raw.readlines() +                if len(lines): +                    cflags = lines[0].split('"')[1].split() +                    print "Got CFLAGS from emerge info." +                    cmdlist.extend(cflags) +                else: +                    # Still no CFLAGS found, use these ... +                    cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes']) +                 +            #sysconfig.get_config_var("CFLAGS").split() +            # includes +            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR")) +            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR")) +            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY")) +            cmdlist.append("-I" + self.python_inc_dir) +            cmdlist.append("-I" + self.kde_inc_dir) +            cmdlist.append("-I" + self.qt_inc_dir) +            cmdlist.append("-I.") +            # input +            cmdlist.append(cppfile) +            # output +            outputfile = os.path.join(self.build_dir,libraryname+'.lo') +            cmdlist.append("-o") +            cmdlist.append(outputfile) +            spawn(cmdlist) # Execute!!! +            print +             +            # Link the resulting object file to create a shared library. +            cmdlist = ['libtool'] +            cmdlist.append("--mode=link") +             +            # Grab the linker command name +            cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0]) +            # link_flags +            cmdlist.append("-module") +            cmdlist.append("-export-dynamic") +            # object +            cmdlist.append(outputfile) +            cmdlist.append("-rpath"); cmdlist.append(self.kde_kcm_lib_dir) +            cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name)) +            # Link libs +            linklist = [] +            linklist.append("-lpython%s" % python_version) +            linklist.extend(sysconfig.get_config_var("LIBS").split()) +             +            # FIXME I doubt half of these libraries need to be here. +            linklist.append(self.sip_dir+"/sip.so") +            # PyQt libs +            linklist.append(self.pyqt_dir+"/qt.so") +            # PyKDE libs +            linklist.append(self.pykde_dir+"/kdecore.so") +            linklist.append(self.pykde_dir+"/kdeui.so") +             +#            linklist.append("-L"+self.sip_dir); linklist.append("-lsip") +#            # PyQt libs +#            linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule") +#            # PyKDE libs +#            linklist.append("-L"+self.pykde_dir); linklist.append("-lkdecorecmodule"); linklist.append("-lkdeuicmodule") +             +            linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/kde3/lib"); linklist.append("-lkdecore"); linklist.append("-lpythonize") +            linklist.append("-L"+self.qt_lib_dir); linklist.append("-lqt-mt") +            linklist.append("-lm") +            linklist.append("-lstdc++") +            linklist.append("-lc") +            linklist.append(self.clib) + +            linklist.append("-R"); linklist.append(self.python_dir) +            linklist.append("-R"); linklist.append(self.qt_lib_dir) +            linklist.append("-R"); linklist.append(self.sip_dir) +            linklist.append("-R"); linklist.append(self.pyqt_dir) +            linklist.append("-R"); linklist.append(self.pykde_dir) +            linklist.append("-R"); linklist.append(self.kde_lib_dir) + +            cmdlist.extend(linklist) +            spawn(cmdlist) # Execute!! +            print +             +    cpptemplate = r""" +/* + * pykcm_launcher.cpp + *  + * Launch Control Centre modules written in Python using an embedded Python + * interpreter. + * Based on David Boddie's PyKDE-components. + */ + +// pythonize.h must be included first. +#include <pythonize.h> +#include <kcmodule.h> +#include <kglobal.h> +#include <klocale.h> +#include <klibloader.h> +#include <kstandarddirs.h> +#include <ksimpleconfig.h> +#include <qstring.h> +#include <sip.h> + +#define MODULE_DIR "%(moduledir)s" +#define EXTRA_MODULE_DIR "/opt/kde3/share/python-support/kde-guidance-kde3" +#define EXTRA_MODULE_DIR_TWO "/opt/kde3/share/python-support/guidance-backends-kde3" +#define EXTRA_MODULE_DIR_THREE "/opt/kde3/share/python-support/kde-guidance-powermanager-kde3" +#define MODULE_NAME "%(modulename)s" +#define FACTORY "%(factoryfunction)s" +#define CPP_FACTORY %(factoryfunction)s +#define LIB_PYTHON "libpython%(python_version)s.so" +#define debug 1 + +static KCModule *report_error(char *msg) { +    if (debug) printf ("error: %%s\n", msg); +    return NULL; +} + +static KCModule* return_instance( QWidget *parent, const char *name ) { +    KCModule* kcmodule; +    PyObject *pyKCModuleTuple;  +    PyObject *pyKCModule; +    Pythonize *pyize;  // Pythonize object to manage the Python interpreter. +    int isErr; +     +    // Try to determine what py script we're loading. Note that "name" +    // typically appears to be NULL. +    QString script(MODULE_NAME); + +    // Reload libpython, but this time tell the runtime linker to make the +    // symbols global and available for later loaded libraries/module. +    KLibLoader::self()->globalLibrary(LIB_PYTHON); +     +    // Start the interpreter. +    pyize = initialize(); +    if (!pyize) { +        return report_error ("***Failed to start interpreter\n"); +    } +     +    // Add the path to the python script to the interpreter search path. +    QString path = QString(MODULE_DIR); +    if(path == QString::null) { +        return report_error ("***Failed to locate script path"); +    } +    if(!pyize->appendToSysPath (path.latin1 ())) { +        return report_error ("***Failed to set sys.path\n"); +    } +    QString extrapath = QString(EXTRA_MODULE_DIR); +    if(!pyize->appendToSysPath (extrapath.latin1 ())) { +        return report_error ("***Failed to set extra sys.path\n"); +    } +    QString extrapath_two = QString(EXTRA_MODULE_DIR_TWO); +    if(!pyize->appendToSysPath (extrapath_two.latin1 ())) { +        return report_error ("***Failed to set extra 2 sys.path\n"); +    } +    QString extrapath_three = QString(EXTRA_MODULE_DIR_THREE); +    if(!pyize->appendToSysPath (extrapath_three.latin1 ())) { +        return report_error ("***Failed to set extra 3 sys.path\n"); +    } +     +    // Load the Python script. +    PyObject *pyModule = pyize->importModule ((char *)script.latin1 ()); +    if(!pyModule) { +        PyErr_Print(); +        return report_error ("***failed to import module\n"); +    } + +    // Inject a helper function +    QString bridge = QString("import sip\n"  +                            "import qt\n" +                            "def kcontrol_bridge_" FACTORY "(parent,name):\n" +                             "    if parent!=0:\n" +#if SIP_VERSION >= 0x040200 +                             "        wparent = sip.wrapinstance(parent,qt.QWidget)\n" +#else                              +                             "        wparent = sip.wrapinstance(parent,'QWidget')\n" +#endif +                             "    else:\n" +                             "        wparent = None\n" +                             "    inst = " FACTORY "(wparent, name)\n" +                             "    return (inst,sip.unwrapinstance(inst))\n"); +    PyRun_String(bridge.latin1(),Py_file_input,PyModule_GetDict(pyModule),PyModule_GetDict(pyModule)); + +    // Get the Python module's factory function. +    PyObject *kcmFactory = pyize->getNewObjectRef(pyModule, "kcontrol_bridge_" FACTORY); +    if(!kcmFactory) { +        return report_error ("***failed to find module factory\n"); +    } +     +    // Call the factory function. Set up the args. +    PyObject *pyParent = PyLong_FromVoidPtr(parent); +    PyObject *pyName = PyString_FromString(MODULE_NAME); +        // Using NN here is effect gives our references to the arguement away. +    PyObject *args = Py_BuildValue ("NN", pyParent, pyName); +    if(pyName && pyParent && args) { +        // run the factory function +        pyKCModuleTuple = pyize->runFunction(kcmFactory, args); +        if(!pyKCModuleTuple) { +            PyErr_Print(); +            return report_error ("*** runFunction failure\n;"); +        } +    } else { +        return report_error ("***failed to create args\n"); +    } +    // cleanup a bit +    pyize->decref(args); +    pyize->decref(kcmFactory); + +    // Stop this from getting garbage collected. +    Py_INCREF(PyTuple_GET_ITEM(pyKCModuleTuple,0)); +     +    // convert the KCModule PyObject to a real C++ KCModule *. +    isErr = 0; +    pyKCModule = PyTuple_GET_ITEM(pyKCModuleTuple,1); +    kcmodule = (KCModule *)PyLong_AsVoidPtr(pyKCModule); +    if(!kcmodule) { +        return report_error ("***failed sip conversion to C++ pointer\n"); +    } +    pyize->decref(pyKCModuleTuple); +     +    // PyKDE can't run the module without this - Pythonize +    // grabs the lock at initialization and we have to give +    // it back before exiting. At this point, we no longer need +    // it. +    //pyize->releaseLock (); + +    // take care of any translation info +    KGlobal::locale()->insertCatalogue(script); + +    // Return the pointer to our new KCModule +    return kcmodule; +} + +extern "C" { +    // Factory function that kcontrol will call. +    KCModule* CPP_FACTORY(QWidget *parent, const char *name) { +        return return_instance(parent, name); +    } +} +""" + +########################################################################### +class InstallKControlModule(Command): +    description = "Install Kcontrol module files" +     +    user_options = [ +        ('install-dir=', 'd', "base directory for installing kcontrol module files"), +        ('install-cmd=', None, "Command to use to install the files"), +        ('xdg-apps-dir=',None,"directory for XDG app files"), +        ('build-dir=','b', "build directory (where to install from)"), +        ('root=', None, "install everything relative to this alternate root directory"), +        ('force', 'f', "force installation (overwrite existing files)"), +        ('skip-build', None, "skip the build steps"), +        ] +    boolean_options = ['force', 'skip-build'] +     +    def initialize_options(self): +        self.build_dir = None +        self.install_dir = None +        self.install_cmd = None +        self.xdg_apps_dir = None +        self.outfiles = [] +        self.root = None +        self.force = 0 +        self.warn_dir = 1 +        self.skip_build = None + +    def finalize_options(self): +        own_install_dir = self.install_dir is not None +        own_xdg_apps_dir = self.xdg_apps_dir is not None +         +        self.set_undefined_options('install', +                                    ('build_base', 'build_dir'), +                                    ('install_kcm', 'install_dir'), +                                    ('install_xdg_apps','xdg_apps_dir'), +                                    ('root', 'root'), +                                    ('force', 'force'), +                                    ('skip_build', 'skip_build'), +                                    ('install_cmd', 'install_cmd') +                                    ) + +        if own_install_dir and self.root is not None: +            self.install_dir = change_root(self.root,self.installdir) +        if own_xdg_apps_dir and self.root is not None: +            self.xdg_apps_dir = change_root(self.root,self.xdg_apps_dir) +             +    def get_command_name(self): +        return 'install_kcm' +         +    def run(self): +        if not self.skip_build: +            self.run_command('build_kcm') +     +        self.announce("Installing Kcontrol module files...") + +        for moduletuple in self.distribution.kcontrol_modules: +            self.announce("Building KControl module from desktop file %s." % moduletuple[0]) +             +            # Read the desktop file +            libraryname = None +            cmodulecategory = None +            try: +                fhandle = open(moduletuple[0],'r') +                for line in fhandle.readlines(): +                    parts = line.strip().split('=') +                    try: +                        if parts[0]=="X-KDE-Library": +                            libraryname = parts[1] +                        elif parts[0]=="Exec": +                            shellcmd = parts[1].split() +                            modulepath = shellcmd[-1] +                            if '/' in modulepath: +                                cmodulecategory = os.path.dirname(modulepath) +                            else: +                                cmodulecategory = "" +                    except IndexError: +                        pass +                fhandle.close() +            except IOError: +                raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0] +                 +            if libraryname is None: +                raise SystemExit, "Failed to find library name (Was there a X-KDE-Library entry in the desktop file?)" +            if cmodulecategory is None: +                raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)" +                 +            desktopfilename = moduletuple[0] +            self.outfiles.extend(self.mkpath(self.xdg_apps_dir)) +            desktopfile_dest = os.path.join(self.xdg_apps_dir,os.path.basename(desktopfilename)) +            self.copy_file(desktopfilename, desktopfile_dest) +             +            stub_la_name = 'kcm_'+libraryname+'.la' +     +            self.outfiles.extend(self.mkpath(self.install_dir)) +             +            # Install the library. +            cmdlist = ['libtool'] +            cmdlist.append("--mode=install") +            cmdlist.append(self.install_cmd) +            cmdlist.append("-c") +            cmdlist.append(os.path.join(self.build_dir,stub_la_name)) +            cmdlist.append(os.path.join(self.install_dir,stub_la_name)) +            spawn(cmdlist) # Execute!! +            print + +            self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs','kcm_'+libraryname+'*'))] +            self.outfiles.append(desktopfile_dest) +             +        self.announce("Done installing Kcontrol module files.") +         +    def get_outputs(self): +        return self.outfiles or [] + +    def mkpath(self, name, mode=0777): +        return dir_util.mkpath(name, mode, dry_run=self.dry_run) + +########################################################################### +class BuildDocbookHTML(Command): +    description = "Build Docbook HTML documentation" + +    user_options = [('meinproc-exe=',None,"Path to the meinproc executable")] +     +    def initialize_options(self): +        self.html_prefix = None +        self.meinproc_exe = None +         +    def finalize_options(self): +        self.set_undefined_options('build', ('meinproc_exe', 'meinproc_exe') ) +         +    def get_command_name(self): +        return 'build_docbook' + +    def run(self): +        for docbook_tuple in self.distribution.docbooks: +            input_dir = docbook_tuple[0] +            language_code = docbook_tuple[1] +             +            self.announce("Building Docbook documentation from directory %s." % input_dir) +             +            indexdoc_file_name = os.path.join(input_dir,'index.docbook') +            if not os.path.exists(indexdoc_file_name): +                raise SystemExit, "File %s is missing." % indexdoc_file_name +             +            cwd = os.getcwd() +            os.chdir(input_dir) +            try: +                spawn([self.meinproc_exe,"--check","--cache",'index.cache.bz2', 'index.docbook']) +                spawn([self.meinproc_exe, 'index.docbook']) +            finally: +                os.chdir(cwd) +             +########################################################################### +class InstallDocbookHTML(Command): +    description = "Install Docbook HTML files" +     +    user_options = [ +        ('install-dir=', 'd',"base directory for installing docbook HTML files"), +        ('root=', None, "install everything relative to this alternate root directory"), +        ('force', 'f', "force installation (overwrite existing files)"), +        ('skip-build', None, "skip the build steps"), +        ] +    boolean_options = ['force', 'skip-build'] +     +    def initialize_options(self): +        self.install_dir = None +        self.outfiles = [] +        self.root = None +        self.force = 0 +        self.warn_dir = 1 +        self.skip_build = None + +    def finalize_options(self): +        own_install_dir = self.install_dir is not None +         +        self.set_undefined_options('install', +                                   ('install_html', 'install_dir'), +                                   ('root', 'root'), +                                   ('force', 'force'), +                                   ('skip_build', 'skip_build'), +                                  ) + +        if own_install_dir and self.root is not None: +            self.install_dir = change_root(self.root,self.installdir) +         +    def get_command_name(self): +        return 'install_html' +         +    def run(self): +        if not self.skip_build: +            self.run_command('build_html') +     +        self.announce("Installing HTML files...") +        counter = 0 +        for docbook_tuple in self.distribution.docbooks: +            input_dir = docbook_tuple[0] +            language_code = docbook_tuple[1] +             +            self.announce("Install Docbook documentation from directory %s." % input_dir) +            source_file = os.path.join(input_dir,'index.cache.bz2') +            if not os.path.exists(source_file): +                raise SystemExit, "File %s is missing." % source_file +             +            dest_path = os.path.join(self.install_dir, language_code, self.distribution.metadata.name) +            self.outfiles.extend(self.mkpath(dest_path)) +            dest_file = os.path.join(dest_path,'index.cache.bz2') +             +            self.copy_file(source_file, dest_file) +            self.outfiles.append(dest_file) +            counter += 1 +             +            # Also install any lose HTML files. +            for source_file in glob.glob(os.path.join(input_dir,'*.html')): +                htmlfile = os.path.basename(source_file) +                dest_file = os.path.join(dest_path,htmlfile) +                self.copy_file(source_file, dest_file) +                self.outfiles.append(dest_file) +                counter += 1 +             +            if len(docbook_tuple)==3: +                extra_files = docbook_tuple[2] +                for file in extra_files: +                    source_file = os.path.join(input_dir,file) +                    dest_file = os.path.join(self.install_dir, language_code, self.distribution.metadata.name,file) +                    self.copy_file(source_file, dest_file) +                    self.outfiles.append(dest_file) +                    counter += 1 +         +        self.announce("Done installing %i HTML files." % counter) +         +    def get_outputs(self): +        return self.outfiles or [] + +    def mkpath(self, name, mode=0777): +        return dir_util.mkpath(name, mode, dry_run=self.dry_run) + +########################################################################### +class UpdateI18NMessages(Command): +    description = "Extract and update messages for translation" + +    user_options = [('xgettext-exe=',None,'Full path to the xgetext executable'),\ +                    ('kde-pot=',None,'Location of the the KDE pot file'),\ +                    ('msgmerge-exe=',None,'Full path to the msgmerge executable')] + +    def initialize_options(self): +        self.xgettext_exe = None +        self.msgmerge_exe = None +        self.kde_pot = None +         +    def finalize_options(self): +        if self.xgettext_exe is None: +            install = self.get_finalized_command('install') +         +            canidate_paths = [] +            if install.user_supplied_kde_prefix: +                canidate_paths.append(os.path.join(install.kde_prefix,'bin')) +                 +            self.announce("Detecting xgettext...") +            canidate_paths.append(ask_kde_config('--install exe --expandvars').strip()) +            self.xgettext_exe = FindExeOnPath('xgettext',canidate_paths) +            if self.xgettext_exe is None: +                raise SystemExit, "Unable to find 'xgettext'." +            self.announce("  ...xgettext found at %s" % self.xgettext_exe) +             +        if self.msgmerge_exe is None: +            install = self.get_finalized_command('install') +         +            canidate_paths = [] +            if install.user_supplied_kde_prefix: +                canidate_paths.append(os.path.join(install.kde_prefix,'bin')) +                 +            self.announce("Detecting msgmerge...") +            canidate_paths.append(ask_kde_config('--install exe --expandvars').strip()) +            self.msgmerge_exe = FindExeOnPath('msgmerge',canidate_paths) +            if self.msgmerge_exe is None: +                raise SystemExit, "Unable to find 'xgettext'." +            self.announce("  ...msgmerge found at %s" % self.msgmerge_exe) +         +        if self.kde_pot is None: +            self.announce("Detecting kde.pot...") +            canidatepaths = [] +            kdedir = os.getenv("KDEDIR") +            if kdedir!=None: +                canidatepaths.append(os.path.join(kdedir,"include")) +            install = self.get_finalized_command('install') +            canidatepaths.append(os.path.join(install.kde_prefix,"include")) +            canidatepaths.append('/opt/kde3/include') +            canidatepaths.append('/opt/kde/include') +            kde_pot_dir = FindFileInPaths('kde.pot',canidatepaths) +             +            if kde_pot_dir is None: +                raise SystemExit, "Failed to find the kde.pot file." +                 +            self.kde_pot = os.path.join(kde_pot_dir,'kde.pot') +            self.announce("   ...kde.pot found at %s" % self.kde_pot) + +    def get_command_name(self): +        return 'update_messages' + +    def run(self): +        if self.distribution.i18n is None: return +         +        self.announce("Extracting and merging i18n messages...") +        po_dir = self.distribution.i18n[0] +         +        # FIXME : .rc and .ui files +        input_files = [] +         +        # Compile any UI files +        for dir in self.distribution.i18n[1]: +            for file in glob.glob(os.path.join(dir,'*.ui')): +                qtuicompiler.UpdateUI(file,kde=True) +         +        # Fetch all of the python files. +        for dir in self.distribution.i18n[1]: +            input_files.extend(glob.glob(os.path.join(dir,'*.py'))) +         +        target_pot = os.path.join(po_dir,self.distribution.metadata.name+".pot") +         +        cmd = [self.xgettext_exe, '-o', target_pot, '-ki18n', '-ktr2i18n', \ +                '-kI18N_NOOP', '-ktranslate', '-kaliasLocale','-x',self.kde_pot] +        cmd.extend(input_files) +        spawn(cmd) + +        for po_file in glob.glob(os.path.join(po_dir,'*.po')): +            temp_po = po_file + '.temp' +            cmd = [self.msgmerge_exe,'-q','-o',temp_po,po_file,target_pot] +            spawn(cmd) +            os.rename(temp_po,po_file) +         +        self.announce("Finished with i18n messages.") +         +########################################################################### +class BuildI18NMessages(Command): +    description = "Build i18n messages" + +    user_options = [('msgfmt-exe=',None,'Path to the msgfmt executable')] + +    def initialize_options(self): +        self.msgfmt_exe = None +         +    def finalize_options(self): +        self.set_undefined_options('build', ('msgfmt_exe', 'msgfmt_exe')) + +    def get_command_name(self): +        return 'build_messages' + +    def run(self): +        if self.distribution.i18n is None: return +         +        self.announce("Building i18n messages...") +        po_dir = self.distribution.i18n[0] +         +        i = 0 +        for po_file in [file for file in os.listdir(po_dir) if file.endswith('.po')]: +            source = os.path.join(po_dir,po_file) +            target = source[:-3]+'.gmo' +            cmd = [self.msgfmt_exe,'-o',target, source] +            spawn(cmd) +            i += 1 +        self.announce("Done building %i i18n messages." % i) + +########################################################################### +class InstallI18NMessages(Command): +    description = "Install messages" + +    user_options = [ +        ('install-dir=', 'd',"base directory for installing message files (default: installation base dir)"), +        ('root=', None, "install everything relative to this alternate root directory"), +        ('force', 'f', "force installation (overwrite existing files)"), +        ('skip-build', None, "skip the build steps"), +        ] +         +    boolean_options = ['force', 'skip-build'] +     +    def initialize_options(self): +        self.install_dir = None +        self.outfiles = [] +        self.root = None +        self.force = 0 +        self.warn_dir = 1 +        self.skip_build = None + +    def finalize_options(self): +        own_install_dir = self.install_dir is not None +         +        self.set_undefined_options('install', +                                   ('install_messages', 'install_dir'), +                                   ('root', 'root'), +                                   ('force', 'force'), +                                   ('skip_build', 'skip_build'), +                                  ) + +        if own_install_dir and self.root is not None: +            self.install_dir = change_root(self.root,self.installdir) +                           +    def get_command_name(self): +        return 'install_messages' +         +    def run(self): +        if not self.skip_build: +            self.run_command('build_messages') +     +        self.announce("Installing i18n messages...") +        po_dir = self.distribution.i18n[0] +         +        counter = 0 +        for po_file in os.listdir(po_dir): +            if po_file.endswith('.po'): +                source_file = os.path.join(po_dir,po_file[:-3]) + '.gmo' +                 +                # Setup installation of the translation file. +                dest_path = os.path.join(self.install_dir, po_file[:-3],'LC_MESSAGES') +                self.outfiles.extend(self.mkpath(dest_path)) +                dest_file = os.path.join(dest_path, self.distribution.metadata.name+'.mo') +                 +                self.copy_file(source_file, dest_file) +                self.outfiles.append(dest_file) +                counter += 1 +        self.announce("Done installing %i i18n messages." % counter) + +    def get_outputs(self): +        return self.outfiles + +    def mkpath(self, name, mode=0777): +        return dir_util.mkpath(name, mode, dry_run=self.dry_run) + +  +########################################################################### +class BuildKioslave(Command): +    description = "Build Kioslaves" + +    user_options = [('no-kioslave',None,"Don't build kioslaves"), +                    ('build-dir=','b', "build directory (where to install from)"), +                    ('python-dir=',None,'Directory containing the Python installation'), +                    ('python-inc-dir=',None,'Directory containing C Header files for Python'), +                    ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'), +                    ('kde-lib-dir=',None,'Directory containing library files for KDE'), +                    ('kde-kioslave-lib-dir=',None,'Directory for KDE kioslave library files'), +                    ('kde-protocol-dir=',None,'Directory for KDE kioslave protocol files'), +                    ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'), +                    ('qt-lib-dir=',None,'Directory containing library files for Qt'), +                    ('sip-dir=','/usr/lib/pyshared/python2.6','Directory containing the sip library files'), +                    ('clib=',None,'gcc library and path'), +                    ('pyqt-dir=','/usr/lib/pyshared/python2.6','PyQt module directory'), +                    ('pykde-dir=',None,'PyKDE module directory'), +                    ('data-dir=',None,'installation directory for data (script) files')] +     +    def initialize_options(self): +        self.no_kioslave = 0 +        self.build_dir = None +        self.python_inc_dir = None +        self.python_dir = None +        self.kde_inc_dir = None +        self.kde_lib_dir = None +        self.kde_kioslave_lib_dir = None +        self.kde_protocol_dir = None +        self.qt_inc_dir = None +        self.qt_lib_dir = None +        self.sip_dir = "/usr/lib/pyshared/python2.6" +        self.clib = None +        self.pyqt_dir = "/usr/lib/pyshared/python2.6" +        self.pykde_dir = None +        self.data_dir = None +         +    def finalize_options(self): +        if self.no_kioslave==0: +            self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir')) +         +            install = self.get_finalized_command('install') +            self.install_prefix = "/opt/kde3/" +     +            # KDE inc dir: find it! +            if self.kde_inc_dir is None: +                canidatepaths = [] +                kdedir = os.getenv("KDEDIR") +                if kdedir!=None: +                    canidatepaths.append(os.path.join(kdedir,"include")) +                canidatepaths.append(os.path.join(install.prefix,"include")) +                canidatepaths.append('/opt/kde3/include') +                canidatepaths.append('/opt/kde/include') +                self.kde_inc_dir = FindFileInPaths('kapplication.h',canidatepaths) +            if self.kde_inc_dir is None: +                raise SystemExit, "Failed to find the KDE header file directory." +            if FindFileInPaths('kapplication.h',[self.kde_inc_dir]) is None: +                raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir +            self.announce("Using %s for KDE header files" % self.kde_inc_dir) +     +            # KDE lib dir +            #if self.kde_lib_dir is None: +            #    self.kde_lib_dir = os.path.join(install.prefix,"lib") +            self.kde_lib_dir = "/opt/kde3/lib/" +            self.announce("Using %s for KDE library files" % self.kde_lib_dir) +     +            # KDE kioslave lib dir +            #if self.kde_kioslave_lib_dir is None: +            #    self.kde_kioslave_lib_dir = os.path.join(self.kde_lib_dir,"kde3") +            self.kde_kioslave_lib_dir = "/opt/kde3/lib/kde3/" +            if FindFileInPaths('kio_*.so',[self.kde_kioslave_lib_dir]) is None: +                raise SystemExit, "Failed to find KDE Kioslave library files in: %s" % self.kde_kioslave_lib_dir +            self.announce("Using %s for KDE Kioslave library files" % self.kde_kioslave_lib_dir) +             +            # Qt inc dir +            if self.qt_inc_dir is None: +                canidatepaths = [] +                qtdir = os.getenv("QTDIR") +                if qtdir != None: +                    canidatepaths.append(os.path.join(qtdir,"include")) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include")) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include")) +                canidatepaths.append(os.path.join(install.prefix,"include")) +                canidatepaths.append("/opt/qt3/include") +                canidatepaths.append("/opt/qt/include") +                canidatepaths.append("/opt/qt/lib/include") +                canidatepaths.append("/opt/qt3/lib/include") +                self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths) +            if self.qt_inc_dir is None: +                raise SystemExit,"Failed to find the Qt header file directory" +            if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None: +                raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir +            self.announce("Using %s for Qt header files" % self.qt_inc_dir) +     +            # Qt lib dir +            if self.qt_lib_dir is None: +                canidatepaths = [] +                qtdir = os.getenv("QTDIR") +                if qtdir != None: +                    canidatepaths.append(os.path.join(qtdir,get_libdir_name())) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name())) +                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name())) +                canidatepaths.append(os.path.join(install.prefix,get_libdir_name())) +                canidatepaths.append("/opt/qt3/"+get_libdir_name()) +                canidatepaths.append("/opt/qt/"+get_libdir_name()) +                canidatepaths.append("/opt/qt/lib/"+get_libdir_name()) +                canidatepaths.append("/opt/qt3/lib/"+get_libdir_name()) +                self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths) +            if self.qt_lib_dir is None: +                raise SystemExit, "Failed to find Qt library files" +            self.announce("Using %s for Qt library files" % self.qt_lib_dir) +                     +            # Python dir +            if self.python_dir is None: +                self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[0] +            self.announce("Using %s for the python directory" % self.python_dir) +             +            # Python include dir. +            if self.python_inc_dir is None: +                # Find the Python include directory. +                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY") +            self.announce("Using %s for Python header files" % self.python_inc_dir) +     +            # PyQt dir +            if self.pyqt_dir is None: +                self.pyqt_dir = sysconfig.get_python_lib() +            if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None): +                raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir +            self.announce("Using %s for PyQt modules" % self.pyqt_dir) +     +            # PyKDE dir +            if self.pykde_dir is None: +                self.pykde_dir = sysconfig.get_python_lib() +            if (FindFileInPaths("libkdecorecmodule*",[self.pykde_dir]) is None) and (FindFileInPaths("kdecore*",[self.pykde_dir]) is None): +                raise SystemExit, "Failed to find the PyKDE directory: %s" % self.pykde_dir +            self.announce("Using %s for PyKDE modules" % self.pykde_dir) +             +            # Sip dir +            if self.sip_dir is None: +                self.sip_dir = sysconfig.get_python_lib() +            if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None): +                raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir +            self.announce("Using %s for libsip files" % self.sip_dir) +                 +            # Find the C library (libgcc, libgcc_s or some other variation). +            if self.clib is None: +                canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name() ] +                self.clib = FindFileInPaths("libgcc*.so",canidatepaths) +                if self.clib!=None: +                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0] +                else: +                    self.clib = FindFileInPaths("libgcc*.a",canidatepaths) +                    if self.clib!=None: +                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0] +            if self.clib is None: +                raise SystemExit, "Failed to find a suitable libgcc library" +            self.announce("Using %s for clib" % self.clib) +     +            # Make a list of places to look for python .so modules +            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split() +            base = sysconfig.get_config_var("LIBP") +            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ] +            self.python_sub_dirs.append(base) + +    def get_command_name(self): +        return 'build_kioslave' + +    def run(self): +        if self.no_kioslave: +            self.announce("Skipping KIO Slaves") +            return +     +        if not os.path.isdir(self.build_dir): +            os.mkdir(self.build_dir) +         +        for moduletuple in self.distribution.kioslaves: +            self.announce("Building KIO Slave from protocol file %s." % moduletuple[0]) +             +            protocolfilename = moduletuple[0] +             +            # Read the protocol file +            libraryname = None +            try: +                fhandle = open(protocolfilename,'r') +                for line in fhandle.readlines(): +                    parts = line.strip().split('=') +                    try: +                        if parts[0]=="exec": +                            libraryname = parts[1] +                    except IndexError: +                        pass +                fhandle.close() +            except IOError: +                raise SystemExit, "Failed to find kioslave protocol file: %s" % moduletuple[0] +                 +            # Sanity check. +            if libraryname is None: +                raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)" +             +            modulename = os.path.basename(moduletuple[1]) +            if modulename.endswith('.py'): +                modulename = modulename[:-3] +             +            stub_cpp_name = libraryname+'.cpp' +            stub_so_name = libraryname+'.so' +            stub_la_name = libraryname+'.la' +            python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1]) +             +            # Build the 'stub' code. +            cppcode = self.cpptemplate % {"moduledir": self.data_dir, +                                            "modulename": modulename, +                                            "python_version": python_version} +             +            # Put it on disk. +            cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name) +            try: +                fhandle = open(cppfile,'w') +                fhandle.write(cppcode) +                fhandle.close() +            except IOError: +                raise SystemExit, "Could not write the C++ stub: %s" % cppfile +                 +            # Compile the stub library. +            cmdlist = ['libtool'] + +            # Couldn't get it to pass without this ... +            cmdlist.append("--mode=compile") +            cmdlist.append("--tag=CXX") +             +            # Find the compiler flags and options +            # CXX is empty on some Systems, let's do it 'the hard way'. +            # FIXME :: get CXX from make.conf for Gentoo. +            if len(sysconfig.get_config_var("CXX").split()) >= 2: +                cmdlist.extend(sysconfig.get_config_var("CXX").split()) +            else: +                cmdlist.extend(['g++', '-pthread']) + +            #cmdlist.extend(sysconfig.get_config_var("CXX").split()) +             +            # cc_flags +            cmdlist.append("-c") +            cmdlist.append("-g") +             +            # The 4 is randomly chosen! +            # FIXME :: get CFLAGS from make.conf for Gentoo. +            if len(sysconfig.get_config_var("CFLAGS").split()) >=4: +                cmdlist.extend(sysconfig.get_config_var("CFLAGS").split()) +            else: +                # On Gentoo systems, CFLAGS are not in the environment. +                raw = os.popen('emerge info 2> /dev/null|grep CFLAGS') +                lines = raw.readlines() +                if len(lines): +                    cflags = lines[0].split('"')[1].split() +                    print "Got CFLAGS from emerge info." +                    cmdlist.extend(cflags) +                else: +                    # Still no CFLAGS found, use these ... +                    cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes']) +                 +            #sysconfig.get_config_var("CFLAGS").split() +            # includes +            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR")) +            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR")) +            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY")) +            cmdlist.append("-I" + self.python_inc_dir) +            cmdlist.append("-I" + self.kde_inc_dir) +            cmdlist.append("-I" + self.qt_inc_dir) +            cmdlist.append("-I.") +            # input +            cmdlist.append(cppfile) +            # output +            outputfile = os.path.join(self.build_dir,libraryname+'.lo') +            cmdlist.append("-o") +            cmdlist.append(outputfile) +            spawn(cmdlist) # Execute!!! +            print +             +            # Link the resulting object file to create a shared library. +            cmdlist = ['libtool'] +            cmdlist.append("--mode=link") +             +            # Grab the linker command name +            cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0]) +            # link_flags +            cmdlist.append("-module") +            cmdlist.append("-export-dynamic") +            # object +            cmdlist.append(outputfile) +            cmdlist.append("-rpath"); cmdlist.append(self.kde_kioslave_lib_dir) +            cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name)) +            # Link libs +            linklist = [] +            linklist.append("-lpython%s" % python_version) +            linklist.extend(sysconfig.get_config_var("LIBS").split()) +             +            # FIXME I doubt half of these libraries need to be here. +            linklist.append(self.sip_dir+"/sip.so") +            # PyQt libs +            linklist.append(self.pyqt_dir+"/qt.so") +            # PyKDE libs +            linklist.append(self.pykde_dir+"/kdecore.so") +             +#            linklist.append("-L"+self.sip_dir); linklist.append("-lsip") +#            # PyQt libs +#            linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule") +#            # PyKDE libs +#            linklist.append("-L"+self.pykde_dir); linklist.append("-lkdecorecmodule"); linklist.append("-lkdeuicmodule") +             +            linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/kde3/lib"); linklist.append("-lkdecore"); linklist.append("-lpythonize") +            linklist.append("-L"+self.qt_lib_dir); linklist.append("-lqt-mt") +            linklist.append("-lm") +            linklist.append("-lstdc++") +            linklist.append("-lc") +            linklist.append(self.clib) + +            linklist.append("-R"); linklist.append(self.python_dir) +            linklist.append("-R"); linklist.append(self.qt_lib_dir) +            linklist.append("-R"); linklist.append(self.sip_dir) +            linklist.append("-R"); linklist.append(self.pyqt_dir) +            linklist.append("-R"); linklist.append(self.pykde_dir) +            linklist.append("-R"); linklist.append(self.kde_lib_dir) + +            cmdlist.extend(linklist) +            spawn(cmdlist) # Execute!! +            print +             +    cpptemplate = r""" +/* + * Launch Control Centre modules written in Python using an embedded Python + * interpreter. + * Based on David Boddie's PyKDE-components. + */ + +#include <stdio.h> +#include <Python.h> +#include <kinstance.h> +#define MODULE_DIR "%(moduledir)s" +#define MODULE_NAME "%(modulename)s" +#define FACTORY "SlaveFactory" + +const char modname[] = MODULE_NAME; +#define MAIN_METHOD "dispatchLoop" + +FILE *d = NULL; + +PyObject* call_function(PyObject *callable, PyObject *args) { +    PyObject *result, *pArgs; +     +    if (callable == NULL) { +        printf(MODULE_NAME " kioslave error: callable == NULL in call_function\n"); +        return NULL; +    } +     +    if (PyCallable_Check(callable)) { +        if(args == NULL) { +            pArgs = PyTuple_New(0); +        } else { +            pArgs = args; +        } +        result = PyObject_CallObject(callable, pArgs); +         +        /* If the arguments were created is this function then decrease +           their reference count. */ +        if(args == NULL) { +            Py_XDECREF(pArgs); +            /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */ +        } +         +        if(result == NULL) { +            PyErr_Print(); +            PyErr_Clear(); +        } +    } +    +    return result; +} + +extern "C" { +    int kdemain( int argc, char **argv) { +        PyObject *pModule, *pName, *pDict; +        KInstance slave(MODULE_NAME); +         +        Py_SetProgramName(argv[0]); +        Py_Initialize(); +        //PyEval_InitThreads(); +        PySys_SetArgv(1, argv); +         +        PyRun_SimpleString("import sys\n"); +        PyRun_SimpleString("sys.path.append('"MODULE_DIR"')\n"); +         +        pName = PyString_FromString(modname); +        pModule = PyImport_Import(pName); +         +        Py_XDECREF(pName); +         +        if(pModule == NULL) { +            printf(MODULE_NAME " kioslave error: pModule == NULL\n"); +            return 1; +        } else { +            PyObject *pClass, *pMethod, *pArgs, *pArg1, *pArg2, *pInstance; +            int i; +             +            pDict = PyModule_GetDict(pModule); +            /* pDict is a borrowed reference */ +             +            pClass = PyDict_GetItemString(pDict, FACTORY); +             +            if(pClass == NULL) { +                printf(MODULE_NAME " kioslave error: pClass == NULL\n"); +                return 1; +            } else { +                pArgs = PyTuple_New(2); +                 +                pArg1 = PyString_FromString(argv[2]); +                pArg2 = PyString_FromString(argv[3]); +                 +                PyTuple_SetItem(pArgs, 0, pArg1); +                PyTuple_SetItem(pArgs, 1, pArg2); +                 +                call_function(pClass, pArgs); +                 +                /* Some time later... */ +                Py_XDECREF(pClass); +                Py_XDECREF(pArgs); +            } +             +            Py_XDECREF(pModule); +        } +         +        Py_Finalize(); +        return 0; +    } +} +""" +########################################################################### +class InstallKioslave(Command): +    description = "Install Kioslave files" +     +    user_options = [ +        ('install-dir=', 'd', "base directory for installing kioslave module files"), +        ('install-cmd=', None, "Command to use to install the files"), +        ('install-protocol-dir=',None,"directory for kioslave protocol files"), +        ('build-dir=','b', "build directory (where to install from)"), +        ('root=', None, "install everything relative to this alternate root directory"), +        ('force', 'f', "force installation (overwrite existing files)"), +        ('skip-build', None, "skip the build steps"), +        ] +    boolean_options = ['force', 'skip-build'] +     +    def initialize_options(self): +        self.build_dir = None +        self.install_dir = None +        self.install_cmd = None +        self.install_protocol_dir = None +        self.outfiles = [] +        self.root = None +        self.force = 0 +        self.warn_dir = 1 +        self.skip_build = None + +    def finalize_options(self): +        own_install_dir = self.install_dir is not None +        own_install_protocol_dir = self.install_protocol_dir is not None +         +        self.set_undefined_options('install', +                                    ('build_base', 'build_dir'), +                                    ('install_kioslave', 'install_dir'), +                                    ('root', 'root'), +                                    ('force', 'force'), +                                    ('skip_build', 'skip_build'), +                                    ('install_cmd', 'install_cmd'), +                                    ('install_protocol','install_protocol_dir') +                                    ) + +        if own_install_dir and self.root is not None: +            self.install_dir = change_root(self.root,self.installdir) +         +        if own_install_protocol_dir and self.root is not None: +            self.install_protocol_dir = change_root(self.root,self.install_protocol_dir) +         +    def get_command_name(self): +        return 'install_kioslave' +         +    def run(self): +        if not self.skip_build: +            self.run_command('build_kioslave') +     +        self.announce("Installing Kioslave files...") + +        for moduletuple in self.distribution.kioslaves: +            self.announce("Building Kioslave module from protocol file %s." % moduletuple[0]) +             +            protocolfilename = moduletuple[0] +             +            # Read the protocol file +            libraryname = None +            try: +                fhandle = open(protocolfilename,'r') +                for line in fhandle.readlines(): +                    parts = line.strip().split('=') +                    try: +                        if parts[0]=="exec": +                            libraryname = parts[1] +                    except IndexError: +                        pass +                fhandle.close() +            except IOError: +                raise SystemExit, "Failed to find kioslave protocol file: %s" % moduletuple[0] +                 +            if libraryname is None: +                raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)" +                 +            self.outfiles.extend(self.mkpath(self.install_protocol_dir)) +            protocolfile_dest = os.path.join(self.install_protocol_dir,os.path.basename(protocolfilename)) +            self.copy_file(protocolfilename, protocolfile_dest) +             +            stub_la_name = libraryname+'.la' +     +            self.outfiles.extend(self.mkpath(self.install_dir)) +             +            # Install the library. +            cmdlist = ['libtool'] +            cmdlist.append("--mode=install") +            cmdlist.append(self.install_cmd) +            cmdlist.append("-c") +            cmdlist.append(os.path.join(self.build_dir,stub_la_name)) +            cmdlist.append(os.path.join(self.install_dir,stub_la_name)) +            spawn(cmdlist) # Execute!! +            print + +            self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs',libraryname+'*'))] +            self.outfiles.append(protocolfile_dest) +             +        self.announce("Done installing Kioslave files.") +         +    def get_outputs(self): +        return self.outfiles or [] + +    def mkpath(self, name, mode=0777): +        return dir_util.mkpath(name, mode, dry_run=self.dry_run) +  +########################################################################### +class CheckPyQt(Command): +    description = "Checks for the presence of a working PyQt installation" + +    user_options = [] +         +    def initialize_options(self): +        pass +         +    def finalize_options(self): +        self.min_qt_version = self.distribution.min_qt_version +         +    def run(self): +        if self.min_qt_version!=None: +            qtver,kdever = get_qt_kde_versions() +            if compare_versions(self.min_qt_version,qtver)==1: +                raise SystemExit, "Your Qt version is too old. Version %s or higher is required, found %s." % (self.min_qt_version,qtver) +            self.announce("Found Qt version %s." % qtver) +        try: +            self.announce("Checking for a working PyQt...") +            import qt +            self.announce("  ...PyQt is working") +        except: +            raise SystemExit, "Couldn't import Qt! Please make sure that PyQt is installed and working." + +    def get_outputs(self): return [] + +########################################################################### +class CheckPyKDE(Command): +    description = "Checks for the presence of a working PyKDE installation" + +    user_options = [] +         +    def initialize_options(self): +        pass +         +    def finalize_options(self): +        self.min_kde_version = self.distribution.min_kde_version +         +    def run(self): +        if self.min_kde_version!=None: +            qtver,kdever = get_qt_kde_versions() +            if compare_versions(self.min_kde_version,kdever)==1: +                raise SystemExit, "Your KDE version is too old. Version %s or higher is required, found %s." % (self.min_kde_version,kdever) +            self.announce("Found KDE version %s." % kdever) +        self.announce("Checking for a working PyKDE...") +         +        # Try to import modules one by one.  +        for k_module in ('dcop', 'kdecore', 'kdeui', 'kio', 'kfile', 'kparts', 'khtml', 'kspell'): +            self.announce(k_module) +            try: +                exec('import ' + k_module) +            except: +                raise SystemExit, "Error: Couldn't find module '" + k_module + "'. \n" + \ +                    "Couldn't import KDE! Please make sure that PyKDE is installed and working.\n" + \ +                    "PyKDE is available here: http://www.riverbankcomputing.co.uk/pykde/index.php" +        self.announce("  ...PyKDE is working") +         +    def get_outputs(self): return [] +     +########################################################################### +def FindFileInPaths2(globpattern,canidatepaths): +    if canidatepaths is None or len(canidatepaths)==0: +        return (None,None) +     +    # Look for the globpattern on the path. +    for path in canidatepaths: +        if path!=None: +            files = glob.glob(os.path.join(path, globpattern)) +            if len(files)!=0: +                return (path,os.path.basename(files[0])) +     +    # Continue searching with a breadth first search. +    dirs = [] +    for path in canidatepaths: +        # Examine any directories on this path. +        dirlist = glob.glob(os.path.join(path, "*")) +        for item in dirlist: +            if os.path.isdir(item): +                # Examine each subdirectory. +                dirs.append(item) +    # Examine all subdirectories. +    return FindFileInPaths2(globpattern, dirs) + +########################################################################### +def FindFileInPaths(globpattern,canidatepaths): +    x,y = FindFileInPaths2(globpattern,canidatepaths) +    return x +     +########################################################################### +# FIXME replace this with spawn.find_executable(). +def FindExeOnPath(exe_name,high_prio_dirs=None,low_prio_dirs=None): +    candiate_paths = [] +     +    if high_prio_dirs is not None: +        candiate_paths.extend(high_prio_dirs) +         +    path_var = os.getenv("PATH") +    candiate_paths.extend(path_var.split(':')) +     +    if low_prio_dirs is not None: +        candiate_paths.extend(low_prio_dirs) +     +    for dir in candiate_paths: +        if dir is not None: +            candiate = os.path.join(dir,exe_name) +            if os.path.isfile(candiate): +                if os.access(candiate,os.X_OK): +                    return candiate +    return None +     +########################################################################### + +def ask_kde_config(question): +    # Look for the kde-config program +    kdeconfig = find_executable("kde-config", os.environ['PATH'] + os.pathsep + \ +        os.pathsep.join(['/bin','/usr/bin','/opt/kde3/bin','/opt/kde/bin','/usr/local/bin'])) +    if kdeconfig!=None: +        # Ask the kde-config program for the  +        fhandle = os.popen(kdeconfig+' ' + question,'r') +        result = fhandle.read() +        fhandle.close() +        return result +    else: +        return None + +########################################################################### +# Convert for example, "3.1.1a" => [3,1,1,'a'] +# +def split_version_name(name): +    result = [] +    accu = '' +    type = 0 +    for c in name: +        if type==0: +            if c.isdigit(): +                type = 1 +            else: +                type = 2 +            accu += c +        elif c=='.': +            if type==1: +                result.append(int(accu)) +            else: +                result.append(accu) +            accu = '' +            type = 0 +        elif type==1: +            # Digits +            if c.isdigit(): +                accu += c +            else: +                result.append(int(accu)) +                type = 2 +                accu = c +        else: +            if c.isdigit(): +                result.append(accu) +                type = 1 +                accu = c +            else: +                accu += c +    if accu!='': +        result.append(accu) +    return result + +########################################################################### +# +# Returns: +# -1 if a < b +# 0 if a and b are equal +# 1 if a > b +def compare_versions(a,b): +    aparts = split_version_name(a) +    bparts = split_version_name(b) +    if len(aparts)>len(bparts): +        compmax = len(aparts) +    else: +        compmax = len(bparts) +    i = 0 +    for i in range(compmax): +        abit = 0 +        if i<len(aparts): +            abit = aparts[i] +        bit = 0 +        if i<len(bparts): +            bbit = bparts[i] +        if isinstance(abit,str) and not isinstance(bbit,str): +            return 1 +        elif not isinstance(abit,str) and isinstance(bbit,str): +            return -1 +        else: +            if abit>bbit: +                return 1 +            elif abit<bbit: +                return -1 +    return 0 + +########################################################################### +def get_qt_kde_versions(): +    versioninfo = ask_kde_config('--version') +    qtver = None +    kdever = None +    if versioninfo!=None: +        for line in versioninfo.splitlines(): +            if line.startswith("Qt: "): +                qtver = line[4:] +            elif line.startswith("KDE: "): +                kdever = line[5:] +    return qtver,kdever + +########################################################################### +def compile_qtdesigner(ui_files, +                  force=0, +                  prefix=None, base_dir=None, +                  verbose=1, dry_run=0): +    """Compile a collection of QT Designer UI files to .py +     +    If 'dry_run' is true, doesn't actually do anything that would +    affect the filesystem. +    """ +    generated_files = [] +    for file in ui_files: +        if not file.endswith(".ui"): +            continue + +        # Terminology from the py_compile module: +        #   cfile - byte-compiled file +        #   dfile - purported source filename (same as 'file' by default) +        if base_dir: +            file = os.path.join(base_dir ,file) +             +        pyfile = file[:-3] + '.py' +        uifile = file + +        pyfile_base = os.path.basename(pyfile) +        if force or newer(uifile, pyfile): +            log.info("compiling Qt-Designer UI %s to %s", file, pyfile_base) +            if not dry_run: +                qtuicompiler.CompileUI(uifile, pyfile) +            generated_files.append(pyfile)     +        else: +            log.debug("skipping Qt-Designer compilation of %s to %s", +                      file, pyfile_base) +    return generated_files + +########################################################################### +def get_libdir_name(): +    #if os.uname()[4] in ['x86_64','mips64','ppc64','sparc64','s390x']: +    #    return 'lib64' +    #else: +        return 'lib' diff --git a/src/pythonize.cpp b/src/pythonize.cpp new file mode 100644 index 0000000..e83f965 --- /dev/null +++ b/src/pythonize.cpp @@ -0,0 +1,238 @@ +/* copyright 2003 Jim Bublitz <jbublitz@nwinternet.com> + +   This library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Library General Public +   License as published by the Free Software Foundation; either +   version 2 of the License, or (at your option) any later version. + +   This library 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public License +   along with this library; see the file COPYING.LIB.  If not, write to +   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +   Boston, MA 02110-1301, USA. +*/ + +#include <stdarg.h> +#include <string.h> + +// this just gets rid of a warning when Python.h redefines it +#undef _POSIX_C_SOURCE + +#include <pythonize.h> + +#define debug 1 + +ObjectRef::ObjectRef (ObjectRef *oi, PyObject *o) +{ +    prevObject = oi; +    object     = o; +} + + +Pythonize::Pythonize () +{ +    pythonInit  = 1; +    objects    = NULL; + +    if (debug) printf ("\n\nPythonize constructor -- pid = %i\n", getpid ()); + +    if (!Py_IsInitialized ()) +    { +        PyEval_InitThreads (); +        Py_Initialize (); +        if (!Py_IsInitialized ()) +        { +            pythonInit = 0; +            return; +        } + +        if (debug) printf ("Python interpreter initialized!\n\n"); + +        // free the lock +        PyEval_ReleaseLock(); +    } +} + +bool Pythonize::runScript (char *scriptPath) +{ +    FILE *f; +    int res; + +    if (debug) printf ("Running script: %s\n", scriptPath); + +    if (scriptPath == NULL || strlen (scriptPath) == 0) return false; + +    f = fopen (scriptPath, "r"); +    if (f == NULL) return false; + +    res = PyRun_SimpleFile (f, scriptPath); + +    fclose (f); +    return res == 0; +} + + +PyObject * Pythonize::runFunction (PyObject *object, PyObject *args) +{ + +    if (!PyCallable_Check (object)) +        return NULL; + +    PyObject *res = PyObject_CallObject (object, args ? args : PyTuple_New (0)); +    Py_XINCREF (res); + +    return res; +} + +void * Pythonize::runFunctionVoid (PyObject *object, PyObject *args) +{ + +    if (!PyCallable_Check (object)) +        return NULL; + +    PyObject *pyRes = PyObject_CallObject (object, args ? args : PyTuple_New (0)); +    void *res = PyLong_AsVoidPtr (pyRes); + +    return res; +} + +bool Pythonize::runString (char *str) +{ + +    if (str == NULL || strlen (str) == 0) return false; + +    int res = PyRun_SimpleString (str); + +    return res == 0; +} + +bool Pythonize::appendToSysPath (const char* newPath) +{ +    if (newPath == NULL || strlen (newPath) == 0) return false; + +    char *fmtString = "import sys\nif not '%s' in sys.path:\n\tsys.path.append ('%s')\n"; //print sys.path\n"; +    int length      = strlen (fmtString) + 2*strlen (newPath) + 1; +    char *line      =  new char [length]; +    if (!line) return false; +    snprintf (line, length, fmtString, newPath, newPath); + +    int res = PyRun_SimpleString (line); + +    delete line; +    return res == 0; +} + +PyObject *Pythonize::importModule (char *moduleName) +{ +    if (moduleName == NULL || strlen (moduleName) == 0) return NULL; + +    PyObject *module = PyImport_ImportModule (moduleName); + +    objects = new ObjectRef (objects, module); +    if (!objects) return NULL; + +    return module; +} + + +Pythonize::~Pythonize () +{ + +    if (debug) printf ("Pythonize destructor\n"); +    ObjectRef *top; + +    while (objects) +    { +        top = objects; +        objects = objects->prevObject; +        delete top; +    } +    if (debug) printf (" --- Objects destroyed\n"); + +    Py_Finalize(); + +    if (debug) printf (" --- Py_Finalized\n"); +} + +// The global Pythonize instance +Pythonize *pyize = new Pythonize (); + +extern "C" +{ +Pythonize *_pythonize; + +Pythonize *initialize () +{ +    if (_pythonize) return _pythonize; + +    _pythonize = new Pythonize (); +    if (!_pythonize || !_pythonize->getPythonInit ()) +    { +        if (_pythonize) delete _pythonize; +        return NULL; +    } + +    return _pythonize; +} + +void finalize () +{ +    if (_pythonize) { +        if (debug) printf(" --- Pythonize finalize()\n"); +        delete _pythonize; +    } +} + +            // adds a path to sys.path +bool appendToSysPath (const char* newPath) +{ +    return _pythonize ? _pythonize->appendToSysPath (newPath) : false; +} + +                // imports a module into the interpreter +                // or gets a PyObject for an already loaded module +PyObject *importModule (char *moduleName) +{ +    return _pythonize ? _pythonize->importModule (moduleName) : NULL; +} + +                // returns an object from a loaded module +                // you must decref the object returned when done with it (new reference returned) +PyObject *getNewObjectRef (PyObject *module, char *object) +{ +    return _pythonize ? _pythonize->getNewObjectRef (module, object) : NULL; +} + +bool getPythonInit () +{ +    return _pythonize ? _pythonize->getPythonInit () : false; +} + +                // decrements the ref count of an object +void decref (PyObject *object) +{ +     Py_XDECREF (object); +} + +                // runs a script on the current sys.path +bool runScript (char *scriptPath) +{ +    return _pythonize ? _pythonize->runScript (scriptPath) : false; +} + +                // executes a string of Python in the interpreter +bool runString (char *str) +{ +    return _pythonize ? _pythonize->runString (str) : false; +} + +                // runs a callable Python object +PyObject *runFunction (PyObject *object, PyObject *args) +{ +    return _pythonize ? _pythonize->runFunction (object, args) : NULL; +} +} diff --git a/src/pythonize.h b/src/pythonize.h new file mode 100644 index 0000000..6db64d2 --- /dev/null +++ b/src/pythonize.h @@ -0,0 +1,104 @@ +/* copyright 2003 Jim Bublitz <jbublitz@nwinternet.com> + +   This library 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 library 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public License +   along with this library; see the file COPYING.LIB.  If not, write to +   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +   Boston, MA 02110-1301, USA. +*/ + +#ifndef __pythonize_h__ +#define __pythonize_h__ + +// Pythonize is a general purpose library that wraps the Python +// interpreter with an interface to a set of common operations +// used when embedding the interpreter. + +#include <Python.h> + +struct ObjectRef +{ +    ObjectRef (ObjectRef *oi, PyObject *o); +    ~ObjectRef () { Py_XDECREF (object); } + +    PyObject        *object;        // pointer to an object we created +    ObjectRef       *prevObject;    // pointer to next object on the stack +}; + +class Pythonize +{ +public: +    Pythonize (); +    ~Pythonize (); + +    // adds a path to sys.path +    bool appendToSysPath (const char* newPath); + +    // imports a module into the interpreter +    // or gets a PyObject for an already loaded module +    PyObject *importModule (char *moduleName); + +    // returns an object from a loaded module +    // you must decref the object returned when done with it (new reference returned) +    PyObject *getNewObjectRef (PyObject *module, char *object) { return PyObject_GetAttrString (module, object); } + +    int getPythonInit () { return pythonInit; } + +    // decrements the ref count of an object +    void decref (PyObject *object) { Py_XDECREF (object); } + +    // runs a script on the current sys.path +    bool runScript (char *scriptPath); + +    // executes a string of Python in the interpreter +    bool runString (char *str); + +    // runs a callable Python object +    PyObject *runFunction(PyObject *object, PyObject *args); +    void *runFunctionVoid(PyObject *object, PyObject *args); + +private: +    int pythonInit;         // status of Py_Initialize +    ObjectRef *objects;     // a stack of PyObjects (used in destructor) +}; + +extern "C" { +    Pythonize *initialize(); +    void finalize(); + +    // adds a path to sys.path +    bool appendToSysPath (const char* newPath); + +    // imports a module into the interpreter +    // or gets a PyObject for an already loaded module +    PyObject *importModule (char *moduleName); + +    // returns an object from a loaded module +    // you must decref the object returned when done with it (new reference returned) +    PyObject *getNewObjectRef (PyObject *module, char *object); + +    bool getPythonInit(); + +    // decrements the ref count of an object +    void decref (PyObject *object); + +    // runs a script on the current sys.path +    bool runScript (char *scriptPath); + +    // executes a string of Python in the interpreter +    bool runString (char *str); + +    // runs a callable Python object +    PyObject *runFunction (PyObject *object, PyObject *args); +} + +#endif diff --git a/src/qtdesigner.py b/src/qtdesigner.py new file mode 100644 index 0000000..3a7b55a --- /dev/null +++ b/src/qtdesigner.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +########################################################################### +# qtdesigner - description                                                # +# ------------------------------                                          # +# begin     : Thu Apr 21 2005                                             # +# copyright : (C) 2005 by Simon Edwards                                   # +# email     : simon@simonzone.com                                         # +#                                                                         # +########################################################################### +#                                                                         # +#   This program is free software; you can redistribute it and/or modify  # +#   it under the terms of the GNU Library General Public License as       # +#   published by the Free Software Foundation; either version 2 of the    # +#   License, or (at your option) any later version.                       # +#                                                                         # +########################################################################### + +import __builtin__ +import qtuicompiler + +python_import = __builtin__.__import__ +def load(*args): +    qtuicompiler.DynamicImport(args,False) +    return apply(python_import,args) +     +__builtin__.__import__ = load diff --git a/src/qtuicompiler.py b/src/qtuicompiler.py new file mode 100644 index 0000000..4d590aa --- /dev/null +++ b/src/qtuicompiler.py @@ -0,0 +1,111 @@ +#!/usr/bin/python +########################################################################### +# qtuicompiler - description                                              # +# ------------------------------                                          # +# begin     : Thu Apr 21 2005                                             # +# copyright : (C) 2005 by Simon Edwards                                   # +# email     : simon@simonzone.com                                         # +#                                                                         # +########################################################################### +#                                                                         # +#   This program is free software; you can redistribute it and/or modify  # +#   it under the terms of the GNU Library General Public License as       # +#   published by the Free Software Foundation; either version 2 of the    # +#   License, or (at your option) any later version.                       # +#                                                                         # +########################################################################### + +import os +import sys +import pyqtconfig +from distutils.spawn import * +import traceback + +pyqt_configuration = pyqtconfig.Configuration() +pyuic_exe = None + +############################################################################ +def FindPyuic(): +    global pyuic_exe +    if pyuic_exe is not None: return pyuic_exe +     +    pyuic_exe = find_executable('pyuic',pyqt_configuration.pyqt_bin_dir) +    if pyuic_exe is None: +        # Search on the $Path. +        pyuic_exe = find_executable('pyuic') + +############################################################################ +def CompileUI(ui_file_name, py_file_name=None, kde=False): +    pyuic_exe = find_executable('pyuic',pyqt_configuration.default_bin_dir) +    if pyuic_exe is None: +        # Search on the $Path. +        pyuic_exe = find_executable('pyuic') +    if pyuic_exe is None: +        pass  # FIXME raise something! +         +    if py_file_name is None: +        py_file_name = os.path.splitext(os.path.basename(ui_file_name))[0] + '.py' +     +    tmp_file_name = py_file_name + '.bak' +    cmd = [pyuic_exe] +    if kde: +        cmd.append('-tr') +        cmd.append('i18n') +    cmd.append('-o') +    cmd.append(tmp_file_name) +    cmd.append(ui_file_name) +    spawn(cmd) +     +    input = open(tmp_file_name, 'r') +    output = open(py_file_name, 'w') +    for line in input.readlines(): +        if kde and string.strip(line) == 'from qt import *': +            output.write(line) +            output.write('from kdecore import *\nfrom kdeui import *\n\n') +        elif kde and string.find(line, " = KDatePicker(") != -1: +            o = string.find(line, ",") +            output.write(line[:o] + ",QDate.currentDate()" + line[o:]) +        else: +            output.write (line) + +    input.close() +    output.close() + +    os.remove(tmp_file_name) + +############################################################################ +def DynamicImport(importargs,kde=False): +    file_name = importargs[0].replace('.',os.sep) +    file_name_ui = file_name + '.ui' +    if os.path.exists(file_name_ui): +        try: +            UpdateUI(file_name_ui,kde) +        except: +            traceback.print_exc() +            raise ImportError, "Unable to compile Qt designer file %s." % args[0] + +############################################################################ +def UpdateUI(ui_file,kde=False): +    py_file = ui_file[:-3] + '.py' +    remake = False +    if os.path.exists(py_file): +        remake = os.stat(py_file).st_mtime <= os.stat(ui_file).st_mtime +    else: +        remake = True + +    if remake: +        CompileUI(ui_file, py_file, kde) + +############################################################################ +def main(): +    # FIXME parse args and add --kde parameter. +    if len(sys.argv)!=3: +        print """\nUsage: +qtuicompiler filename.ui filename.py\n\n +""" +        return + +    CompileUI(sys.argv[1],sys.argv[2]) +     +if __name__=='__main__': +    main() | 
