diff --git a/wxPython/wx/tools/XRCed/globals.py b/wxPython/wx/tools/XRCed/globals.py
index e731674e41..e2a470d994 100644
--- a/wxPython/wx/tools/XRCed/globals.py
+++ b/wxPython/wx/tools/XRCed/globals.py
@@ -21,7 +21,7 @@ MinWxVersion = (2,6,0)
if wxVERSION[:3] < MinWxVersion:
print '''\
******************************* WARNING **************************************
- This version of XRCed may not work correctly on your version of wxWindows.
+ This version of XRCed may not work correctly on your version of wxWidgets.
Please upgrade wxWindows to %d.%d.%d or higher.
******************************************************************************''' % MinWxVersion
diff --git a/wxPython/wx/tools/XRCed/xrced.py b/wxPython/wx/tools/XRCed/xrced.py
index ddf9add60a..78b97e54b3 100644
--- a/wxPython/wx/tools/XRCed/xrced.py
+++ b/wxPython/wx/tools/XRCed/xrced.py
@@ -122,6 +122,9 @@ class Frame(wxFrame):
menu.AppendSeparator()
menu.Append(wxID_SAVE, '&Save\tCtrl-S', 'Save XRC file')
menu.Append(wxID_SAVEAS, 'Save &As...', 'Save XRC file under different name')
+ self.ID_GENERATE_PYTHON = wxNewId()
+ menu.Append(self.ID_GENERATE_PYTHON, '&Generate Python...',
+ 'Generate a Python module that uses this XRC')
menu.AppendSeparator()
menu.Append(wxID_EXIT, '&Quit\tCtrl-Q', 'Exit application')
@@ -222,6 +225,7 @@ class Frame(wxFrame):
EVT_MENU(self, wxID_OPEN, self.OnOpen)
EVT_MENU(self, wxID_SAVE, self.OnSaveOrSaveAs)
EVT_MENU(self, wxID_SAVEAS, self.OnSaveOrSaveAs)
+ EVT_MENU(self, self.ID_GENERATE_PYTHON, self.OnGeneratePython)
EVT_MENU(self, wxID_EXIT, self.OnExit)
# Edit
EVT_MENU(self, wxID_UNDO, self.OnUndo)
@@ -373,6 +377,20 @@ class Frame(wxFrame):
else:
dlg.Destroy()
return
+
+ if conf.localconf:
+ # if we already have a localconf then it needs to be
+ # copied to a new config with the new name
+ lc = conf.localconf
+ nc = self.CreateLocalConf(path)
+ flag, key, idx = lc.GetFirstEntry()
+ while flag:
+ nc.Write(key, lc.Read(key))
+ flag, key, idx = lc.GetNextEntry(idx)
+ conf.localconf = nc
+ else:
+ # otherwise create a new one
+ conf.localconf = self.CreateLocalConf(path)
else:
path = self.dataFile
self.SetStatusText('Saving...')
@@ -384,6 +402,11 @@ class Frame(wxFrame):
self.Save(tmpName) # save temporary file first
shutil.move(tmpName, path)
self.dataFile = path
+ if conf.localconf.ReadBool("autogenerate", False):
+ pypath = conf.localconf.Read("filename")
+ embed = conf.localconf.ReadBool("embedResource", False)
+ self.GeneratePython(self.dataFile, pypath, embed)
+
self.SetStatusText('Data saved')
self.SaveRecent(path)
except IOError:
@@ -399,6 +422,28 @@ class Frame(wxFrame):
EVT_MENU(self, newid, self.OnRecentFile)
conf.recentfiles[newid] = path
+ def GeneratePython(self, dataFile, pypath, embed):
+ try:
+ import wx.tools.pywxrc
+ rescomp = wx.tools.pywxrc.XmlResourceCompiler()
+ rescomp.MakePythonModule(dataFile, pypath, embed)
+ except:
+ inf = sys.exc_info()
+ wxLogError(traceback.format_exception(inf[0], inf[1], None)[-1])
+ wxLogError('Error generating python code : %s' % pypath)
+ raise
+
+
+ def OnGeneratePython(self, evt):
+ if self.modified or not conf.localconf:
+ wx.MessageBox("Save the XRC file first!", "Error")
+ return
+
+ dlg = PythonOptions(self, conf.localconf, self.dataFile)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+
def OnExit(self, evt):
self.Close()
@@ -1047,8 +1092,16 @@ Homepage: http://xrced.sourceforge.net\
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
evt.Skip()
+
+ def CreateLocalConf(self, path):
+ name = os.path.splitext(path)[0]
+ name += '.xcfg'
+ return wx.FileConfig(localFilename=name)
+
+
def Clear(self):
self.dataFile = ''
+ conf.localconf = None
undoMan.Clear()
self.SetModified(False)
tree.Clear()
@@ -1094,6 +1147,7 @@ Homepage: http://xrced.sourceforge.net\
if dir: os.chdir(dir)
tree.SetData(dom)
self.SetTitle(progname + ': ' + os.path.basename(path))
+ conf.localconf = self.CreateLocalConf(self.dataFile)
except:
# Nice exception printing
inf = sys.exc_info()
@@ -1146,12 +1200,13 @@ Homepage: http://xrced.sourceforge.net\
self.domCopy = None
self.SetModified(False)
panel.SetModified(False)
+ conf.localconf.Flush()
except:
inf = sys.exc_info()
wxLogError(traceback.format_exception(inf[0], inf[1], None)[-1])
wxLogError('Error writing file: %s' % path)
raise
-
+
def AskSave(self):
if not (self.modified or panel.IsModified()): return True
flags = wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
@@ -1175,6 +1230,72 @@ Homepage: http://xrced.sourceforge.net\
################################################################################
+class PythonOptions(wx.Dialog):
+
+ def __init__(self, parent, cfg, dataFile):
+ pre = wx.PreDialog()
+ g.frame.res.LoadOnDialog(pre, parent, "PYTHON_OPTIONS")
+ self.PostCreate(pre)
+
+ self.cfg = cfg
+ self.dataFile = dataFile
+
+ self.AutoGenerateCB = XRCCTRL(self, "AutoGenerateCB")
+ self.EmbedCB = XRCCTRL(self, "EmbedCB")
+ self.GettextCB = XRCCTRL(self, "GettextCB")
+ self.MakeXRSFileCB = XRCCTRL(self, "MakeXRSFileCB")
+ self.FileNameTC = XRCCTRL(self, "FileNameTC")
+ self.BrowseBtn = XRCCTRL(self, "BrowseBtn")
+ self.GenerateBtn = XRCCTRL(self, "GenerateBtn")
+ self.SaveOptsBtn = XRCCTRL(self, "SaveOptsBtn")
+
+ self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.BrowseBtn)
+ self.Bind(wx.EVT_BUTTON, self.OnGenerate, self.GenerateBtn)
+ self.Bind(wx.EVT_BUTTON, self.OnSaveOpts, self.SaveOptsBtn)
+
+ if self.cfg.Read("filename", "") != "":
+ self.FileNameTC.SetValue(self.cfg.Read("filename"))
+ else:
+ name = os.path.splitext(dataFile)[0]
+ name += '_xrc.py'
+ self.FileNameTC.SetValue(name)
+ self.AutoGenerateCB.SetValue(self.cfg.ReadBool("autogenerate", False))
+ self.EmbedCB.SetValue(self.cfg.ReadBool("embedResource", False))
+ self.MakeXRSFileCB.SetValue(self.cfg.ReadBool("makeXRS", False))
+ self.GettextCB.SetValue(self.cfg.ReadBool("genGettext", False))
+
+
+ def OnBrowse(self, evt):
+ path = self.FileNameTC.GetValue()
+ dirname = os.path.abspath(os.path.dirname(path))
+ name = os.path.split(path)[1]
+ dlg = wxFileDialog(self, 'Save As', dirname, name, '*.py',
+ wxSAVE | wxOVERWRITE_PROMPT)
+ if dlg.ShowModal() == wxID_OK:
+ path = dlg.GetPath()
+ self.FileNameTC.SetValue(path)
+ dlg.Destroy()
+
+
+ def OnGenerate(self, evt):
+ pypath = self.FileNameTC.GetValue()
+ embed = self.EmbedCB.GetValue()
+ frame.GeneratePython(self.dataFile, pypath, embed)
+ self.OnSaveOpts()
+
+
+ def OnSaveOpts(self, evt=None):
+ self.cfg.Write("filename", self.FileNameTC.GetValue())
+ self.cfg.WriteBool("autogenerate", self.AutoGenerateCB.GetValue())
+ self.cfg.WriteBool("embedResource", self.EmbedCB.GetValue())
+ self.cfg.WriteBool("makeXRS", self.MakeXRSFileCB.GetValue())
+ self.cfg.WriteBool("genGettext", self.GettextCB.GetValue())
+
+ self.EndModal(wx.ID_OK)
+
+
+################################################################################
+
def usage():
print >> sys.stderr, 'usage: xrced [-dhiv] [file]'
@@ -1210,6 +1331,7 @@ Please upgrade wxWindows to %d.%d.%d or higher.''' % MinWxVersion)
# Settings
global conf
conf = g.conf = wxConfig(style = wxCONFIG_USE_LOCAL_FILE)
+ conf.localconf = None
conf.autoRefresh = conf.ReadInt('autorefresh', True)
pos = conf.ReadInt('x', -1), conf.ReadInt('y', -1)
size = conf.ReadInt('width', 800), conf.ReadInt('height', 600)
@@ -1246,7 +1368,7 @@ Please upgrade wxWindows to %d.%d.%d or higher.''' % MinWxVersion)
def OnExit(self):
# Write config
global conf
- wc = wxConfigBase_Get()
+ wc = conf
wc.WriteInt('autorefresh', conf.autoRefresh)
wc.WriteInt('x', conf.x)
wc.WriteInt('y', conf.y)
diff --git a/wxPython/wx/tools/XRCed/xrced.xrc b/wxPython/wx/tools/XRCed/xrced.xrc
index 70e7772a84..e80599b59f 100644
--- a/wxPython/wx/tools/XRCed/xrced.xrc
+++ b/wxPython/wx/tools/XRCed/xrced.xrc
@@ -511,4 +511,104 @@
+
\ No newline at end of file
diff --git a/wxPython/wx/tools/pywxrc.py b/wxPython/wx/tools/pywxrc.py
index 3a92664d7a..dbec81f2ce 100644
--- a/wxPython/wx/tools/pywxrc.py
+++ b/wxPython/wx/tools/pywxrc.py
@@ -7,518 +7,223 @@
# Ported to Python in order to not require yet another
# binary in wxPython distributions
#
+# Massive rework by Eli Golovinsky
+#
# RCS-ID: $Id$
# Copyright: (c) 2004 by Total Control Software, 2000 Vaclav Slavik
# Licence: wxWindows license
#----------------------------------------------------------------------
"""
-pywxrc -- XML resource compiler
+pywxrc -- Python XML resource compiler
-Usage: wxrc [-h] [-v] [-e] [-c] [-p] [-g] [-n ] [-o ] input file(s)...
- -h, --help show help message
- -v, --verbose be verbose
- -e, --extra-cpp-code output C++ header file with XRC derived classes
- -c, --cpp-code output C++ source rather than .xrs file
- -p, --python-code output wxPython source rather than .rsc file
- -g, --gettext output list of translatable strings (to stdout or file if -o used)
- -n, --function str C++/Python function name (with -c or -p) [InitXmlResource]
- -o, --output str output file [resource.xrs/cpp/py]
+Usage: python pywxrc.py -h
+ python pywxrc.py [-e] [-o filename]
+
+ -h, --help show help message
+ -e, --embed embed resources in output file
+ -o, --output output filename, or - for stdout
"""
-import sys, os, getopt, glob
+import sys, os, getopt, glob, re
+import xml.dom.minidom as minidom
import wx
import wx.xrc
-
#----------------------------------------------------------------------
-class XRCWidgetData:
- def __init__(self, vname, vclass):
- self.name = vname
- self.klass = vclass
- def GetName(self):
- return self.name
- def GetClass(self):
- return self.klass
+class PythonTemplates:
+ FILE_HEADER = """\
+# This file was automatically generated by pywxrc, do not edit by hand.
+import wx
+import wx.xrc as xrc
-#----------------------------------------------------------------------
+__res = None
-class XRCWndClassData:
- def __init__(self, className, parentClassName, node):
- self.className = className
- self.parentClassName = parentClassName
- self.BrowseXmlNode(node.GetChildren())
- self.wdata = []
+def get_resources():
+ \"\"\" This function provides access to the XML resources in this module.\"\"\"
+ global __res
+ if __res == None:
+ __init_resources()
+ return __res
+"""
- def BrowseXmlNode(self, node):
- while node:
- if node.GetName() == "object" and node.HasProp("class") and node.HasProp("name"):
- classVal = node.GetPropVal("class", "")
- nameVal = node.GetPropVal("name", "")
- self.wdata.append(XRCWidgetData(nameVal, classVal))
- children = node.GetChildren()
- if children:
- self.BrowseXmlNode(children)
- node = node.GetNext()
-
-
- def GetWidgetData(self):
- return self.wdata
-
-
- def IsRealClass(self, name):
- if name in ['tool', 'unknown', 'notebookpage', 'separator',
- 'sizeritem', 'wxMenuItem']:
- return False
- else:
- return True
-
-
- def GenerateHeaderCode(self, file):
- file.write("class %s : public %s {\nprotected:\n" % (self.className, self.parentClassName))
-
- for w in self.wdata:
- if not self.IsRealClass(w.GetClass()):
- continue
- if not w.GetName():
- continue
- file.write(" " + w.GetClass() + "* " + w.GetName() + ";\n")
+ CLASS_HEADER = """\
+class %(windowName)sBase(wx.%(windowClass)s):
+ def PreCreate(self):
+ \"\"\" This function is called during the class's initialization.
- file.write("\nprivate:\n void InitWidgetsFromXRC(){\n",
- + " wxXmlResource::Get()->LoadObject(this,NULL,\""
- + self.className
- + "\",\""
- + self.parentClassName
- + "\");\n");
-
- for w in self.wdata:
- if not self.IsRealClass(w.GetClass()):
- continue
- if not w.GetName():
- continue
- file.write( " "
- + w.GetName()
- + " = XRCCTRL(*this,\""
- + w.GetName()
- + "\","
- + w.GetClass()
- + ");\n")
-
- file.write(" }\n")
- file.write("public:\n"
- + self.className
- + "::"
- + self.className
- + "(){\n"
- + " InitWidgetsFromXRC();\n"
- + " }\n"
- + "};\n")
-
-
-
-#----------------------------------------------------------------------
-
-
-class XmlResApp:
- def __init__(self):
- self.flagVerbose = False
- self.flagCPP = False
- self.flagH = False
- self.flagPython = False
- self.flagGettext = False
- self.parOutput = ""
- self.parFuncname = "InitXmlResource"
- self.parFiles = []
- self.aXRCWndClassData = []
-
-
- #--------------------------------------------------
- def main(self, args):
- try:
- opts, args = getopt.getopt(args, "hvecpgn:o:",
- "help verbose extra-cpp-code cpp-code python-code gettext function= output=".split())
- except getopt.GetoptError:
- print __doc__
- sys.exit(1)
-
- for opt, val in opts:
- if opt in ["-h", "--help"]:
- print __doc__
- sys.exit(1)
-
- if opt in ["-v", "--verbose"]:
- self.flagVerbose = True
-
- if opt in ["-e", "--extra-cpp-code"]:
- self.flagH = True
-
- if opt in ["-c", "--cpp-code"]:
- self.flagCPP = True
-
- if opt in ["-p", "--python-code"]:
- self.flagPython = True
-
- if opt in ["-g", "--gettext"]:
- self.flagGettext = True
-
- if opt in ["-n", "--function"]:
- self.parFuncname = val
-
- if opt in ["-o", "--output"]:
- self.parOutput = val
-
- if self.flagCPP + self.flagPython + self.flagGettext == 0:
- print __doc__
- print "\nYou must specify one of -c, -p or -g!\n"
- sys.exit(1)
-
- if self.flagCPP + self.flagPython + self.flagGettext > 1:
- print __doc__
- print "\n-c, -p and -g are mutually exclusive, specify only 1!\n"
- sys.exit(1)
-
-
- if self.parOutput:
- self.parOutput = os.path.normpath(self.parOutput)
- self.parOutputPath = os.path.split(self.parOutput)[0]
- else:
- self.parOutputPath = "."
- if self.flagCPP:
- self.parOutput = "resource.cpp"
- elif self.flagPython:
- self.parOutput = "resource.py"
- elif self.flagGettext:
- self.parOutput = ""
- else:
- self.parOutput = "resource.xrs"
-
- if not args:
- print __doc__
- sys.exit(1)
- for arg in args:
- self.parFiles += glob.glob(arg)
-
- self.retCode = 0
- if self.flagGettext:
- self.OutputGettext()
- else:
- self.CompileRes()
-
-
-
- #--------------------------------------------------
- def CompileRes(self):
- files = self.PrepareTempFiles()
- try:
- os.unlink(self.parOutput)
- except OSError:
- pass
-
- if not self.retCode:
- if self.flagCPP:
- self.MakePackageCPP(files)
- if self.flagH:
- self.GenCPPHeader()
-
- elif self.flagPython:
- self.MakePackagePython(files)
-
- else:
- self.MakePackageZIP(files)
-
- self.DeleteTempFiles(files)
-
-
- #--------------------------------------------------
- def OutputGettext(self):
+ Override it for custom setup before the window is created usually to
+ set additional window styles using SetWindowStyle() and SetExtraStyle().\"\"\"
pass
+
+ def __init__(self, parent):
+ # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
+ pre = wx.Pre%(windowClass)s()
+ get_resources().LoadOn%(windowClass)s(pre, parent, "%(windowName)s")
+ self.PreCreate()
+ self.PostCreate(pre)
+
+ # Define variables for the controls
+"""
+
+ CREATE_WIDGET_VAR = """\
+ self.%(widgetName)s = xrc.XRCCTRL(self, \"%(widgetName)s\")
+"""
+
+ INIT_RESOURE_HEADER = """\
+# -------------------------------------------------------------
+# ------------------------ Resource data ----------------------
+# -------------------------------------------------------------
+
+def __init_resources():
+"""
+
+ LOAD_RES_FILE = """\
+ global __res
+ __res = xrc.XmlResource('%(resourceFilename)s')
+"""
+
+ FILE_AS_STRING = """\
+ %(filename)s = '''\\
+%(fileData)s'''
+
+
+"""
+
+ PREPARE_MEMFS = """\
+ # Load all the strings as memory files
+ wx.FileSystem.AddHandler(wx.MemoryFSHandler())
+"""
- #--------------------------------------------------
- def GetInternalFileName(self, name, flist):
- name2 = name;
- name2 = name2.replace(":", "_")
- name2 = name2.replace("/", "_")
- name2 = name2.replace("\\", "_")
- name2 = name2.replace("*", "_")
- name2 = name2.replace("?", "_")
+ ADD_FILE_TO_MEMFS = """\
+ wx.MemoryFSHandler.AddFile('XRC/%(memoryPath)s/%(filename)s', %(filename)s)
+"""
- s = os.path.split(self.parOutput)[1] + "$" + name2
+ LOAD_RES_MEMFS = """\
+ global __res
+ __res = xrc.EmptyXmlResource()
+ __res.Load('memory:XRC/%(memoryPath)s/%(resourceFilename)s')
+"""
- if os.path.exists(s) and s not in flist:
- i = 0
- while True:
- s = os.path.split(self.parOutput)[1] + ("$%s%03d" % (name2, i))
- if not os.path.exists(s) or s in flist:
- break
- return s;
-
+#----------------------------------------------------------------------
- #--------------------------------------------------
- def PrepareTempFiles(self):
- flist = []
- for f in self.parFiles:
- if self.flagVerbose:
- print "processing %s..." % f
+class XmlResourceCompiler:
+
+ templates = PythonTemplates()
- doc = wx.xrc.EmptyXmlDocument()
+ """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)
+
+ resourceDocument = minidom.parse(resourceFilename)
+ print >>outputFile, self.templates.FILE_HEADER
+ print >>outputFile, self.GenerateClasses(resourceDocument)
+
+ if embedResources:
+ print >>outputFile, self.GenerateInitResourcesEmbedded(resourceFilename, resourceDocument)
+ else:
+ print >>outputFile, self.GenerateInitResourcesFile(resourceFilename, resourceDocument)
+
+ #-------------------------------------------------------------------
+
+ def GenerateClasses(self, resourceDocument):
+ outputList = []
+
+ resource = resourceDocument.firstChild
+ topWindows = [e for e in resource.childNodes
+ if e.nodeType == e.ELEMENT_NODE and e.tagName == "object"]
+
+ # Generate a class for each top-window object (Frame, Panel, Dialog, etc.)
+ for topWindow in topWindows:
+ windowClass = topWindow.getAttribute("class")
+ windowClass = re.sub("^wx", "", windowClass)
+ windowName = topWindow.getAttribute("name")
+ outputList.append(self.templates.CLASS_HEADER % locals())
- if not doc.Load(f):
- print "Error parsing file", f
- self.retCode = 1
- continue
-
- path, name = os.path.split(f)
- name, ext = os.path.splitext(name)
-
- self.FindFilesInXML(doc.GetRoot(), flist, path)
- if self.flagH:
- node = doc.GetRoot().GetChildren()
- while node:
- if node.GetName() == "object" and node.HasProp("class") and node.HasProp("name"):
- classVal = node.GetPropVal("class", "")
- nameVal = node.GetPropVal("name", "")
- self.aXRCWndClassData.append(XRCWidgetData(nameVal, classVal))
- node = node.GetNext()
- internalName = self.GetInternalFileName(f, flist)
-
- doc.Save(os.path.join(self.parOutputPath, internalName))
- flist.append(internalName)
-
- return flist
-
-
- #--------------------------------------------------
- # Does 'node' contain filename information at all?
- def NodeContainsFilename(self, node):
- # Any bitmaps:
- if node.GetName() == "bitmap":
- return True
-
- if node.GetName() == "icon":
- return True
-
- # URLs in wxHtmlWindow:
- if node.GetName() == "url":
- return True
-
- # wxBitmapButton:
- parent = node.GetParent()
- if parent != None and \
- parent.GetPropVal("class", "") == "wxBitmapButton" and \
- (node.GetName() == "focus" or node.etName() == "disabled" or
- node.GetName() == "selected"):
- return True
-
- # wxBitmap or wxIcon toplevel resources:
- if node.GetName() == "object":
- klass = node.GetPropVal("class", "")
- if klass == "wxBitmap" or klass == "wxIcon":
- return True
-
- return False
-
- #--------------------------------------------------
- # find all files mentioned in structure, e.g. filename
- def FindFilesInXML(self, node, flist, inputPath):
- # Is 'node' XML node element?
- if node is None: return
- if node.GetType() != wx.xrc.XML_ELEMENT_NODE: return
-
- containsFilename = self.NodeContainsFilename(node);
-
- n = node.GetChildren()
- while n:
- if (containsFilename and
- (n.GetType() == wx.xrc.XML_TEXT_NODE or
- n.GetType() == wx.xrc.XML_CDATA_SECTION_NODE)):
-
- if os.path.isabs(n.GetContent()) or inputPath == "":
- fullname = n.GetContent()
- else:
- fullname = os.path.join(inputPath, n.GetContent())
-
- if self.flagVerbose:
- print "adding %s..." % fullname
-
- filename = self.GetInternalFileName(n.GetContent(), flist)
- n.SetContent(filename)
-
- if filename not in flist:
- flist.append(filename)
+ # Generate a variable for each control, and standard event handlers
+ # for standard controls.
+ for widget in topWindow.getElementsByTagName("object"):
+ widgetClass = widget.getAttribute("class")
+ widgetClass = re.sub("^wx", "", widgetClass)
+ widgetName = widget.getAttribute("name")
+ if (widgetName != "" and widgetClass != "" and
+ widgetClass not in
+ ['tool', 'unknown', 'notebookpage',
+ 'separator', 'sizeritem', 'MenuItem']):
+ outputList.append(self.templates.CREATE_WIDGET_VAR % locals())
+ outputList.append('\n\n')
- inp = open(fullname)
- out = open(os.path.join(self.parOutputPath, filename), "w")
- out.write(inp.read())
+ return "".join(outputList)
- # subnodes:
- if n.GetType() == wx.xrc.XML_ELEMENT_NODE:
- self.FindFilesInXML(n, flist, inputPath);
+ #-------------------------------------------------------------------
- n = n.GetNext()
-
+ def GenerateInitResourcesEmbedded(self, resourceFilename, resourceDocument):
+ outputList = []
+ outputList.append(self.templates.INIT_RESOURE_HEADER)
- #--------------------------------------------------
- def DeleteTempFiles(self, flist):
- for f in flist:
- os.unlink(os.path.join(self.parOutputPath, f))
+ files = []
+ resourcePath = os.path.split(resourceFilename)[0]
+ memoryPath = self.GetMemoryFilename(os.path.splitext(os.path.split(resourceFilename)[1])[0])
+ resourceFilename = self.GetMemoryFilename(os.path.split(resourceFilename)[1])
+
+ self.ReplaceFilenamesInXRC(resourceDocument.firstChild, files, resourcePath)
+
+ filename = resourceFilename
+ fileData = resourceDocument.toxml()
+ outputList.append(self.templates.FILE_AS_STRING % locals())
- #--------------------------------------------------
- def MakePackageZIP(self, flist):
- files = " ".join(flist)
+ for f in files:
+ filename = self.GetMemoryFilename(f)
+ fileData = self.FileToString(os.path.join(resourcePath, f))
+ outputList.append(self.templates.FILE_AS_STRING % locals())
- if self.flagVerbose:
- print "compressing %s..." % self.parOutput
+ 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())
+
+ outputList.append(self.templates.LOAD_RES_MEMFS % locals())
+
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
- cwd = os.getcwd()
- os.chdir(self.parOutputPath)
- cmd = "zip -9 -j "
- if not self.flagVerbose:
- cmd += "-q "
- cmd += self.parOutput + " " + files
+ def GenerateInitResourcesFile(self, resourceFilename, resourceDocument):
+ outputList = []
+ outputList.append(self.templates.INIT_RESOURE_HEADER)
+ outputList.append(self.templates.LOAD_RES_FILE % locals())
+ return "".join(outputList)
- from distutils.spawn import spawn
- try:
- spawn(cmd.split())
- success = True
- except:
- success = False
-
- os.chdir(cwd)
-
- if not success:
- print "Unable to execute zip program. Make sure it is in the path."
- print "You can download it at http://www.cdrom.com/pub/infozip/"
- self.retCode = 1
-
+ #-------------------------------------------------------------------
- #--------------------------------------------------
- def FileToCppArray(self, filename, num):
- output = []
+ def GetMemoryFilename(self, filename):
+ # Remove special chars from the filename
+ return re.sub(r"[^A-Za-z0-9_]", "_", filename)
+
+ #-------------------------------------------------------------------
+
+ def FileToString(self, filename):
+ outputList = []
+
buffer = open(filename, "rb").read()
- lng = len(buffer)
-
- output.append("static size_t xml_res_size_%d = %d;\n" % (num, lng))
- output.append("static unsigned char xml_res_file_%d[] = {\n" % num)
- # we cannot use string literals because MSVC is dumb wannabe compiler
- # with arbitrary limitation to 2048 strings :(
+ fileLen = len(buffer)
linelng = 0
- for i in xrange(lng):
- tmp = "%i" % ord(buffer[i])
- if i != 0: output.append(',')
- if linelng > 70:
- linelng = 0
- output.append("\n")
-
- output.append(tmp)
- linelng += len(tmp)+1
-
- output.append("};\n\n")
-
- return "".join(output)
-
-
-
- #--------------------------------------------------
- def MakePackageCPP(self, flist):
- file = open(self.parOutput, "wt")
-
- if self.flagVerbose:
- print "creating C++ source file %s..." % self.parOutput
-
- file.write("""\
-//
-// This file was automatically generated by wxrc, do not edit by hand.
-//
-
-#include
-
-#ifdef __BORLANDC__
- #pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
- #include
-#endif
-
-#include
-#include
-#include
-#include
-
-""")
-
- num = 0
- for f in flist:
- file.write(self.FileToCppArray(os.path.join(self.parOutputPath, f), num))
- num += 1
-
-
- file.write("void " + self.parFuncname + "()\n")
- file.write("""\
-{
-
- // Check for memory FS. If not present, load the handler:
- {
- wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/dummy_file\"), wxT(\"dummy one\"));
- wxFileSystem fsys;
- wxFSFile *f = fsys.OpenFile(wxT(\"memory:XRC_resource/dummy_file\"));
- wxMemoryFSHandler::RemoveFile(wxT(\"XRC_resource/dummy_file\"));
- if (f) delete f;
- else wxFileSystem::AddHandler(new wxMemoryFSHandler);
- }
-""");
-
- for i in range(len(flist)):
- file.write(" wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/" + flist[i])
- file.write("\"), xml_res_file_%i, xml_res_size_%i);\n" %(i, i))
-
-
- for i in range(len(self.parFiles)):
- file.write(" wxXmlResource::Get()->Load(wxT(\"memory:XRC_resource/" +
- self.GetInternalFileName(self.parFiles[i], flist) +
- "\"));\n")
-
- file.write("}\n")
-
-
- #--------------------------------------------------
- def GenCPPHeader(self):
- path, name = os.path.split(self.parOutput)
- name, ext = os.path.splitext(name)
- heaFileName = name+'.h'
-
- file = open(heaFileName, "wt")
- file.write("""\
-//
-// This file was automatically generated by wxrc, do not edit by hand.
-//
-""");
- file.write("#ifndef __" + name + "_h__\n")
- file.write("#define __" + name + "_h__\n")
-
- for data in self.aXRCWndClassData:
- data.GenerateHeaderCode(file)
-
- file.write("\nvoid \n" + self.parFuncname + "();\n#endif\n")
-
-
- #--------------------------------------------------
- def FileToPythonArray(self, filename, num):
- output = []
- buffer = open(filename, "rb").read()
- lng = len(buffer)
-
- output.append(" xml_res_file_%d = '''\\\n" % num)
-
- linelng = 0
- for i in xrange(lng):
+ for i in xrange(fileLen):
s = buffer[i]
c = ord(s)
if s == '\n':
@@ -533,182 +238,121 @@ class XmlResApp:
if linelng > 70:
linelng = 0
- output.append("\\\n")
-
- output.append(tmp)
+ outputList.append("\\\n")
+
+ outputList.append(tmp)
linelng += len(tmp)
-
- output.append("'''\n\n")
-
- return "".join(output)
-
- #--------------------------------------------------
- def MakePackagePython(self, flist):
- file = open(self.parOutput, "wt")
-
- if self.flagVerbose:
- print "creating Python source file %s..." % self.parOutput
-
- file.write("""\
-#
-# This file was automatically generated by wxrc, do not edit by hand.
-#
-
-import wx
-import wx.xrc
-
-""")
- file.write("def " + self.parFuncname + "():\n")
-
- num = 0
- for f in flist:
- file.write(self.FileToPythonArray(os.path.join(self.parOutputPath, f), num))
- num += 1
-
- file.write("""
-
- # check if the memory filesystem handler has been loaded yet, and load it if not
- wx.MemoryFSHandler.AddFile('XRC_resource/dummy_file', 'dummy value')
- fsys = wx.FileSystem()
- f = fsys.OpenFile('memory:XRC_resource/dummy_file')
- wx.MemoryFSHandler.RemoveFile('XRC_resource/dummy_file')
- if f is not None:
- f.Destroy()
- else:
- wx.FileSystem.AddHandler(wx.MemoryFSHandler())
-
- # load all the strings as memory files and load into XmlRes
-""")
-
- for i in range(len(flist)):
- file.write(" wx.MemoryFSHandler.AddFile('XRC_resource/" + flist[i] +
- "', xml_res_file_%i)\n" % i)
-
- for pf in self.parFiles:
- file.write(" wx.xrc.XmlResource.Get().Load('memory:XRC_resource/" +
- self.GetInternalFileName(pf, flist) + "')\n")
-
- #--------------------------------------------------
- def OutputGettext(self):
- strings = self.FindStrings()
-
- if not self.parOutput:
- out = sys.stdout
- else:
- out = open(self.parOutput, "wt")
-
- for st in strings:
- out.write("_(\"%s\")\n" % st)
+ return "".join(outputList)
+ #-------------------------------------------------------------------
-
- #--------------------------------------------------
- def FindStrings(self):
- strings = []
- for pf in self.parFiles:
- if self.flagVerbose:
- print "processing %s..." % pf
+ def NodeContainsFilename(self, node):
+ """ Does 'node' contain filename information at all? """
- doc = wx.xrc.EmptyXmlDocument()
- if not doc.Load(pf):
- print "Error parsing file", pf
- self.retCode = 1
- continue
+ # Any bitmaps:
+ if node.nodeName == "bitmap":
+ return True
- strings += self.FindStringsInNode(doc.GetRoot())
+ if node.nodeName == "icon":
+ return True
- return strings
-
-
- #--------------------------------------------------
- def ConvertText(self, st):
- st2 = ""
- dt = list(st)
+ # URLs in wxHtmlWindow:
+ if node.nodeName == "url":
+ return True
- 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]
+ # wxBitmapButton:
+ parent = node.parentNode
+ if parent.__class__ != minidom.Document and \
+ parent.getAttribute("class") == "wxBitmapButton" and \
+ (node.nodeName == "focus" or node.nodeName == "disabled" or
+ node.nodeName == "selected"):
+ return True
- return st2
-
-
-
- #--------------------------------------------------
- def FindStringsInNode(self, parent):
- def is_number(st):
- try:
- i = int(st)
+ # wxBitmap or wxIcon toplevel resources:
+ if node.nodeName == "object":
+ klass = node.getAttribute("class")
+ if klass == "wxBitmap" or klass == "wxIcon":
return True
- except ValueError:
- return False
-
- strings = []
- if parent is None:
- return strings;
- child = parent.GetChildren()
- while child:
- if ((parent.GetType() == wx.xrc.XML_ELEMENT_NODE) and
- # parent is an element, i.e. has subnodes...
- (child.GetType() == wx.xrc.XML_TEXT_NODE or
- child.GetType() == wx.xrc.XML_CDATA_SECTION_NODE) and
- # ...it is textnode...
- (
- parent.GetName() == "label" or
- (parent.GetName() == "value" and
- not is_number(child.GetContent())) or
- parent.GetName() == "help" or
- parent.GetName() == "longhelp" or
- parent.GetName() == "tooltip" or
- parent.GetName() == "htmlcode" or
- parent.GetName() == "title" or
- parent.GetName() == "item"
- )):
- # ...and known to contain translatable string
- if (not self.flagGettext or
- parent.GetPropVal("translate", "1") != "0"):
+ return False
- strings.append(self.ConvertText(child.GetContent()))
+ #-------------------------------------------------------------------
- # subnodes:
- if child.GetType() == wx.xrc.XML_ELEMENT_NODE:
- strings += self.FindStringsInNode(child)
+ def ReplaceFilenamesInXRC(self, node, files, resourcePath):
+ """ Finds all files mentioned in resource file, e.g. filename
+ and replaces them with the memory filenames.
+
+ Fills a list of the filenames found."""
+
+ # Is 'node' XML node element?
+ if node is None: return
+ if node.nodeType != minidom.Document.ELEMENT_NODE: return
- child = child.GetNext()
+ containsFilename = self.NodeContainsFilename(node);
- return strings
+ for n in node.childNodes:
+
+ if (containsFilename and
+ (n.nodeType == minidom.Document.TEXT_NODE or
+ n.nodeType == minidom.Document.CDATA_SECTION_NODE)):
+
+ filename = n.nodeValue
+ memoryFilename = self.GetMemoryFilename(filename)
+ n.nodeValue = memoryFilename
+
+ if filename not in files:
+ files.append(filename)
+
+ # Recurse into children
+ if n.nodeType == minidom.Document.ELEMENT_NODE:
+ self.ReplaceFilenamesInXRC(n, files, resourcePath);
#---------------------------------------------------------------------------
-def main():
- XmlResApp().main(sys.argv[1:])
+def main(args):
+ resourceFilename = ""
+ outputFilename = ""
+ embedResources = False
+ try:
+ opts, args = getopt.gnu_getopt(args, "heo:", "help embed output=".split())
+ except getopt.GetoptError:
+ print __doc__
+ sys.exit(1)
+
+ # If there is no input file argument, show help and exit
+ if args:
+ resourceFilename = args[0]
+ else:
+ print __doc__
+ sys.exit(1)
+
+ # Parse options and arguments
+ for opt, val in opts:
+ if opt in ["-h", "--help"]:
+ print __doc__
+ sys.exit(1)
+
+ 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"
+
+ comp = XmlResourceCompiler()
+
+ try:
+ comp.MakePythonModule(resourceFilename, outputFilename, embedResources)
+ except IOError, e:
+ print >>sys.stderr, "%s." % str(e)
+ else:
+ if outputFilename != "-":
+ print >>sys.stderr, "Resources written to %s." % outputFilename
if __name__ == "__main__":
- main()
+ main(sys.argv[1:])