]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/pywxrc.py
a30b8fd79d0cef06d4ca2bc7fd3f2fb23f8441bd
1 #----------------------------------------------------------------------
2 # Name: wx.tools.pywxrc
3 # Purpose: XML resource compiler
6 # Based on wxrc.cpp by Vaclav Slavik, Eduardo Marques
7 # Ported to Python in order to not require yet another
8 # binary in wxPython distributions
10 # Massive rework by Eli Golovinsky
13 # Copyright: (c) 2004 by Total Control Software, 2000 Vaclav Slavik
14 # Licence: wxWindows license
15 #----------------------------------------------------------------------
18 pywxrc -- Python XML resource compiler
19 (see http://wiki.wxpython.org/index.cgi/pywxrc for more info)
21 Usage: python pywxrc.py -h
22 python pywxrc.py [-p] [-g] [-e] [-o filename] xrc input files...
24 -h, --help show help message
25 -p, --python generate python module
26 -g, --gettext output list of translatable strings (may be combined with -p)
27 -e, --embed embed XRC resources in the output file
28 -o, --output output filename, or - for stdout
31 import sys
, os
, getopt
, glob
, re
32 import xml
.dom
.minidom
as minidom
36 #----------------------------------------------------------------------
38 class PythonTemplates
:
40 # This file was automatically generated by pywxrc, do not edit by hand.
48 \"\"\" This function provides access to the XML resources in this module.\"\"\"
57 class xrc%(windowName)s(wx.%(windowClass)s):
59 \"\"\" This function is called during the class's initialization.
61 Override it for custom setup before the window is created usually to
62 set additional window styles using SetWindowStyle() and SetExtraStyle().\"\"\"
65 def __init__(self, parent):
66 # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
67 pre = wx.Pre%(windowClass)s()
68 get_resources().LoadOn%(windowClass)s(pre, parent, "%(windowName)s")
72 # Define variables for the controls
75 CREATE_WIDGET_VAR
= """\
76 self.%(widgetName)s = xrc.XRCCTRL(self, \"%(widgetName)s\")
79 INIT_RESOURE_HEADER
= """\
80 # ------------------------ Resource data ----------------------
82 def __init_resources():
84 __res = xrc.EmptyXmlResource()
88 __res.Load('%(resourceFilename)s')"""
97 wx.FileSystem.AddHandler(wx.MemoryFSHandler())
100 ADD_FILE_TO_MEMFS
= """\
101 wx.MemoryFSHandler.AddFile('XRC/%(memoryPath)s/%(filename)s', %(filename)s)
104 LOAD_RES_MEMFS
= """\
105 __res.Load('memory:XRC/%(memoryPath)s/%(resourceFilename)s')
108 GETTEXT_DUMMY_FUNC
= """
109 # ----------------------- Gettext strings ---------------------
111 def __gettext_strings():
112 # This is a dummy function that lists all the strings that are used in
113 # the XRC file in the _("a string") format to be recognized by GNU
114 # gettext utilities (specificaly the xgettext utility) and the
115 # mki18n.py script. For more information see:
116 # http://wiki.wxpython.org/index.cgi/Internationalization
123 #----------------------------------------------------------------------
125 class XmlResourceCompiler
:
127 templates
= PythonTemplates()
129 """This class generates Python code from XML resource files (XRC)."""
131 def MakePythonModule(self
, inputFiles
, outputFilename
,
132 embedResources
=False, generateGetText
=False):
134 outputFile
= self
._OpenOutputFile
(outputFilename
)
140 # process all the inputFiles, collecting the output data
141 for inFile
in inputFiles
:
142 resourceDocument
= minidom
.parse(inFile
)
143 classes
.append(self
.GenerateClasses(resourceDocument
))
146 res
= self
.GenerateInitResourcesEmbedded(inFile
, resourceDocument
)
148 res
= self
.GenerateInitResourcesFile(inFile
, resourceDocument
)
149 resources
.append(res
)
152 gettextStrings
+= self
.FindStringsInNode(resourceDocument
.firstChild
)
154 # now write it all out
155 print >>outputFile
, self
.templates
.FILE_HEADER
156 print >>outputFile
, "\n".join(classes
)
158 print >>outputFile
, self
.templates
.INIT_RESOURE_HEADER
160 print >>outputFile
, self
.templates
.PREPARE_MEMFS
161 print >>outputFile
, "\n".join(resources
)
164 gettextStrings
= [' _("%s")' % s
for s
in gettextStrings
]
165 gettextStrings
= "\n".join(gettextStrings
)
166 print >>outputFile
, self
.templates
.GETTEXT_DUMMY_FUNC
% gettextStrings
168 #-------------------------------------------------------------------
170 def MakeGetTextOutput(self
, inputFiles
, outputFilename
):
172 Just output the gettext strings by themselves, with no other
175 outputFile
= self
._OpenOutputFile
(outputFilename
)
176 for inFile
in inputFiles
:
177 resourceDocument
= minidom
.parse(inFile
)
178 resource
= resourceDocument
.firstChild
179 strings
= self
.FindStringsInNode(resource
)
180 strings
= ['_("%s");' % s
for s
in strings
]
181 print >>outputFile
, "\n".join(strings
)
183 #-------------------------------------------------------------------
185 def GenerateClasses(self
, resourceDocument
):
188 resource
= resourceDocument
.firstChild
189 topWindows
= [e
for e
in resource
.childNodes
190 if e
.nodeType
== e
.ELEMENT_NODE
and e
.tagName
== "object"]
192 # Generate a class for each top-window object (Frame, Panel, Dialog, etc.)
193 for topWindow
in topWindows
:
194 windowClass
= topWindow
.getAttribute("class")
195 windowClass
= re
.sub("^wx", "", windowClass
)
196 windowName
= topWindow
.getAttribute("name")
197 outputList
.append(self
.templates
.CLASS_HEADER
% locals())
199 # Generate a variable for each control, and standard event handlers
200 # for standard controls.
201 for widget
in topWindow
.getElementsByTagName("object"):
202 widgetClass
= widget
.getAttribute("class")
203 widgetClass
= re
.sub("^wx", "", widgetClass
)
204 widgetName
= widget
.getAttribute("name")
205 if (widgetName
!= "" and widgetClass
!= "" and
207 ['tool', 'unknown', 'notebookpage',
208 'separator', 'sizeritem', 'MenuItem']):
209 outputList
.append(self
.templates
.CREATE_WIDGET_VAR
% locals())
210 outputList
.append('\n\n')
212 return "".join(outputList
)
214 #-------------------------------------------------------------------
216 def GenerateInitResourcesEmbedded(self
, resourceFilename
, resourceDocument
):
220 resourcePath
= os
.path
.split(resourceFilename
)[0]
221 memoryPath
= self
.GetMemoryFilename(os
.path
.splitext(os
.path
.split(resourceFilename
)[1])[0])
222 resourceFilename
= self
.GetMemoryFilename(os
.path
.split(resourceFilename
)[1])
224 self
.ReplaceFilenamesInXRC(resourceDocument
.firstChild
, files
, resourcePath
)
226 filename
= resourceFilename
227 fileData
= resourceDocument
.toxml()
228 outputList
.append(self
.templates
.FILE_AS_STRING
% locals())
231 filename
= self
.GetMemoryFilename(f
)
232 fileData
= self
.FileToString(os
.path
.join(resourcePath
, f
))
233 outputList
.append(self
.templates
.FILE_AS_STRING
% locals())
235 for f
in [resourceFilename
] + files
:
236 filename
= self
.GetMemoryFilename(f
)
237 outputList
.append(self
.templates
.ADD_FILE_TO_MEMFS
% locals())
239 outputList
.append(self
.templates
.LOAD_RES_MEMFS
% locals())
241 return "".join(outputList
)
243 #-------------------------------------------------------------------
245 def GenerateInitResourcesFile(self
, resourceFilename
, resourceDocument
):
246 # take only the filename portion out of resourceFilename
247 resourceFilename
= os
.path
.split(resourceFilename
)[1]
249 outputList
.append(self
.templates
.LOAD_RES_FILE
% locals())
250 return "".join(outputList
)
252 #-------------------------------------------------------------------
254 def GetMemoryFilename(self
, filename
):
255 # Remove special chars from the filename
256 return re
.sub(r
"[^A-Za-z0-9_]", "_", filename
)
258 #-------------------------------------------------------------------
260 def FileToString(self
, filename
):
263 buffer = open(filename
, "rb").read()
264 fileLen
= len(buffer)
267 for i
in xrange(fileLen
):
273 elif c
< 32 or c
> 127 or s
== "'":
282 outputList
.append("\\\n")
284 outputList
.append(tmp
)
287 return "".join(outputList
)
289 #-------------------------------------------------------------------
291 def NodeContainsFilename(self
, node
):
292 """ Does 'node' contain filename information at all? """
295 if node
.nodeName
== "bitmap":
298 if node
.nodeName
== "icon":
301 # URLs in wxHtmlWindow:
302 if node
.nodeName
== "url":
306 parent
= node
.parentNode
307 if parent
.__class
__ != minidom
.Document
and \
308 parent
.getAttribute("class") == "wxBitmapButton" and \
309 (node
.nodeName
== "focus" or node
.nodeName
== "disabled" or
310 node
.nodeName
== "selected"):
313 # wxBitmap or wxIcon toplevel resources:
314 if node
.nodeName
== "object":
315 klass
= node
.getAttribute("class")
316 if klass
== "wxBitmap" or klass
== "wxIcon":
321 #-------------------------------------------------------------------
323 def ReplaceFilenamesInXRC(self
, node
, files
, resourcePath
):
324 """ Finds all files mentioned in resource file, e.g. <bitmap>filename</bitmap>
325 and replaces them with the memory filenames.
327 Fills a list of the filenames found."""
329 # Is 'node' XML node element?
330 if node
is None: return
331 if node
.nodeType
!= minidom
.Document
.ELEMENT_NODE
: return
333 containsFilename
= self
.NodeContainsFilename(node
);
335 for n
in node
.childNodes
:
337 if (containsFilename
and
338 (n
.nodeType
== minidom
.Document
.TEXT_NODE
or
339 n
.nodeType
== minidom
.Document
.CDATA_SECTION_NODE
)):
341 filename
= n
.nodeValue
342 memoryFilename
= self
.GetMemoryFilename(filename
)
343 n
.nodeValue
= memoryFilename
345 if filename
not in files
:
346 files
.append(filename
)
348 # Recurse into children
349 if n
.nodeType
== minidom
.Document
.ELEMENT_NODE
:
350 self
.ReplaceFilenamesInXRC(n
, files
, resourcePath
);
352 #-------------------------------------------------------------------
354 def FindStringsInNode(self
, parent
):
366 for child
in parent
.childNodes
:
367 if ((parent
.nodeType
== parent
.ELEMENT_NODE
) and
368 # parent is an element, i.e. has subnodes...
369 (child
.nodeType
== child
.TEXT_NODE
or
370 child
.nodeType
== child
.CDATA_SECTION_NODE
) and
371 # ...it is textnode...
373 parent
.tagName
== "label" or
374 (parent
.tagName
== "value" and
375 not is_number(child
.nodeValue
)) or
376 parent
.tagName
== "help" or
377 parent
.tagName
== "longhelp" or
378 parent
.tagName
== "tooltip" or
379 parent
.tagName
== "htmlcode" or
380 parent
.tagName
== "title" or
381 parent
.tagName
== "item"
383 # ...and known to contain translatable string
384 if (parent
.getAttribute("translate") != "0"):
385 strings
.append(self
.ConvertText(child
.nodeValue
))
388 if child
.nodeType
== child
.ELEMENT_NODE
:
389 strings
+= self
.FindStringsInNode(child
)
393 #-------------------------------------------------------------------
395 def ConvertText(self
, st
):
400 for i
in range(len(dt
)):
418 if dt
[i
+1] not in ['n', 't', 'r']:
430 #-------------------------------------------------------------------
432 def _OpenOutputFile(self
, outputFilename
):
433 if outputFilename
== "-":
434 outputFile
= sys
.stdout
437 outputFile
= open(outputFilename
, "wt")
439 raise IOError("Can't write output to '%s'" % outputFilename
)
446 #---------------------------------------------------------------------------
449 resourceFilename
= ""
450 outputFilename
= None
451 embedResources
= False
452 generateGetText
= False
453 generatePython
= False
456 opts
, args
= getopt
.gnu_getopt(args
,
458 "help python gettext embed output=".split())
459 except getopt
.GetoptError
, e
:
460 print "\nError : %s\n" % str(e
)
464 # If there is no input file argument, show help and exit
467 print "No xrc input file was specified."
470 # Parse options and arguments
471 for opt
, val
in opts
:
472 if opt
in ["-h", "--help"]:
476 if opt
in ["-p", "--python"]:
477 generatePython
= True
479 if opt
in ["-o", "--output"]:
482 if opt
in ["-e", "--embed"]:
483 embedResources
= True
485 if opt
in ["-g", "--gettext"]:
486 generateGetText
= True
489 # check for and expand any wildcards in the list of input files
492 inputFiles
+= glob
.glob(arg
)
495 comp
= XmlResourceCompiler()
499 if not outputFilename
:
500 outputFilename
= os
.path
.splitext(args
[0])[0] + "_xrc.py"
501 comp
.MakePythonModule(inputFiles
, outputFilename
,
502 embedResources
, generateGetText
)
504 elif generateGetText
:
505 if not outputFilename
:
507 comp
.MakeGetTextOutput(inputFiles
, outputFilename
)
511 print "One or both of -p, -g must be specified."
516 print >>sys
.stderr
, "%s." % str(e
)
518 if outputFilename
!= "-":
519 print >>sys
.stderr
, "Resources written to %s." % outputFilename
521 if __name__
== "__main__":