X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/73b2a9a749a960c7c5150d70e847cd740983c034..b2458f311b426717c4d36b51aed2595a59f373d9:/wxPython/wx/tools/pywxrc.py diff --git a/wxPython/wx/tools/pywxrc.py b/wxPython/wx/tools/pywxrc.py index dbec81f2ce..a30b8fd79d 100644 --- a/wxPython/wx/tools/pywxrc.py +++ b/wxPython/wx/tools/pywxrc.py @@ -16,13 +16,16 @@ """ pywxrc -- Python XML resource compiler + (see http://wiki.wxpython.org/index.cgi/pywxrc for more info) Usage: python pywxrc.py -h - python pywxrc.py [-e] [-o filename] + python pywxrc.py [-p] [-g] [-e] [-o filename] xrc input files... - -h, --help show help message - -e, --embed embed resources in output file - -o, --output output filename, or - for stdout + -h, --help show help message + -p, --python generate python module + -g, --gettext output list of translatable strings (may be combined with -p) + -e, --embed embed XRC resources in the output file + -o, --output output filename, or - for stdout """ import sys, os, getopt, glob, re @@ -51,7 +54,7 @@ def get_resources(): """ CLASS_HEADER = """\ -class %(windowName)sBase(wx.%(windowClass)s): +class xrc%(windowName)s(wx.%(windowClass)s): def PreCreate(self): \"\"\" This function is called during the class's initialization. @@ -74,28 +77,23 @@ class %(windowName)sBase(wx.%(windowClass)s): """ INIT_RESOURE_HEADER = """\ -# ------------------------------------------------------------- # ------------------------ Resource data ---------------------- -# ------------------------------------------------------------- def __init_resources(): + global __res + __res = xrc.EmptyXmlResource() """ LOAD_RES_FILE = """\ - global __res - __res = xrc.XmlResource('%(resourceFilename)s') -""" + __res.Load('%(resourceFilename)s')""" FILE_AS_STRING = """\ %(filename)s = '''\\ %(fileData)s''' - """ PREPARE_MEMFS = """\ - # Load all the strings as memory files - wx.FileSystem.AddHandler(wx.MemoryFSHandler()) """ @@ -104,11 +102,24 @@ def __init_resources(): """ LOAD_RES_MEMFS = """\ - global __res - __res = xrc.EmptyXmlResource() __res.Load('memory:XRC/%(memoryPath)s/%(resourceFilename)s') """ + GETTEXT_DUMMY_FUNC = """ +# ----------------------- Gettext strings --------------------- + +def __gettext_strings(): + # This is a dummy function that lists all the strings that are used in + # the XRC file in the _("a string") format to be recognized by GNU + # gettext utilities (specificaly the xgettext utility) and the + # mki18n.py script. For more information see: + # http://wiki.wxpython.org/index.cgi/Internationalization + + def _(str): pass + +%s +""" + #---------------------------------------------------------------------- class XmlResourceCompiler: @@ -117,23 +128,57 @@ class XmlResourceCompiler: """This class generates Python code from XML resource files (XRC).""" - def MakePythonModule(self, resourceFilename, outputFilename, embedResources=False): - if outputFilename == "-": - outputFile = sys.stdout - else: - try: - outputFile = open(outputFilename, "wt") - except IOError: - raise IOError("Can't write output to '%s'" % outputFilename) + def MakePythonModule(self, inputFiles, outputFilename, + embedResources=False, generateGetText=False): + + outputFile = self._OpenOutputFile(outputFilename) + + classes = [] + resources = [] + gettextStrings = [] - resourceDocument = minidom.parse(resourceFilename) + # process all the inputFiles, collecting the output data + for inFile in inputFiles: + resourceDocument = minidom.parse(inFile) + classes.append(self.GenerateClasses(resourceDocument)) + + if embedResources: + res = self.GenerateInitResourcesEmbedded(inFile, resourceDocument) + else: + res = self.GenerateInitResourcesFile(inFile, resourceDocument) + resources.append(res) + + if generateGetText: + gettextStrings += self.FindStringsInNode(resourceDocument.firstChild) + + # now write it all out print >>outputFile, self.templates.FILE_HEADER - print >>outputFile, self.GenerateClasses(resourceDocument) - + print >>outputFile, "\n".join(classes) + + print >>outputFile, self.templates.INIT_RESOURE_HEADER if embedResources: - print >>outputFile, self.GenerateInitResourcesEmbedded(resourceFilename, resourceDocument) - else: - print >>outputFile, self.GenerateInitResourcesFile(resourceFilename, resourceDocument) + print >>outputFile, self.templates.PREPARE_MEMFS + print >>outputFile, "\n".join(resources) + + if generateGetText: + gettextStrings = [' _("%s")' % s for s in gettextStrings] + gettextStrings = "\n".join(gettextStrings) + print >>outputFile, self.templates.GETTEXT_DUMMY_FUNC % gettextStrings + + #------------------------------------------------------------------- + + def MakeGetTextOutput(self, inputFiles, outputFilename): + """ + Just output the gettext strings by themselves, with no other + code generation. + """ + outputFile = self._OpenOutputFile(outputFilename) + for inFile in inputFiles: + resourceDocument = minidom.parse(inFile) + resource = resourceDocument.firstChild + strings = self.FindStringsInNode(resource) + strings = ['_("%s");' % s for s in strings] + print >>outputFile, "\n".join(strings) #------------------------------------------------------------------- @@ -170,9 +215,6 @@ class XmlResourceCompiler: def GenerateInitResourcesEmbedded(self, resourceFilename, resourceDocument): outputList = [] - - outputList.append(self.templates.INIT_RESOURE_HEADER) - files = [] resourcePath = os.path.split(resourceFilename)[0] @@ -190,8 +232,6 @@ class XmlResourceCompiler: fileData = self.FileToString(os.path.join(resourcePath, f)) outputList.append(self.templates.FILE_AS_STRING % locals()) - outputList.append(self.templates.PREPARE_MEMFS % locals()) - for f in [resourceFilename] + files: filename = self.GetMemoryFilename(f) outputList.append(self.templates.ADD_FILE_TO_MEMFS % locals()) @@ -203,8 +243,9 @@ class XmlResourceCompiler: #------------------------------------------------------------------- def GenerateInitResourcesFile(self, resourceFilename, resourceDocument): + # take only the filename portion out of resourceFilename + resourceFilename = os.path.split(resourceFilename)[1] outputList = [] - outputList.append(self.templates.INIT_RESOURE_HEADER) outputList.append(self.templates.LOAD_RES_FILE % locals()) return "".join(outputList) @@ -308,24 +349,122 @@ class XmlResourceCompiler: if n.nodeType == minidom.Document.ELEMENT_NODE: self.ReplaceFilenamesInXRC(n, files, resourcePath); + #------------------------------------------------------------------- + + def FindStringsInNode(self, parent): + def is_number(st): + try: + i = int(st) + return True + except ValueError: + return False + + strings = [] + if parent is None: + return strings; + + for child in parent.childNodes: + if ((parent.nodeType == parent.ELEMENT_NODE) and + # parent is an element, i.e. has subnodes... + (child.nodeType == child.TEXT_NODE or + child.nodeType == child.CDATA_SECTION_NODE) and + # ...it is textnode... + ( + parent.tagName == "label" or + (parent.tagName == "value" and + not is_number(child.nodeValue)) or + parent.tagName == "help" or + parent.tagName == "longhelp" or + parent.tagName == "tooltip" or + parent.tagName == "htmlcode" or + parent.tagName == "title" or + parent.tagName == "item" + )): + # ...and known to contain translatable string + if (parent.getAttribute("translate") != "0"): + strings.append(self.ConvertText(child.nodeValue)) + + # subnodes: + if child.nodeType == child.ELEMENT_NODE: + strings += self.FindStringsInNode(child) + + return strings + + #------------------------------------------------------------------- + + def ConvertText(self, st): + st2 = "" + dt = list(st) + + skipNext = False + for i in range(len(dt)): + if skipNext: + skipNext = False + continue + + if dt[i] == '_': + if dt[i+1] == '_': + st2 += '_' + skipNext = True + else: + st2 += '&' + elif dt[i] == '\n': + st2 += '\\n' + elif dt[i] == '\t': + st2 += '\\t' + elif dt[i] == '\r': + st2 += '\\r' + elif dt[i] == '\\': + if dt[i+1] not in ['n', 't', 'r']: + st2 += '\\\\' + else: + st2 += '\\' + elif dt[i] == '"': + st2 += '\\"' + else: + st2 += dt[i] + + return st2 + + + #------------------------------------------------------------------- + + def _OpenOutputFile(self, outputFilename): + if outputFilename == "-": + outputFile = sys.stdout + else: + try: + outputFile = open(outputFilename, "wt") + except IOError: + raise IOError("Can't write output to '%s'" % outputFilename) + return outputFile + + + + + #--------------------------------------------------------------------------- def main(args): resourceFilename = "" - outputFilename = "" + outputFilename = None embedResources = False + generateGetText = False + generatePython = False try: - opts, args = getopt.gnu_getopt(args, "heo:", "help embed output=".split()) - except getopt.GetoptError: + opts, args = getopt.gnu_getopt(args, + "hpgeo:", + "help python gettext embed output=".split()) + except getopt.GetoptError, e: + print "\nError : %s\n" % str(e) print __doc__ sys.exit(1) # If there is no input file argument, show help and exit - if args: - resourceFilename = args[0] - else: + if not args: print __doc__ + print "No xrc input file was specified." sys.exit(1) # Parse options and arguments @@ -334,19 +473,45 @@ def main(args): print __doc__ sys.exit(1) + if opt in ["-p", "--python"]: + generatePython = True + if opt in ["-o", "--output"]: outputFilename = val if opt in ["-e", "--embed"]: embedResources = True - if outputFilename is None or outputFilename == "": - outputFilename = os.path.splitext(resourceFilename)[0] + "_xrc.py" + if opt in ["-g", "--gettext"]: + generateGetText = True + + + # check for and expand any wildcards in the list of input files + inputFiles = [] + for arg in args: + inputFiles += glob.glob(arg) + comp = XmlResourceCompiler() try: - comp.MakePythonModule(resourceFilename, outputFilename, embedResources) + if generatePython: + if not outputFilename: + outputFilename = os.path.splitext(args[0])[0] + "_xrc.py" + comp.MakePythonModule(inputFiles, outputFilename, + embedResources, generateGetText) + + elif generateGetText: + if not outputFilename: + outputFilename = '-' + comp.MakeGetTextOutput(inputFiles, outputFilename) + + else: + print __doc__ + print "One or both of -p, -g must be specified." + sys.exit(1) + + except IOError, e: print >>sys.stderr, "%s." % str(e) else: