First pass at integrating a code generator in XRCed. Initial patch
from Eli Golovinsky, with lots of additional mods by me. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38618 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -21,7 +21,7 @@ MinWxVersion = (2,6,0)
|
|||||||
if wxVERSION[:3] < MinWxVersion:
|
if wxVERSION[:3] < MinWxVersion:
|
||||||
print '''\
|
print '''\
|
||||||
******************************* WARNING **************************************
|
******************************* 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.
|
Please upgrade wxWindows to %d.%d.%d or higher.
|
||||||
******************************************************************************''' % MinWxVersion
|
******************************************************************************''' % MinWxVersion
|
||||||
|
|
||||||
|
@@ -122,6 +122,9 @@ class Frame(wxFrame):
|
|||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
menu.Append(wxID_SAVE, '&Save\tCtrl-S', 'Save XRC file')
|
menu.Append(wxID_SAVE, '&Save\tCtrl-S', 'Save XRC file')
|
||||||
menu.Append(wxID_SAVEAS, 'Save &As...', 'Save XRC file under different name')
|
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.AppendSeparator()
|
||||||
menu.Append(wxID_EXIT, '&Quit\tCtrl-Q', 'Exit application')
|
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_OPEN, self.OnOpen)
|
||||||
EVT_MENU(self, wxID_SAVE, self.OnSaveOrSaveAs)
|
EVT_MENU(self, wxID_SAVE, self.OnSaveOrSaveAs)
|
||||||
EVT_MENU(self, wxID_SAVEAS, 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)
|
EVT_MENU(self, wxID_EXIT, self.OnExit)
|
||||||
# Edit
|
# Edit
|
||||||
EVT_MENU(self, wxID_UNDO, self.OnUndo)
|
EVT_MENU(self, wxID_UNDO, self.OnUndo)
|
||||||
@@ -373,6 +377,20 @@ class Frame(wxFrame):
|
|||||||
else:
|
else:
|
||||||
dlg.Destroy()
|
dlg.Destroy()
|
||||||
return
|
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:
|
else:
|
||||||
path = self.dataFile
|
path = self.dataFile
|
||||||
self.SetStatusText('Saving...')
|
self.SetStatusText('Saving...')
|
||||||
@@ -384,6 +402,11 @@ class Frame(wxFrame):
|
|||||||
self.Save(tmpName) # save temporary file first
|
self.Save(tmpName) # save temporary file first
|
||||||
shutil.move(tmpName, path)
|
shutil.move(tmpName, path)
|
||||||
self.dataFile = 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.SetStatusText('Data saved')
|
||||||
self.SaveRecent(path)
|
self.SaveRecent(path)
|
||||||
except IOError:
|
except IOError:
|
||||||
@@ -399,6 +422,28 @@ class Frame(wxFrame):
|
|||||||
EVT_MENU(self, newid, self.OnRecentFile)
|
EVT_MENU(self, newid, self.OnRecentFile)
|
||||||
conf.recentfiles[newid] = path
|
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):
|
def OnExit(self, evt):
|
||||||
self.Close()
|
self.Close()
|
||||||
|
|
||||||
@@ -1047,8 +1092,16 @@ Homepage: http://xrced.sourceforge.net\
|
|||||||
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
|
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
|
||||||
evt.Skip()
|
evt.Skip()
|
||||||
|
|
||||||
|
|
||||||
|
def CreateLocalConf(self, path):
|
||||||
|
name = os.path.splitext(path)[0]
|
||||||
|
name += '.xcfg'
|
||||||
|
return wx.FileConfig(localFilename=name)
|
||||||
|
|
||||||
|
|
||||||
def Clear(self):
|
def Clear(self):
|
||||||
self.dataFile = ''
|
self.dataFile = ''
|
||||||
|
conf.localconf = None
|
||||||
undoMan.Clear()
|
undoMan.Clear()
|
||||||
self.SetModified(False)
|
self.SetModified(False)
|
||||||
tree.Clear()
|
tree.Clear()
|
||||||
@@ -1094,6 +1147,7 @@ Homepage: http://xrced.sourceforge.net\
|
|||||||
if dir: os.chdir(dir)
|
if dir: os.chdir(dir)
|
||||||
tree.SetData(dom)
|
tree.SetData(dom)
|
||||||
self.SetTitle(progname + ': ' + os.path.basename(path))
|
self.SetTitle(progname + ': ' + os.path.basename(path))
|
||||||
|
conf.localconf = self.CreateLocalConf(self.dataFile)
|
||||||
except:
|
except:
|
||||||
# Nice exception printing
|
# Nice exception printing
|
||||||
inf = sys.exc_info()
|
inf = sys.exc_info()
|
||||||
@@ -1146,12 +1200,13 @@ Homepage: http://xrced.sourceforge.net\
|
|||||||
self.domCopy = None
|
self.domCopy = None
|
||||||
self.SetModified(False)
|
self.SetModified(False)
|
||||||
panel.SetModified(False)
|
panel.SetModified(False)
|
||||||
|
conf.localconf.Flush()
|
||||||
except:
|
except:
|
||||||
inf = sys.exc_info()
|
inf = sys.exc_info()
|
||||||
wxLogError(traceback.format_exception(inf[0], inf[1], None)[-1])
|
wxLogError(traceback.format_exception(inf[0], inf[1], None)[-1])
|
||||||
wxLogError('Error writing file: %s' % path)
|
wxLogError('Error writing file: %s' % path)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def AskSave(self):
|
def AskSave(self):
|
||||||
if not (self.modified or panel.IsModified()): return True
|
if not (self.modified or panel.IsModified()): return True
|
||||||
flags = wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
|
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():
|
def usage():
|
||||||
print >> sys.stderr, 'usage: xrced [-dhiv] [file]'
|
print >> sys.stderr, 'usage: xrced [-dhiv] [file]'
|
||||||
|
|
||||||
@@ -1210,6 +1331,7 @@ Please upgrade wxWindows to %d.%d.%d or higher.''' % MinWxVersion)
|
|||||||
# Settings
|
# Settings
|
||||||
global conf
|
global conf
|
||||||
conf = g.conf = wxConfig(style = wxCONFIG_USE_LOCAL_FILE)
|
conf = g.conf = wxConfig(style = wxCONFIG_USE_LOCAL_FILE)
|
||||||
|
conf.localconf = None
|
||||||
conf.autoRefresh = conf.ReadInt('autorefresh', True)
|
conf.autoRefresh = conf.ReadInt('autorefresh', True)
|
||||||
pos = conf.ReadInt('x', -1), conf.ReadInt('y', -1)
|
pos = conf.ReadInt('x', -1), conf.ReadInt('y', -1)
|
||||||
size = conf.ReadInt('width', 800), conf.ReadInt('height', 600)
|
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):
|
def OnExit(self):
|
||||||
# Write config
|
# Write config
|
||||||
global conf
|
global conf
|
||||||
wc = wxConfigBase_Get()
|
wc = conf
|
||||||
wc.WriteInt('autorefresh', conf.autoRefresh)
|
wc.WriteInt('autorefresh', conf.autoRefresh)
|
||||||
wc.WriteInt('x', conf.x)
|
wc.WriteInt('x', conf.x)
|
||||||
wc.WriteInt('y', conf.y)
|
wc.WriteInt('y', conf.y)
|
||||||
|
@@ -511,4 +511,104 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="wxDialog" name="PYTHON_OPTIONS">
|
||||||
|
<title>Python Module Config</title>
|
||||||
|
<object class="wxBoxSizer">
|
||||||
|
<orient>wxVERTICAL</orient>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxBoxSizer">
|
||||||
|
<orient>wxVERTICAL</orient>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxCheckBox" name="AutoGenerateCB">
|
||||||
|
<label>Autogenerate Python module when saving XRC</label>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxCheckBox" name="EmbedCB">
|
||||||
|
<label>Embed resource in python module</label>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxCheckBox" name="GettextCB">
|
||||||
|
<label>Generate gettext strings</label>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxCheckBox" name="MakeXRSFileCB">
|
||||||
|
<label>Generate and use compressed XRS file</label>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="spacer">
|
||||||
|
<size>1,10</size>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxStaticText">
|
||||||
|
<label>Filename:</label>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxBoxSizer">
|
||||||
|
<orient>wxHORIZONTAL</orient>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxTextCtrl" name="FileNameTC">
|
||||||
|
<size>500,-1</size>
|
||||||
|
</object>
|
||||||
|
<flag>wxALIGN_CENTRE_VERTICAL</flag>
|
||||||
|
</object>
|
||||||
|
<object class="spacer">
|
||||||
|
<size>5,0</size>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxButton" name="BrowseBtn">
|
||||||
|
<label>Browse...</label>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<flag>wxALL</flag>
|
||||||
|
<border>10</border>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxStaticLine"/>
|
||||||
|
<flag>wxEXPAND</flag>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxBoxSizer">
|
||||||
|
<orient>wxHORIZONTAL</orient>
|
||||||
|
<object class="spacer">
|
||||||
|
<size>1,10</size>
|
||||||
|
<option>1</option>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxButton" name="GenerateBtn">
|
||||||
|
<label>Generate module</label>
|
||||||
|
<default>1</default>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="spacer">
|
||||||
|
<size>10,1</size>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxButton" name="SaveOptsBtn">
|
||||||
|
<label>Save options</label>
|
||||||
|
<style></style>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="spacer">
|
||||||
|
<size>10,1</size>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxButton" name="wxID_CANCEL">
|
||||||
|
<label></label>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<flag>wxALL|wxEXPAND|wxALIGN_CENTRE_HORIZONTAL</flag>
|
||||||
|
<border>10</border>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
</resource>
|
</resource>
|
@@ -7,518 +7,223 @@
|
|||||||
# Ported to Python in order to not require yet another
|
# Ported to Python in order to not require yet another
|
||||||
# binary in wxPython distributions
|
# binary in wxPython distributions
|
||||||
#
|
#
|
||||||
|
# Massive rework by Eli Golovinsky
|
||||||
|
#
|
||||||
# RCS-ID: $Id$
|
# RCS-ID: $Id$
|
||||||
# Copyright: (c) 2004 by Total Control Software, 2000 Vaclav Slavik
|
# Copyright: (c) 2004 by Total Control Software, 2000 Vaclav Slavik
|
||||||
# Licence: wxWindows license
|
# Licence: wxWindows license
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pywxrc -- XML resource compiler
|
pywxrc -- Python XML resource compiler
|
||||||
|
|
||||||
Usage: wxrc [-h] [-v] [-e] [-c] [-p] [-g] [-n <str>] [-o <str>] input file(s)...
|
Usage: python pywxrc.py -h
|
||||||
-h, --help show help message
|
python pywxrc.py <resource.xrc> [-e] [-o filename]
|
||||||
-v, --verbose be verbose
|
|
||||||
-e, --extra-cpp-code output C++ header file with XRC derived classes
|
-h, --help show help message
|
||||||
-c, --cpp-code output C++ source rather than .xrs file
|
-e, --embed embed resources in output file
|
||||||
-p, --python-code output wxPython source rather than .rsc file
|
-o, --output output filename, or - for stdout
|
||||||
-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]
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys, os, getopt, glob
|
import sys, os, getopt, glob, re
|
||||||
|
import xml.dom.minidom as minidom
|
||||||
import wx
|
import wx
|
||||||
import wx.xrc
|
import wx.xrc
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
class XRCWidgetData:
|
class PythonTemplates:
|
||||||
def __init__(self, vname, vclass):
|
FILE_HEADER = """\
|
||||||
self.name = vname
|
# This file was automatically generated by pywxrc, do not edit by hand.
|
||||||
self.klass = vclass
|
|
||||||
def GetName(self):
|
|
||||||
return self.name
|
|
||||||
def GetClass(self):
|
|
||||||
return self.klass
|
|
||||||
|
|
||||||
|
import wx
|
||||||
|
import wx.xrc as xrc
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
__res = None
|
||||||
|
|
||||||
class XRCWndClassData:
|
def get_resources():
|
||||||
def __init__(self, className, parentClassName, node):
|
\"\"\" This function provides access to the XML resources in this module.\"\"\"
|
||||||
self.className = className
|
global __res
|
||||||
self.parentClassName = parentClassName
|
if __res == None:
|
||||||
self.BrowseXmlNode(node.GetChildren())
|
__init_resources()
|
||||||
self.wdata = []
|
return __res
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
def BrowseXmlNode(self, node):
|
CLASS_HEADER = """\
|
||||||
while node:
|
class %(windowName)sBase(wx.%(windowClass)s):
|
||||||
if node.GetName() == "object" and node.HasProp("class") and node.HasProp("name"):
|
def PreCreate(self):
|
||||||
classVal = node.GetPropVal("class", "")
|
\"\"\" This function is called during the class's initialization.
|
||||||
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")
|
|
||||||
|
|
||||||
file.write("\nprivate:\n void InitWidgetsFromXRC(){\n",
|
Override it for custom setup before the window is created usually to
|
||||||
+ " wxXmlResource::Get()->LoadObject(this,NULL,\""
|
set additional window styles using SetWindowStyle() and SetExtraStyle().\"\"\"
|
||||||
+ 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):
|
|
||||||
pass
|
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())
|
||||||
|
"""
|
||||||
|
|
||||||
#--------------------------------------------------
|
ADD_FILE_TO_MEMFS = """\
|
||||||
def GetInternalFileName(self, name, flist):
|
wx.MemoryFSHandler.AddFile('XRC/%(memoryPath)s/%(filename)s', %(filename)s)
|
||||||
name2 = name;
|
"""
|
||||||
name2 = name2.replace(":", "_")
|
|
||||||
name2 = name2.replace("/", "_")
|
|
||||||
name2 = name2.replace("\\", "_")
|
|
||||||
name2 = name2.replace("*", "_")
|
|
||||||
name2 = name2.replace("?", "_")
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
#--------------------------------------------------
|
class XmlResourceCompiler:
|
||||||
def PrepareTempFiles(self):
|
|
||||||
flist = []
|
templates = PythonTemplates()
|
||||||
for f in self.parFiles:
|
|
||||||
if self.flagVerbose:
|
|
||||||
print "processing %s..." % f
|
|
||||||
|
|
||||||
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):
|
# Generate a variable for each control, and standard event handlers
|
||||||
print "Error parsing file", f
|
# for standard controls.
|
||||||
self.retCode = 1
|
for widget in topWindow.getElementsByTagName("object"):
|
||||||
continue
|
widgetClass = widget.getAttribute("class")
|
||||||
|
widgetClass = re.sub("^wx", "", widgetClass)
|
||||||
path, name = os.path.split(f)
|
widgetName = widget.getAttribute("name")
|
||||||
name, ext = os.path.splitext(name)
|
if (widgetName != "" and widgetClass != "" and
|
||||||
|
widgetClass not in
|
||||||
self.FindFilesInXML(doc.GetRoot(), flist, path)
|
['tool', 'unknown', 'notebookpage',
|
||||||
if self.flagH:
|
'separator', 'sizeritem', 'MenuItem']):
|
||||||
node = doc.GetRoot().GetChildren()
|
outputList.append(self.templates.CREATE_WIDGET_VAR % locals())
|
||||||
while node:
|
outputList.append('\n\n')
|
||||||
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. <bitmap>filename</bitmap>
|
|
||||||
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)
|
|
||||||
|
|
||||||
inp = open(fullname)
|
return "".join(outputList)
|
||||||
out = open(os.path.join(self.parOutputPath, filename), "w")
|
|
||||||
out.write(inp.read())
|
|
||||||
|
|
||||||
# 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)
|
||||||
|
|
||||||
#--------------------------------------------------
|
files = []
|
||||||
def DeleteTempFiles(self, flist):
|
|
||||||
for f in flist:
|
|
||||||
os.unlink(os.path.join(self.parOutputPath, f))
|
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
#--------------------------------------------------
|
for f in files:
|
||||||
def MakePackageZIP(self, flist):
|
filename = self.GetMemoryFilename(f)
|
||||||
files = " ".join(flist)
|
fileData = self.FileToString(os.path.join(resourcePath, f))
|
||||||
|
outputList.append(self.templates.FILE_AS_STRING % locals())
|
||||||
|
|
||||||
if self.flagVerbose:
|
outputList.append(self.templates.PREPARE_MEMFS % locals())
|
||||||
print "compressing %s..." % self.parOutput
|
|
||||||
|
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()
|
def GenerateInitResourcesFile(self, resourceFilename, resourceDocument):
|
||||||
os.chdir(self.parOutputPath)
|
outputList = []
|
||||||
cmd = "zip -9 -j "
|
outputList.append(self.templates.INIT_RESOURE_HEADER)
|
||||||
if not self.flagVerbose:
|
outputList.append(self.templates.LOAD_RES_FILE % locals())
|
||||||
cmd += "-q "
|
return "".join(outputList)
|
||||||
cmd += self.parOutput + " " + files
|
|
||||||
|
|
||||||
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 GetMemoryFilename(self, filename):
|
||||||
def FileToCppArray(self, filename, num):
|
# Remove special chars from the filename
|
||||||
output = []
|
return re.sub(r"[^A-Za-z0-9_]", "_", filename)
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
def FileToString(self, filename):
|
||||||
|
outputList = []
|
||||||
|
|
||||||
buffer = open(filename, "rb").read()
|
buffer = open(filename, "rb").read()
|
||||||
lng = len(buffer)
|
fileLen = 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 :(
|
|
||||||
|
|
||||||
linelng = 0
|
linelng = 0
|
||||||
for i in xrange(lng):
|
for i in xrange(fileLen):
|
||||||
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 <wx/wxprec.h>
|
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
|
||||||
#pragma hdrstop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
|
||||||
#include <wx/wx.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <wx/filesys.h>
|
|
||||||
#include <wx/fs_mem.h>
|
|
||||||
#include <wx/xrc/xmlres.h>
|
|
||||||
#include <wx/xrc/xh_all.h>
|
|
||||||
|
|
||||||
""")
|
|
||||||
|
|
||||||
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):
|
|
||||||
s = buffer[i]
|
s = buffer[i]
|
||||||
c = ord(s)
|
c = ord(s)
|
||||||
if s == '\n':
|
if s == '\n':
|
||||||
@@ -533,182 +238,121 @@ class XmlResApp:
|
|||||||
|
|
||||||
if linelng > 70:
|
if linelng > 70:
|
||||||
linelng = 0
|
linelng = 0
|
||||||
output.append("\\\n")
|
outputList.append("\\\n")
|
||||||
|
|
||||||
output.append(tmp)
|
outputList.append(tmp)
|
||||||
linelng += len(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")
|
|
||||||
|
|
||||||
|
return "".join(outputList)
|
||||||
#--------------------------------------------------
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
def NodeContainsFilename(self, node):
|
||||||
#--------------------------------------------------
|
""" Does 'node' contain filename information at all? """
|
||||||
def FindStrings(self):
|
|
||||||
strings = []
|
|
||||||
for pf in self.parFiles:
|
|
||||||
if self.flagVerbose:
|
|
||||||
print "processing %s..." % pf
|
|
||||||
|
|
||||||
doc = wx.xrc.EmptyXmlDocument()
|
# Any bitmaps:
|
||||||
if not doc.Load(pf):
|
if node.nodeName == "bitmap":
|
||||||
print "Error parsing file", pf
|
return True
|
||||||
self.retCode = 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
strings += self.FindStringsInNode(doc.GetRoot())
|
if node.nodeName == "icon":
|
||||||
|
return True
|
||||||
|
|
||||||
return strings
|
# URLs in wxHtmlWindow:
|
||||||
|
if node.nodeName == "url":
|
||||||
|
return True
|
||||||
#--------------------------------------------------
|
|
||||||
def ConvertText(self, st):
|
|
||||||
st2 = ""
|
|
||||||
dt = list(st)
|
|
||||||
|
|
||||||
skipNext = False
|
# wxBitmapButton:
|
||||||
for i in range(len(dt)):
|
parent = node.parentNode
|
||||||
if skipNext:
|
if parent.__class__ != minidom.Document and \
|
||||||
skipNext = False
|
parent.getAttribute("class") == "wxBitmapButton" and \
|
||||||
continue
|
(node.nodeName == "focus" or node.nodeName == "disabled" or
|
||||||
|
node.nodeName == "selected"):
|
||||||
if dt[i] == '_':
|
return True
|
||||||
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
|
# wxBitmap or wxIcon toplevel resources:
|
||||||
|
if node.nodeName == "object":
|
||||||
|
klass = node.getAttribute("class")
|
||||||
|
if klass == "wxBitmap" or klass == "wxIcon":
|
||||||
#--------------------------------------------------
|
|
||||||
def FindStringsInNode(self, parent):
|
|
||||||
def is_number(st):
|
|
||||||
try:
|
|
||||||
i = int(st)
|
|
||||||
return True
|
return True
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
strings = []
|
|
||||||
if parent is None:
|
|
||||||
return strings;
|
|
||||||
child = parent.GetChildren()
|
|
||||||
|
|
||||||
while child:
|
return False
|
||||||
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"):
|
|
||||||
|
|
||||||
strings.append(self.ConvertText(child.GetContent()))
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
# subnodes:
|
def ReplaceFilenamesInXRC(self, node, files, resourcePath):
|
||||||
if child.GetType() == wx.xrc.XML_ELEMENT_NODE:
|
""" Finds all files mentioned in resource file, e.g. <bitmap>filename</bitmap>
|
||||||
strings += self.FindStringsInNode(child)
|
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():
|
def main(args):
|
||||||
XmlResApp().main(sys.argv[1:])
|
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__":
|
if __name__ == "__main__":
|
||||||
main()
|
main(sys.argv[1:])
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user