| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 | 
import errnoimport osimport refrom string import TemplatePYTHONQT_WRAPPER_WITH_PARENT = Template("""//-----------------------------------------------------------------------------class PythonQtWrapper_${className} : public QObject{Q_OBJECTpublic:public Q_SLOTS:  ${className}* new_${className}(${parentClassName}*  parent = 0)    {    return new ${className}(parent);    }  void delete_${className}(${className}* obj) { delete obj; }};""")PYTHONQT_WRAPPER_WITHOUT_PARENT = Template("""//-----------------------------------------------------------------------------class PythonQtWrapper_${className} : public QObject{Q_OBJECTpublic:public Q_SLOTS:  ${className}* new_${className}()    {    return new ${className}();    }  void delete_${className}(${className}* obj) { delete obj; }};""")def _mkdir_p(path):    """See """    try:        os.makedirs(path)    except OSError as exc:        if exc.errno == errno.EEXIST and os.path.isdir(path):            pass        else: raisedef ctk_wrap_pythonqt(target, namespace, output_dir, input_files, extra_verbose):    if extra_verbose:        print("target: %s" % target)        print("namespace: %s" % namespace)        print("output_dir: %s" % output_dir)        print("input_files: %s" % input_files)        _mkdir_p(output_dir)        includes = []    pythonqtWrappers = []    registerclasses = []    namespace = namespace.replace('.', '_')        for input_file in input_files:        filename = os.path.basename(input_file)        if extra_verbose:            print("Wrapping %s" % filename)               # what is the filename without the extension        filename_we = os.path.splitext(filename)[0]        # Extract classname - NOTE: We assume the filename matches the associated class        className = filename_we        if extra_verbose:            print("\tclassName:%s" % className)        # Extract parent classname        parentClassName = None        # Read input files        with open(input_file) as f:            content = f.read()                        # Skip wrapping if file do NOT contain Q_OBJECT            if 'Q_OBJECT' not in content:                if extra_verbose:                    print("\tskipping - No Q_OBJECT macro")                continue            # Skip wrapping if constructor doesn't match:            #    my_class()            #    my_class(QObject* newParent ...)            #    my_class(QWidget* newParent ...)            # Constructor with either QWidget or QObject as first parameter            regex = r"[^~]%s[\s\n]*\([\s\n]*((QObject|QWidget)[\s\n]*\*[\s\n]*\w+[\s\n]*(\=[\s\n]*(0|NULL)|,.*\=.*\)|\)|\)))" % className            res = re.search(regex, content, re.MULTILINE)            if res is None:                if extra_verbose:                    print("\tskipping - Missing expected constructor signature")                continue                 # Skip wrapping if object has a virtual pure method            # "x3b" is the unicode for semicolon            regex = r"virtual[\w\n\s\*\(\)]+\=[\s\n]*(0|NULL)[\s\n]*\x3b"            res = re.search(regex, content, re.MULTILINE)            if res is not None:                if extra_verbose:                    print("skipping - Contains a virtual pure method")                continue            if parentClassName is None:                # Does constructor signature is of the form: myclass()                regex = r"[^~]%s[\s\n]*\([\s\n]*\)" % className                res = re.search(regex, content, re.MULTILINE)                           if res is not None:                    parentClassName = ""                    if extra_verbose:                        print("\tconstructor of the form: %s()" % className)            if parentClassName is None:                # Does constructor signature is of the form: myclass(QObject * parent ...)                regex = r"%s[\s\n]*\([\s\n]*QObject[\s\n]*\*[\s\n]*\w+[\s\n]*(\=[\s\n]*(0|NULL)|,.*\=.*\)|\))" % className                res = re.search(regex, content, re.MULTILINE)                if res is not None:                    parentClassName = "QObject"                    if extra_verbose:                        print("\tconstructor of the form: %s(QObject * parent ... )" % className)            if parentClassName is None:                # Does constructor signature is of the form: myclass(QWidget * parent ...)                regex = r"%s[\s\n]*\([\s\n]*QWidget[\s\n]*\*[\s\n]*\w+[\s\n]*(\=[\s\n]*(0|NULL)|,.*\=.*\)|\))" % className                res = re.search(regex, content, re.MULTILINE)                if res is not None:                    parentClassName = "QWidget"                    if extra_verbose:                        print("\tconstructor of the form: %s(QWidget * parent ... )" % className)        if parentClassName is not None:            includes.append('#include "%s.h"' % filename_we)        # Generate PythonQtWrapper class        if parentClassName == "QObject" or parentClassName == "QWidget":            pythonqtWrappers.append(                PYTHONQT_WRAPPER_WITH_PARENT.substitute(className = className, parentClassName = parentClassName))                    elif parentClassName == "":            pythonqtWrappers.append(PYTHONQT_WRAPPER_WITHOUT_PARENT.substitute(className = className))        else: # Case parentClassName is None            raise Exception("Problem wrapping %s" % input_file)                # Generate code allowing to register the class metaobject and its associated "light" wrapper        registerclasses.append(        Template("""  PythonQt::self()->registerClass(  &${className}::staticMetaObject, "${target}",  PythonQtCreateObject<PythonQtWrapper_${className}>);  """).substitute(className = className, target = target))    output_header = output_dir + "/" + namespace + "_" + target + ".h"    if extra_verbose:        print("output_header: %s" % output_header)    # Write master include file    with open(output_header, "w") as f:        f.write(Template("""//// File auto-generated by ctkWrapPythonQt.py//#ifndef __${namespace}_${target}_h#define __${namespace}_${target}_h#include <QObject>${includes}${pythonqtWrappers}#endif""").substitute(namespace = namespace, target = target, includes = '\n'.join(includes), pythonqtWrappers = '\n'.join(pythonqtWrappers)))    output_cpp = output_dir + "/" + namespace + "_" + target + "_init.cpp"    if extra_verbose:        print("output_cpp: %s" % output_cpp)    with open(output_cpp , "w") as f:        # Write wrapper header        f.write(Template("""//// File auto-generated by ctkWrapPythonQt.py//#include <PythonQt.h>// XXX Avoid  warning: "HAVE_XXXX" redefined#undef HAVE_STAT#undef HAVE_FTIME#undef HAVE_GETPID#undef HAVE_IO_H#undef HAVE_STRERROR#undef HAVE_SYS_UTIME_H#undef HAVE_TEMPNAM#undef HAVE_TMPNAM#undef HAVE_LONG_LONG#undef HAVE_INT64_T#include "${namespace}_${target}.h"void PythonQt_init_${namespace}_${target}(PyObject* module){  Q_UNUSED(module);  ${registerclasses}}""").substitute(namespace = namespace, target = target, registerclasses = '\n'.join(registerclasses)))if __name__ == '__main__':    from optparse import OptionParser    usage = "usage: %prog [options] <output_file> <input_file> [<input_file1> [...]]"    parser = OptionParser(usage=usage)    parser.add_option("-t", "--target",                      dest="target", action="store", type="string",                      help="Name of the associated library")    parser.add_option("-n", "--namespace",                      dest="namespace", action="store", type="string",                      help="Wrapping namespace")    parser.add_option("--output-dir",                      dest="output_dir", action="store", type="string",                      help="Output directory")    parser.add_option("-v", "--verbose",                      dest="verbose", action="store_true",                      help="Print verbose information")    parser.add_option("--extra-verbose",                      dest="extra_verbose", action="store_true",                      help="Print extra verbose information")    (options, args) = parser.parse_args()    #if len(args) < 2:    #    parser.error("arguments '%s' are required !" % '<output_file> <input_file>')    if options.extra_verbose:        options.verbose = True    ctk_wrap_pythonqt(options.target, options.namespace, options.output_dir, args, options.extra_verbose)          if options.verbose:        print("Wrapped %d files" % len(args))
 |