2 # Purpose: XRC editor, main module
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
9 xrced -- Simple resource editor for XRC format used by wxWidgets/wxPython
14 xrced [ -h ] [ -v ] [ XRC-file ]
18 -h output short usage info and exit
20 -v output version info and exit
24 import os
, sys
, getopt
, re
, traceback
, tempfile
, shutil
, cPickle
25 from xml
.parsers
import expat
28 from tree
import * # imports xxx which imports params
31 from params
import genericStyles
32 # Cleanup recursive import sideeffects, otherwise we can't create undoMan
34 undo
.ParamPage
= ParamPage
35 undoMan
= g
.undoMan
= UndoManager()
37 # Set application path for loading resources
38 if __name__
== '__main__':
39 basePath
= os
.path
.dirname(sys
.argv
[0])
41 basePath
= os
.path
.dirname(__file__
)
43 # Remember system path
46 # 1 adds CMD command to Help menu
50 <HTML><H2>Welcome to XRC<font color="blue">ed</font></H2><H3><font color="green">DON'T PANIC :)</font></H3>
51 Read this note before clicking on anything!<P>
52 To start select tree root, then popup menu with your right mouse button,
53 select "Append Child", and then any command.<P>
54 Or just press one of the buttons on the tools palette.<P>
55 Enter XML ID, change properties, create children.<P>
56 To test your interface select Test command (View menu).<P>
57 Consult README.txt file for the details.</HTML>
60 defaultIDs
= {xxxPanel
:'PANEL', xxxDialog
:'DIALOG', xxxFrame
:'FRAME',
61 xxxMenuBar
:'MENUBAR', xxxMenu
:'MENU', xxxToolBar
:'TOOLBAR',
62 xxxWizard
:'WIZARD', xxxBitmap
:'BITMAP', xxxIcon
:'ICON'}
64 defaultName
= 'UNTITLED.xrc'
66 ################################################################################
68 # ScrolledMessageDialog - modified from wxPython lib to set fixed-width font
69 class ScrolledMessageDialog(wx
.Dialog
):
70 def __init__(self
, parent
, msg
, caption
, pos
= wx
.DefaultPosition
, size
= (500,300)):
71 from wx
.lib
.layoutf
import Layoutf
72 wx
.Dialog
.__init
__(self
, parent
, -1, caption
, pos
, size
)
73 text
= wx
.TextCtrl(self
, -1, msg
, wx
.DefaultPosition
,
74 wx
.DefaultSize
, wx
.TE_MULTILINE | wx
.TE_READONLY
)
75 text
.SetFont(g
.modernFont())
76 dc
= wx
.WindowDC(text
)
77 w
, h
= dc
.GetFullTextExtent(' ', g
.modernFont())[:2]
78 ok
= wx
.Button(self
, wx
.ID_OK
, "OK")
80 text
.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self
,ok
)))
81 text
.SetSize((w
* 80 + 30, h
* 40))
82 text
.ShowPosition(1) # scroll to the first line
83 ok
.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!35', (self
,)))
84 self
.SetAutoLayout(True)
86 self
.CenterOnScreen(wx
.BOTH
)
88 ################################################################################
90 # Event handler for using during location
91 class Locator(wx
.EvtHandler
):
92 def ProcessEvent(self
, evt
):
95 class Frame(wx
.Frame
):
96 def __init__(self
, pos
, size
):
97 wx
.Frame
.__init
__(self
, None, -1, '', pos
, size
)
99 frame
= g
.frame
= self
100 bar
= self
.CreateStatusBar(2)
101 bar
.SetStatusWidths([-1, 40])
102 self
.SetIcon(images
.getIconIcon())
107 # Load our own resources
108 self
.res
= xrc
.EmptyXmlResource()
109 # !!! Blocking of assert failure occurring in older unicode builds
111 quietlog
= wx
.LogNull()
112 self
.res
.Load(os
.path
.join(basePath
, 'xrced.xrc'))
113 except wx
._core
.PyAssertionError
:
114 print 'PyAssertionError was ignored'
117 menuBar
= wx
.MenuBar()
120 menu
.Append(wx
.ID_NEW
, '&New\tCtrl-N', 'New file')
121 menu
.AppendSeparator()
122 menu
.Append(wx
.ID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
124 self
.recentMenu
= wx
.Menu()
125 g
.fileHistory
.UseMenu(self
.recentMenu
)
126 g
.fileHistory
.AddFilesToMenu()
127 self
.Bind(wx
.EVT_MENU
, self
.OnRecentFile
, id=wx
.ID_FILE1
, id2
=wx
.ID_FILE9
)
128 menu
.AppendMenu(-1, 'Open &Recent', self
.recentMenu
, 'Open a recent file')
130 menu
.AppendSeparator()
131 menu
.Append(wx
.ID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
132 menu
.Append(wx
.ID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
133 self
.ID_GENERATE_PYTHON
= wx
.NewId()
134 menu
.Append(self
.ID_GENERATE_PYTHON
, '&Generate Python...',
135 'Generate a Python module that uses this XRC')
136 menu
.AppendSeparator()
137 self
.ID_PREFS
= wx
.NewId()
138 menu
.Append(self
.ID_PREFS
, 'Preferences...', 'Change XRCed settings')
139 menu
.AppendSeparator()
140 menu
.Append(wx
.ID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
142 menuBar
.Append(menu
, '&File')
145 menu
.Append(wx
.ID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
146 menu
.Append(wx
.ID_REDO
, '&Redo\tCtrl-Y', 'Redo')
147 menu
.AppendSeparator()
148 menu
.Append(wx
.ID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
149 menu
.Append(wx
.ID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
150 menu
.Append(wx
.ID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
151 self
.ID_DELETE
= wx
.NewId()
152 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
153 menu
.AppendSeparator()
154 self
.ID_LOCATE
= wx
.NewId()
155 self
.ID_TOOL_LOCATE
= wx
.NewId()
156 self
.ID_TOOL_PASTE
= wx
.NewId()
157 menu
.Append(self
.ID_LOCATE
, '&Locate\tCtrl-L', 'Locate control in test window and select it')
158 menuBar
.Append(menu
, '&Edit')
161 self
.ID_EMBED_PANEL
= wx
.NewId()
162 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
163 'Toggle embedding properties panel in the main window', True)
164 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
165 self
.ID_SHOW_TOOLS
= wx
.NewId()
166 menu
.Append(self
.ID_SHOW_TOOLS
, 'Show &Tools', 'Toggle tools', True)
167 menu
.Check(self
.ID_SHOW_TOOLS
, conf
.showTools
)
168 menu
.AppendSeparator()
169 self
.ID_TEST
= wx
.NewId()
170 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Show test window')
171 self
.ID_REFRESH
= wx
.NewId()
172 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
173 self
.ID_AUTO_REFRESH
= wx
.NewId()
174 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tAlt-A',
175 'Toggle auto-refresh mode', True)
176 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
177 self
.ID_TEST_HIDE
= wx
.NewId()
178 menu
.Append(self
.ID_TEST_HIDE
, '&Hide\tF6', 'Close test window')
179 menuBar
.Append(menu
, '&View')
182 self
.ID_MOVEUP
= wx
.NewId()
183 menu
.Append(self
.ID_MOVEUP
, '&Up', 'Move before previous sibling')
184 self
.ID_MOVEDOWN
= wx
.NewId()
185 menu
.Append(self
.ID_MOVEDOWN
, '&Down', 'Move after next sibling')
186 self
.ID_MOVELEFT
= wx
.NewId()
187 menu
.Append(self
.ID_MOVELEFT
, '&Make sibling', 'Make sibling of parent')
188 self
.ID_MOVERIGHT
= wx
.NewId()
189 menu
.Append(self
.ID_MOVERIGHT
, '&Make child', 'Make child of previous sibling')
190 menuBar
.Append(menu
, '&Move')
193 menu
.Append(wx
.ID_ABOUT
, '&About...', 'About XCRed')
194 self
.ID_README
= wx
.NewId()
195 menu
.Append(self
.ID_README
, '&Readme...\tF1', 'View the README file')
197 self
.ID_DEBUG_CMD
= wx
.NewId()
198 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
199 wx
.EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
200 menuBar
.Append(menu
, '&Help')
202 self
.menuBar
= menuBar
203 self
.SetMenuBar(menuBar
)
206 tb
= self
.CreateToolBar(wx
.TB_HORIZONTAL | wx
.NO_BORDER | wx
.TB_FLAT
)
207 tb
.SetToolBitmapSize((24,24))
208 new_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
)
209 open_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
)
210 save_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
)
211 undo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
)
212 redo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
)
213 cut_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
)
214 copy_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
)
215 paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
)
217 tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file')
218 tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file')
219 tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file')
220 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
221 tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo')
222 tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo')
223 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
224 tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut')
225 tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy')
226 tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste')
227 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
228 tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
,
229 images
.getLocateBitmap(), #images.getLocateArmedBitmap(),
230 'Locate', 'Locate control in test window and select it', True)
231 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
232 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
233 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
234 'Refresh', 'Refresh view')
235 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
236 'Auto-refresh', 'Toggle auto-refresh mode', True)
237 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
238 tb
.AddSimpleTool(self
.ID_MOVEUP
, images
.getToolMoveUpBitmap(),
239 'Up', 'Move before previous sibling')
240 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, images
.getToolMoveDownBitmap(),
241 'Down', 'Move after next sibling')
242 tb
.AddSimpleTool(self
.ID_MOVELEFT
, images
.getToolMoveLeftBitmap(),
243 'Make Sibling', 'Make sibling of parent')
244 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, images
.getToolMoveRightBitmap(),
245 'Make Child', 'Make child of previous sibling')
246 # if wx.Platform == '__WXGTK__':
247 # tb.AddSeparator() # otherwise auto-refresh sticks in status line
248 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
252 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
255 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
)
256 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
)
257 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
)
258 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
)
259 wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
)
260 wx
.EVT_MENU(self
, self
.ID_PREFS
, self
.OnPrefs
)
261 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
263 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
264 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
265 wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
)
266 wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
)
267 wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
)
268 wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
)
269 wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
)
270 wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
)
271 wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
)
273 wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
274 wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
)
275 wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
276 wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
277 wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
278 wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
)
280 wx
.EVT_MENU(self
, self
.ID_MOVEUP
, self
.OnMoveUp
)
281 wx
.EVT_MENU(self
, self
.ID_MOVEDOWN
, self
.OnMoveDown
)
282 wx
.EVT_MENU(self
, self
.ID_MOVELEFT
, self
.OnMoveLeft
)
283 wx
.EVT_MENU(self
, self
.ID_MOVERIGHT
, self
.OnMoveRight
)
285 wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
)
286 wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
289 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
)
290 wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
)
291 wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
)
292 wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
)
293 wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
)
294 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
)
295 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
)
296 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
)
297 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
)
298 wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
299 wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
300 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
303 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
304 #sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
305 # Horizontal sizer for toolbar and splitter
306 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
307 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
308 self
.splitter
= splitter
309 splitter
.SetMinimumPaneSize(100)
312 g
.tree
= tree
= XML_Tree(splitter
, -1)
314 # Init pull-down menu data
316 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
318 # Vertical toolbar for GUI buttons
319 g
.tools
= tools
= Tools(self
)
320 tools
.Show(conf
.showTools
)
321 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
323 tree
.RegisterKeyEvents()
325 # Miniframe for split mode
326 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
327 (conf
.panelX
, conf
.panelY
),
328 (conf
.panelWidth
, conf
.panelHeight
))
329 self
.miniFrame
= miniFrame
330 sizer2
= wx
.BoxSizer()
331 miniFrame
.SetAutoLayout(True)
332 miniFrame
.SetSizer(sizer2
)
333 wx
.EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
)
334 # Create panel for parameters
337 panel
= Panel(splitter
)
338 # Set plitter windows
339 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
341 panel
= Panel(miniFrame
)
342 sizer2
.Add(panel
, 1, wx
.EXPAND
)
344 splitter
.Initialize(tree
)
345 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
346 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
347 self
.SetAutoLayout(True)
351 wx
.EVT_IDLE(self
, self
.OnIdle
)
352 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
353 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
354 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
355 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
357 def OnRecentFile(self
,evt
):
358 # open recently used file
359 if not self
.AskSave(): return
362 # get the pathname based on the menu ID
363 fileNum
= evt
.GetId() - wx
.ID_FILE1
364 path
= g
.fileHistory
.GetHistoryFile(fileNum
)
367 self
.SetStatusText('Data loaded')
368 # add it back to the history so it will be moved up the list
369 self
.SaveRecent(path
)
371 self
.SetStatusText('Failed')
375 def OnNew(self
, evt
):
376 if not self
.AskSave(): return
379 def OnOpen(self
, evt
):
380 if not self
.AskSave(): return
381 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
382 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
383 if dlg
.ShowModal() == wx
.ID_OK
:
385 self
.SetStatusText('Loading...')
389 self
.SetStatusText('Data loaded')
390 self
.SaveRecent(path
)
392 self
.SetStatusText('Failed')
397 def OnSaveOrSaveAs(self
, evt
):
398 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
399 if self
.dataFile
: name
= ''
400 else: name
= defaultName
401 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
402 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
403 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
404 if dlg
.ShowModal() == wx
.ID_OK
:
406 if isinstance(path
, unicode):
407 path
= path
.encode(sys
.getfilesystemencoding())
414 # if we already have a localconf then it needs to be
415 # copied to a new config with the new name
417 nc
= self
.CreateLocalConf(path
)
418 flag
, key
, idx
= lc
.GetFirstEntry()
420 nc
.Write(key
, lc
.Read(key
))
421 flag
, key
, idx
= lc
.GetNextEntry(idx
)
424 # otherwise create a new one
425 conf
.localconf
= self
.CreateLocalConf(path
)
428 self
.SetStatusText('Saving...')
432 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
434 self
.Save(tmpName
) # save temporary file first
435 shutil
.move(tmpName
, path
)
437 self
.SetModified(False)
438 if conf
.localconf
.ReadBool("autogenerate", False):
439 pypath
= conf
.localconf
.Read("filename")
440 embed
= conf
.localconf
.ReadBool("embedResource", False)
441 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
442 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
444 self
.SetStatusText('Data saved')
445 self
.SaveRecent(path
)
447 self
.SetStatusText('Failed')
451 def SaveRecent(self
,path
):
452 # append to recently used files
453 g
.fileHistory
.AddFileToHistory(path
)
455 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
457 import wx
.tools
.pywxrc
458 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
459 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
462 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
463 wx
.LogError('Error generating python code : %s' % pypath
)
467 def OnGeneratePython(self
, evt
):
468 if self
.modified
or not conf
.localconf
:
469 wx
.MessageBox("Save the XRC file first!", "Error")
472 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
476 def OnPrefs(self
, evt
):
477 dlg
= PrefsDialog(self
)
478 if dlg
.ShowModal() == wx
.ID_OK
:
479 # Fetch new preferences
480 for id,cdp
in dlg
.checkControls
.items():
482 if dlg
.FindWindowById(id).IsChecked():
483 d
[p
] = str(c
.GetValue())
484 elif p
in d
: del d
[p
]
485 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
488 def OnExit(self
, evt
):
491 def OnUndo(self
, evt
):
492 # Extra check to not mess with idle updating
493 if undoMan
.CanUndo():
495 g
.panel
.SetModified(False)
496 if not undoMan
.CanUndo():
497 self
.SetModified(False)
499 def OnRedo(self
, evt
):
500 if undoMan
.CanRedo():
502 self
.SetModified(True)
504 def OnCopy(self
, evt
):
505 selected
= tree
.selection
506 if not selected
: return # key pressed event
507 xxx
= tree
.GetPyData(selected
)
508 if wx
.TheClipboard
.Open():
510 data
= wx
.CustomDataObject('XRCED')
511 # Set encoding in header
513 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
515 data
= wx
.CustomDataObject('XRCED_node')
517 data
.SetData(cPickle
.dumps(s
))
518 wx
.TheClipboard
.SetData(data
)
519 wx
.TheClipboard
.Close()
520 self
.SetStatusText('Copied')
522 wx
.MessageBox("Unable to open the clipboard", "Error")
524 def OnPaste(self
, evt
):
525 selected
= tree
.selection
526 if not selected
: return # key pressed event
527 # For pasting with Ctrl pressed
529 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
530 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
531 if g
.tree
.ctrl
: appendChild
= False
532 else: appendChild
= not tree
.NeedInsert(selected
)
533 else: appendChild
= not tree
.NeedInsert(selected
)
534 xxx
= tree
.GetPyData(selected
)
536 # If has next item, insert, else append to parent
537 nextItem
= tree
.GetNextSibling(selected
)
538 parentLeaf
= tree
.GetItemParent(selected
)
539 # Expanded container (must have children)
540 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
541 # Insert as first child
542 nextItem
= tree
.GetFirstChild(selected
)[0]
543 parentLeaf
= selected
545 # No children or unexpanded item - appendChild stays True
546 nextItem
= wx
.TreeItemId() # no next item
547 parentLeaf
= selected
548 parent
= tree
.GetPyData(parentLeaf
).treeObject()
550 # Create a copy of clipboard pickled element
551 success
= success_node
= False
552 if wx
.TheClipboard
.Open():
554 data
= wx
.CustomDataObject('XRCED')
555 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
557 success
= wx
.TheClipboard
.GetData(data
)
559 # there is a problem if XRCED_node is in clipboard
560 # but previous SetData was for XRCED
562 if not success
: # try other format
563 data
= wx
.CustomDataObject('XRCED_node')
564 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
565 success_node
= wx
.TheClipboard
.GetData(data
)
567 wx
.TheClipboard
.Close()
569 if not success
and not success_node
:
571 "There is no data in the clipboard in the required format",
575 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
577 elem
= minidom
.parseString(xml
).childNodes
[0]
579 elem
= g
.tree
.dom
.createComment(xml
)
581 # Tempopary xxx object to test things
582 xxx
= MakeXXXFromDOM(parent
, elem
)
584 # Check compatibility
585 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
587 # Check parent and child relationships.
588 # If parent is sizer or notebook, child is of wrong class or
589 # parent is normal window, child is child container then detach child.
590 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
591 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
592 if isChildContainer
and \
593 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
594 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
595 not (parent
.isSizer
or parentIsBook
)):
596 elem
.removeChild(xxx
.child
.node
) # detach child
597 elem
.unlink() # delete child container
598 elem
= xxx
.child
.node
# replace
599 # This may help garbage collection
600 xxx
.child
.parent
= None
601 isChildContainer
= False
602 # Parent is sizer or notebook, child is not child container
603 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
604 # Create sizer item element
605 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
606 sizerItemElem
.appendChild(elem
)
608 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
609 pageElem
= MakeEmptyDOM('notebookpage')
610 pageElem
.appendChild(elem
)
612 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
613 pageElem
= MakeEmptyDOM('choicebookpage')
614 pageElem
.appendChild(elem
)
616 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
617 pageElem
= MakeEmptyDOM('listbookpage')
618 pageElem
.appendChild(elem
)
620 # Insert new node, register undo
621 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
622 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
623 # Scroll to show new item (!!! redundant?)
624 tree
.EnsureVisible(newItem
)
625 tree
.SelectItem(newItem
)
626 if not tree
.IsVisible(newItem
):
627 tree
.ScrollTo(newItem
)
630 if g
.testWin
and tree
.IsHighlatable(newItem
):
632 tree
.needUpdate
= True
633 tree
.pendingHighLight
= newItem
635 tree
.pendingHighLight
= None
637 self
.SetStatusText('Pasted')
640 def ItemsAreCompatible(self
, parent
, child
):
641 # Check compatibility
643 # Comments are always compatible
644 if child
.__class
__ == xxxComment
:
647 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
649 if parent
.__class
__ != xxxMainNode
: error
= True
650 elif child
.__class
__ == xxxMenuBar
:
651 # Menubar can be put in frame or dialog
652 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
653 elif child
.__class
__ == xxxToolBar
:
654 # Toolbar can be top-level of child of panel or frame
655 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
656 not parent
.isSizer
: error
= True
657 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
659 elif child
.__class
__ == xxxSpacer
:
660 if not parent
.isSizer
: error
= True
661 elif child
.__class
__ == xxxSeparator
:
662 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
663 elif child
.__class
__ == xxxTool
:
664 if parent
.__class
__ != xxxToolBar
: error
= True
665 elif child
.__class
__ == xxxMenu
:
666 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
667 elif child
.__class
__ == xxxMenuItem
:
668 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
669 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
671 else: # normal controls can be almost anywhere
672 if parent
.__class
__ == xxxMainNode
or \
673 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
675 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
676 else: parentClass
= parent
.className
677 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
678 (parentClass
, child
.className
))
682 def OnMoveUp(self
, evt
):
683 selected
= tree
.selection
684 if not selected
: return
686 index
= tree
.ItemIndex(selected
)
687 if index
== 0: return # No previous sibling found
689 # Remove highlight, update testWin
690 if g
.testWin
and g
.testWin
.highLight
:
691 g
.testWin
.highLight
.Remove()
692 tree
.needUpdate
= True
695 self
.lastOp
= 'MOVEUP'
696 status
= 'Moved before previous sibling'
702 parent
= tree
.GetItemParent(selected
)
703 elem
= tree
.RemoveLeaf(selected
)
704 nextItem
= tree
.GetFirstChild(parent
)[0]
705 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
706 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
707 newIndex
= tree
.ItemIndex(selected
)
708 tree
.SelectItem(selected
)
710 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
713 self
.SetStatusText(status
)
717 def OnMoveDown(self
, evt
):
718 selected
= tree
.selection
719 if not selected
: return
721 index
= tree
.ItemIndex(selected
)
722 next
= tree
.GetNextSibling(selected
)
725 # Remove highlight, update testWin
726 if g
.testWin
and g
.testWin
.highLight
:
727 g
.testWin
.highLight
.Remove()
728 tree
.needUpdate
= True
731 self
.lastOp
= 'MOVEDOWN'
732 status
= 'Moved after next sibling'
738 parent
= tree
.GetItemParent(selected
)
739 elem
= tree
.RemoveLeaf(selected
)
740 nextItem
= tree
.GetFirstChild(parent
)[0]
741 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
742 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
743 newIndex
= tree
.ItemIndex(selected
)
744 tree
.SelectItem(selected
)
746 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
749 self
.SetStatusText(status
)
753 def OnMoveLeft(self
, evt
):
754 selected
= tree
.selection
755 if not selected
: return
757 oldParent
= tree
.GetItemParent(selected
)
758 if not oldParent
: return
759 pparent
= tree
.GetItemParent(oldParent
)
760 if not pparent
: return
762 # Check compatibility
763 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
765 # Remove highlight, update testWin
766 if g
.testWin
and g
.testWin
.highLight
:
767 g
.testWin
.highLight
.Remove()
768 tree
.needUpdate
= True
771 self
.lastOp
= 'MOVELEFT'
772 status
= 'Made next sibling of parent'
774 oldIndex
= tree
.ItemIndex(selected
)
775 elem
= tree
.RemoveLeaf(selected
)
776 nextItem
= tree
.GetFirstChild(pparent
)[0]
777 parentIndex
= tree
.ItemIndex(oldParent
)
778 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
780 # Check parent and child relationships.
781 # If parent is sizer or notebook, child is of wrong class or
782 # parent is normal window, child is child container then detach child.
783 parent
= tree
.GetPyData(pparent
).treeObject()
784 xxx
= MakeXXXFromDOM(parent
, elem
)
785 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
786 if isChildContainer
and \
787 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
788 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
789 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
790 elem
.removeChild(xxx
.child
.node
) # detach child
791 elem
.unlink() # delete child container
792 elem
= xxx
.child
.node
# replace
793 # This may help garbage collection
794 xxx
.child
.parent
= None
795 isChildContainer
= False
796 # Parent is sizer or notebook, child is not child container
797 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
798 # Create sizer item element
799 sizerItemElem
= MakeEmptyDOM('sizeritem')
800 sizerItemElem
.appendChild(elem
)
802 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
803 pageElem
= MakeEmptyDOM('notebookpage')
804 pageElem
.appendChild(elem
)
807 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
808 newIndex
= tree
.ItemIndex(selected
)
810 tree
.SelectItem(selected
)
812 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
815 self
.SetStatusText(status
)
817 def OnMoveRight(self
, evt
):
818 selected
= tree
.selection
819 if not selected
: return
821 oldParent
= tree
.GetItemParent(selected
)
822 if not oldParent
: return
824 newParent
= tree
.GetPrevSibling(selected
)
825 if not newParent
: return
827 parent
= tree
.GetPyData(newParent
).treeObject()
829 # Check compatibility
830 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
832 # Remove highlight, update testWin
833 if g
.testWin
and g
.testWin
.highLight
:
834 g
.testWin
.highLight
.Remove()
835 tree
.needUpdate
= True
838 self
.lastOp
= 'MOVERIGHT'
839 status
= 'Made last child of previous sibling'
841 oldIndex
= tree
.ItemIndex(selected
)
842 elem
= tree
.RemoveLeaf(selected
)
844 # Check parent and child relationships.
845 # If parent is sizer or notebook, child is of wrong class or
846 # parent is normal window, child is child container then detach child.
847 xxx
= MakeXXXFromDOM(parent
, elem
)
848 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
849 if isChildContainer
and \
850 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
851 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
852 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
853 elem
.removeChild(xxx
.child
.node
) # detach child
854 elem
.unlink() # delete child container
855 elem
= xxx
.child
.node
# replace
856 # This may help garbage collection
857 xxx
.child
.parent
= None
858 isChildContainer
= False
859 # Parent is sizer or notebook, child is not child container
860 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
861 # Create sizer item element
862 sizerItemElem
= MakeEmptyDOM('sizeritem')
863 sizerItemElem
.appendChild(elem
)
865 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
866 pageElem
= MakeEmptyDOM('notebookpage')
867 pageElem
.appendChild(elem
)
870 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
872 newIndex
= tree
.ItemIndex(selected
)
874 tree
.SelectItem(selected
)
876 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
879 self
.SetStatusText(status
)
881 def OnCutDelete(self
, evt
):
882 selected
= tree
.selection
883 if not selected
: return # key pressed event
885 if evt
.GetId() == wx
.ID_CUT
:
887 status
= 'Removed to clipboard'
889 self
.lastOp
= 'DELETE'
893 # If deleting top-level item, delete testWin
894 if selected
== g
.testWin
.item
:
898 # Remove highlight, update testWin
899 if g
.testWin
.highLight
:
900 g
.testWin
.highLight
.Remove()
901 tree
.needUpdate
= True
904 index
= tree
.ItemFullIndex(selected
)
905 xxx
= tree
.GetPyData(selected
)
906 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
908 elem
= tree
.RemoveLeaf(selected
)
909 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
910 if evt
.GetId() == wx
.ID_CUT
:
911 if wx
.TheClipboard
.Open():
913 data
= wx
.CustomDataObject('XRCED')
915 s
= elem
.toxml(encoding
=expat
.native_encoding
)
917 data
= wx
.CustomDataObject('XRCED_node')
919 data
.SetData(cPickle
.dumps(s
))
920 wx
.TheClipboard
.SetData(data
)
921 wx
.TheClipboard
.Close()
923 wx
.MessageBox("Unable to open the clipboard", "Error")
924 tree
.pendingHighLight
= None
928 self
.SetStatusText(status
)
930 def OnSubclass(self
, evt
):
931 selected
= tree
.selection
932 xxx
= tree
.GetPyData(selected
).treeObject()
934 subclass
= xxx
.subclass
935 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
936 if dlg
.ShowModal() == wx
.ID_OK
:
937 subclass
= dlg
.GetValue()
939 elem
.setAttribute('subclass', subclass
)
940 elif elem
.hasAttribute('subclass'):
941 elem
.removeAttribute('subclass')
943 xxx
.subclass
= elem
.getAttribute('subclass')
944 tree
.SetItemText(selected
, xxx
.treeName())
945 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
948 def OnEmbedPanel(self
, evt
):
949 conf
.embedPanel
= evt
.IsChecked()
951 # Remember last dimentions
952 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
953 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
954 size
= self
.GetSize()
955 pos
= self
.GetPosition()
956 sizePanel
= panel
.GetSize()
957 panel
.Reparent(self
.splitter
)
958 self
.miniFrame
.GetSizer().Remove(panel
)
960 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
961 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
962 self
.miniFrame
.Show(False)
964 conf
.sashPos
= self
.splitter
.GetSashPosition()
965 pos
= self
.GetPosition()
966 size
= self
.GetSize()
967 sizePanel
= panel
.GetSize()
968 self
.splitter
.Unsplit(panel
)
969 sizer
= self
.miniFrame
.GetSizer()
970 panel
.Reparent(self
.miniFrame
)
972 sizer
.Add(panel
, 1, wx
.EXPAND
)
973 self
.miniFrame
.Show(True)
974 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
975 conf
.panelWidth
, conf
.panelHeight
)
976 self
.miniFrame
.Layout()
978 self
.SetDimensions(pos
.x
, pos
.y
,
979 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
981 def OnShowTools(self
, evt
):
982 conf
.showTools
= evt
.IsChecked()
983 g
.tools
.Show(conf
.showTools
)
985 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
987 self
.toolsSizer
.Remove(g
.tools
)
988 self
.toolsSizer
.Layout()
990 def OnTest(self
, evt
):
991 if not tree
.selection
: return # key pressed event
992 tree
.ShowTestWindow(tree
.selection
)
994 def OnTestHide(self
, evt
):
995 tree
.CloseTestWindow()
997 # Find object by relative position
998 def FindObject(self
, item
, obj
):
999 # We simply perform depth-first traversal, sinse it's too much
1000 # hassle to deal with all sizer/window combinations
1001 w
= tree
.FindNodeObject(item
)
1002 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
1004 if tree
.ItemHasChildren(item
):
1005 child
= tree
.GetFirstChild(item
)[0]
1007 found
= self
.FindObject(child
, obj
)
1008 if found
: return found
1009 child
= tree
.GetNextSibling(child
)
1012 # Click event after locate activated
1013 def OnTestWinLeftDown(self
, evt
):
1014 # Restore normal event processing
1015 self
.SetHandler(g
.testWin
)
1016 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1017 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
1019 tree
.EnsureVisible(item
)
1020 tree
.SelectItem(item
)
1021 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1023 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1025 self
.SetStatusText('Locate failed!')
1027 def SetHandler(self
, w
, h
=None):
1029 w
.SetEventHandler(h
)
1030 w
.SetCursor(wx
.CROSS_CURSOR
)
1032 w
.SetEventHandler(w
)
1033 w
.SetCursor(wx
.NullCursor
)
1034 for ch
in w
.GetChildren():
1035 self
.SetHandler(ch
, h
)
1037 def OnLocate(self
, evt
):
1039 if evt
.GetId() == self
.ID_LOCATE
or \
1040 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1041 self
.SetHandler(g
.testWin
, g
.testWin
)
1042 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1043 if evt
.GetId() == self
.ID_LOCATE
:
1044 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1045 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1046 self
.SetHandler(g
.testWin
, None)
1047 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1048 self
.SetStatusText('Click somewhere in your test window now')
1050 def OnRefresh(self
, evt
):
1051 # If modified, apply first
1052 selection
= tree
.selection
1054 xxx
= tree
.GetPyData(selection
)
1055 if xxx
and panel
.IsModified():
1056 tree
.Apply(xxx
, selection
)
1059 tree
.CreateTestWin(g
.testWin
.item
)
1060 panel
.modified
= False
1061 tree
.needUpdate
= False
1063 def OnAutoRefresh(self
, evt
):
1064 conf
.autoRefresh
= evt
.IsChecked()
1065 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1066 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1068 def OnAbout(self
, evt
):
1072 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1073 Homepage: http://xrced.sourceforge.net\
1075 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1079 def OnReadme(self
, evt
):
1080 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1081 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1085 # Simple emulation of python command line
1086 def OnDebugCMD(self
, evt
):
1089 exec raw_input('C:\> ')
1094 (etype
, value
, tb
) =sys
.exc_info()
1095 tblist
=traceback
.extract_tb(tb
)[1:]
1096 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1097 +traceback
.format_list(tblist
))
1100 def OnCreate(self
, evt
):
1101 # Ignore fake events generated while dragging
1103 g
.tools
.drag
= False
1105 selected
= tree
.selection
1106 if tree
.ctrl
: appendChild
= False
1107 else: appendChild
= not tree
.NeedInsert(selected
)
1108 xxx
= tree
.GetPyData(selected
)
1112 # If has previous item, insert after it, else append to parent
1114 parentLeaf
= tree
.GetItemParent(selected
)
1116 # If has next item, insert, else append to parent
1117 nextItem
= tree
.GetNextSibling(selected
)
1118 parentLeaf
= tree
.GetItemParent(selected
)
1119 # Expanded container (must have children)
1120 elif tree
.shift
and tree
.IsExpanded(selected
) \
1121 and tree
.GetChildrenCount(selected
, False):
1122 nextItem
= tree
.GetFirstChild(selected
)[0]
1123 parentLeaf
= selected
1125 nextItem
= wx
.TreeItemId()
1126 parentLeaf
= selected
1127 parent
= tree
.GetPyData(parentLeaf
)
1128 if parent
.hasChild
: parent
= parent
.child
1130 self
.CreateXXX(parent
, parentLeaf
, nextItem
, evt
.GetId())
1132 # Actual method to create object and add to XML and wx trees
1133 def CreateXXX(self
, parent
, parentLeaf
, nextItem
, id):
1134 selected
= tree
.selection
1135 # Create object_ref?
1136 if id == ID_NEW
.REF
:
1137 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1139 xxx
= MakeEmptyRefXXX(parent
, ref
)
1140 elif id == ID_NEW
.COMMENT
:
1141 xxx
= MakeEmptyCommentXXX(parent
)
1143 # Create empty element
1144 if id >= ID_NEW
.CUSTOM
:
1145 className
= pullDownMenu
.customMap
[id]
1147 className
= pullDownMenu
.createMap
[id]
1148 xxx
= MakeEmptyXXX(parent
, className
)
1150 # Insert new node, register undo
1151 if xxx
.isElement
: # true object
1152 # Set default name for top-level windows
1153 if parent
.__class
__ == xxxMainNode
:
1154 cl
= xxx
.treeObject().__class
__
1155 frame
.maxIDs
[cl
] += 1
1156 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1157 # And for some other standard controls
1158 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1159 # ... we can even set automatically tree name
1160 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[id][0])
1161 obj
= xxx
.treeObject()
1163 elem
= g
.tree
.dom
.createElement('label')
1164 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[id][1]))
1165 obj
.params
['label'] = xxxParam(elem
)
1166 xxx
.treeObject().node
.appendChild(elem
)
1167 # Else, set label if exists to class name
1168 elif 'label' in xxx
.treeObject().allParams
:
1170 if label
[:2] == 'wx': label
= label
[2:]
1171 xxx
.treeObject().set('label', label
.upper())
1172 # For comment nodes, simply add node
1173 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1174 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1175 tree
.EnsureVisible(newItem
)
1176 tree
.SelectItem(newItem
)
1177 if not tree
.IsVisible(newItem
):
1178 tree
.ScrollTo(newItem
)
1181 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1182 if conf
.autoRefresh
:
1183 tree
.needUpdate
= True
1184 tree
.pendingHighLight
= newItem
1186 tree
.pendingHighLight
= None
1188 if not xxx
.isElement
:
1189 tree
.EditLabel(newItem
)
1193 # Replace one object with another
1194 def OnReplace(self
, evt
):
1195 selected
= tree
.selection
1196 xxx
= tree
.GetPyData(selected
).treeObject()
1198 parent
= elem
.parentNode
1199 undoMan
.RegisterUndo(UndoReplace(selected
))
1201 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1203 # Create temporary empty node (with default values)
1204 dummy
= MakeEmptyDOM(className
)
1205 if className
== 'spacer' and xxx
.className
!= 'spacer':
1207 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1208 klass
= xxxSizerItem
1210 klass
= xxxDict
[className
]
1211 # Remove non-compatible children
1212 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1213 tree
.DeleteChildren(selected
)
1214 nodes
= elem
.childNodes
[:]
1217 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1221 if not klass
.hasChildren
: remove
= True
1222 elif tag
not in klass
.allParams
and \
1223 (not klass
.hasStyle
or tag
not in klass
.styles
):
1228 elem
.removeChild(node
)
1231 # Remove sizeritem child if spacer
1232 if className
== 'spacer' and xxx
.className
!= 'spacer':
1233 sizeritem
= elem
.parentNode
1234 assert sizeritem
.getAttribute('class') == 'sizeritem'
1235 sizeritem
.removeChild(elem
)
1238 tree
.GetPyData(selected
).hasChild
= False
1239 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1240 # Create sizeritem element
1241 assert xxx
.parent
.isSizer
1242 elem
.setAttribute('class', 'sizeritem')
1243 node
= MakeEmptyDOM(className
)
1244 elem
.appendChild(node
)
1245 # Replace to point to new object
1246 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1248 tree
.SetPyData(selected
, xxx
)
1251 # Copy parameters present in dummy but not in elem
1252 for node
in dummy
.childNodes
:
1253 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1257 elem
.setAttribute('class', className
)
1258 if elem
.hasAttribute('subclass'):
1259 elem
.removeAttribute('subclass') # clear subclassing
1260 # Re-create xxx element
1261 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1262 # Remove incompatible style flags
1263 if 'style' in xxx
.params
:
1264 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1265 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1266 if newStyles
!= styles
:
1268 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1271 xxx
.params
['style'].update(value
)
1273 # Update parent in child objects
1274 if tree
.ItemHasChildren(selected
):
1275 i
, cookie
= tree
.GetFirstChild(selected
)
1277 x
= tree
.GetPyData(i
)
1279 if x
.hasChild
: x
.child
.parent
= xxx
1280 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1283 if tree
.GetPyData(selected
).hasChild
: # child container
1284 container
= tree
.GetPyData(selected
)
1285 container
.resetChild(xxx
)
1288 tree
.SetPyData(selected
, xxx
)
1289 tree
.SetItemText(selected
, xxx
.treeName())
1290 tree
.SetItemImage(selected
, xxx
.treeImage())
1292 # Set default name for top-level windows
1293 if parent
.__class
__ == xxxMainNode
:
1294 cl
= xxx
.treeObject().__class
__
1295 frame
.maxIDs
[cl
] += 1
1296 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1299 g
.panel
.SetData(xxx
)
1303 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1305 if g
.testWin
and tree
.IsHighlatable(selected
):
1306 if conf
.autoRefresh
:
1307 tree
.needUpdate
= True
1308 tree
.pendingHighLight
= selected
1310 tree
.pendingHighLight
= None
1314 # Expand/collapse subtree
1315 def OnExpand(self
, evt
):
1316 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1317 else: tree
.ExpandAll(tree
.root
)
1318 def OnCollapse(self
, evt
):
1319 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1320 else: tree
.CollapseAll(tree
.root
)
1322 def OnPullDownHighlight(self
, evt
):
1323 menuId
= evt
.GetMenuId()
1325 menu
= evt
.GetEventObject()
1326 help = menu
.GetHelpString(menuId
)
1327 self
.SetStatusText(help)
1329 self
.SetStatusText('')
1331 def OnUpdateUI(self
, evt
):
1332 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1333 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1334 elif evt
.GetId() == wx
.ID_SAVE
:
1335 evt
.Enable(self
.modified
)
1336 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1337 evt
.Enable(tree
.selection
is not None)
1338 elif evt
.GetId() == self
.ID_TEST
:
1339 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1340 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
]:
1341 evt
.Enable(g
.testWin
is not None)
1342 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1343 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1345 def OnIdle(self
, evt
):
1346 if self
.inIdle
: return # Recursive call protection
1350 if conf
.autoRefresh
:
1352 #self.SetStatusText('Refreshing test window...')
1354 tree
.CreateTestWin(g
.testWin
.item
)
1355 #self.SetStatusText('')
1356 tree
.needUpdate
= False
1357 elif tree
.pendingHighLight
:
1359 tree
.HighLight(tree
.pendingHighLight
)
1361 # Remove highlight if any problem
1362 if g
.testWin
and g
.testWin
.highLight
:
1363 g
.testWin
.highLight
.Remove()
1364 tree
.pendingHighLight
= None
1371 # We don't let close panel window
1372 def OnCloseMiniFrame(self
, evt
):
1375 def OnIconize(self
, evt
):
1377 conf
.x
, conf
.y
= self
.GetPosition()
1378 conf
.width
, conf
.height
= self
.GetSize()
1380 conf
.sashPos
= self
.splitter
.GetSashPosition()
1382 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1383 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1384 self
.miniFrame
.Iconize()
1386 if not conf
.embedPanel
:
1387 self
.miniFrame
.Iconize(False)
1390 def OnCloseWindow(self
, evt
):
1391 if not self
.AskSave(): return
1392 if g
.testWin
: g
.testWin
.Destroy()
1393 if not panel
.GetPageCount() == 2:
1394 panel
.page2
.Destroy()
1396 # If we don't do this, page does not get destroyed (a bug?)
1398 if not self
.IsIconized():
1399 conf
.x
, conf
.y
= self
.GetPosition()
1400 conf
.width
, conf
.height
= self
.GetClientSize()
1402 conf
.sashPos
= self
.splitter
.GetSashPosition()
1404 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1405 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1408 def CreateLocalConf(self
, path
):
1409 name
= os
.path
.splitext(path
)[0]
1411 return wx
.FileConfig(localFilename
=name
)
1415 conf
.localconf
= None
1417 self
.SetModified(False)
1423 # Numbers for new controls
1425 for cl
in [xxxPanel
, xxxDialog
, xxxFrame
,
1426 xxxMenuBar
, xxxMenu
, xxxToolBar
,
1427 xxxWizard
, xxxBitmap
, xxxIcon
]:
1429 # Restore handlers, menu, etc. to initial
1430 setHandlers(self
.handlers
[:])
1431 g
.pullDownMenu
.custom
= self
.custom
[:]
1432 # Remove modules imported from comment directives
1433 map(sys
.modules
.pop
, [m
for m
in sys
.modules
if m
not in self
.modules
])
1434 xxxParamComment
.locals = {} # clear local namespace
1435 xxxParamComment
.allow
= None # clear execution state
1437 def SetModified(self
, state
=True):
1438 self
.modified
= state
1439 name
= os
.path
.basename(self
.dataFile
)
1440 if not name
: name
= defaultName
1442 self
.SetTitle(progname
+ ': ' + name
+ ' *')
1444 self
.SetTitle(progname
+ ': ' + name
)
1446 def Open(self
, path
):
1447 if not os
.path
.exists(path
):
1448 wx
.LogError('File does not exists: %s' % path
)
1450 # Try to read the file
1454 dom
= minidom
.parse(f
)
1456 # Set encoding global variable and default encoding
1458 g
.currentEncoding
= dom
.encoding
1459 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode())
1461 g
.currentEncoding
= ''
1463 self
.dataFile
= path
= os
.path
.abspath(path
)
1464 dir = os
.path
.dirname(path
)
1465 if dir: os
.chdir(dir)
1466 # Allow importing modules from the same directory
1467 sys
.path
= sys_path
+ [dir]
1469 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1470 conf
.localconf
= self
.CreateLocalConf(self
.dataFile
)
1472 # Nice exception printing
1473 inf
= sys
.exc_info()
1474 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1475 wx
.LogError('Error reading file: %s' % path
)
1480 def Indent(self
, node
, indent
= 0):
1481 if node
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1482 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1483 node
.parentNode
.insertBefore(text
, node
)
1484 return # no children
1485 # Copy child list because it will change soon
1486 children
= node
.childNodes
[:]
1487 # Main node doesn't need to be indented
1489 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1490 node
.parentNode
.insertBefore(text
, node
)
1492 # Append newline after last child, except for text nodes
1493 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1494 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1495 node
.appendChild(text
)
1496 # Indent children which are elements
1498 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
or \
1499 n
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1500 self
.Indent(n
, indent
+ 2)
1502 def Save(self
, path
):
1506 if tree
.selection
and panel
.IsModified():
1507 self
.OnRefresh(wx
.CommandEvent())
1508 if g
.currentEncoding
:
1509 f
= codecs
.open(path
, 'wt', g
.currentEncoding
)
1511 f
= codecs
.open(path
, 'wt')
1512 # Make temporary copy for formatting it
1513 # !!! We can't clone dom node, it works only once
1514 #self.domCopy = tree.dom.cloneNode(True)
1515 self
.domCopy
= MyDocument()
1516 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True))
1517 # Remove first child (test element)
1518 testElem
= mainNode
.firstChild
1519 mainNode
.removeChild(testElem
)
1521 self
.Indent(mainNode
)
1522 self
.domCopy
.writexml(f
, encoding
= g
.currentEncoding
)
1524 self
.domCopy
.unlink()
1526 self
.SetModified(False)
1527 panel
.SetModified(False)
1528 conf
.localconf
.Flush()
1530 inf
= sys
.exc_info()
1531 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1532 wx
.LogError('Error writing file: %s' % path
)
1536 if not (self
.modified
or panel
.IsModified()): return True
1537 flags
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
1538 dlg
= wx
.MessageDialog( self
, 'File is modified. Save before exit?',
1539 'Save before too late?', flags
)
1540 say
= dlg
.ShowModal()
1543 if say
== wx
.ID_YES
:
1544 self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
))
1545 # If save was successful, modified flag is unset
1546 if not self
.modified
: return True
1547 elif say
== wx
.ID_NO
:
1548 self
.SetModified(False)
1549 panel
.SetModified(False)
1553 ################################################################################
1555 class PythonOptions(wx
.Dialog
):
1557 def __init__(self
, parent
, cfg
, dataFile
):
1558 pre
= wx
.PreDialog()
1559 g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS")
1560 self
.PostCreate(pre
)
1563 self
.dataFile
= dataFile
1565 self
.AutoGenerateCB
= xrc
.XRCCTRL(self
, "AutoGenerateCB")
1566 self
.EmbedCB
= xrc
.XRCCTRL(self
, "EmbedCB")
1567 self
.GettextCB
= xrc
.XRCCTRL(self
, "GettextCB")
1568 self
.MakeXRSFileCB
= xrc
.XRCCTRL(self
, "MakeXRSFileCB")
1569 self
.FileNameTC
= xrc
.XRCCTRL(self
, "FileNameTC")
1570 self
.BrowseBtn
= xrc
.XRCCTRL(self
, "BrowseBtn")
1571 self
.GenerateBtn
= xrc
.XRCCTRL(self
, "GenerateBtn")
1572 self
.SaveOptsBtn
= xrc
.XRCCTRL(self
, "SaveOptsBtn")
1574 self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
)
1575 self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
)
1576 self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
)
1578 if self
.cfg
.Read("filename", "") != "":
1579 self
.FileNameTC
.SetValue(self
.cfg
.Read("filename"))
1581 name
= os
.path
.splitext(os
.path
.split(dataFile
)[1])[0]
1583 self
.FileNameTC
.SetValue(name
)
1584 self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False))
1585 self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False))
1586 self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False))
1587 self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False))
1590 def OnBrowse(self
, evt
):
1591 path
= self
.FileNameTC
.GetValue()
1592 dirname
= os
.path
.abspath(os
.path
.dirname(path
))
1593 name
= os
.path
.split(path
)[1]
1594 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py',
1595 wx
.SAVE | wx
.OVERWRITE_PROMPT
)
1596 if dlg
.ShowModal() == wx
.ID_OK
:
1597 path
= dlg
.GetPath()
1598 self
.FileNameTC
.SetValue(path
)
1602 def OnGenerate(self
, evt
):
1603 pypath
= self
.FileNameTC
.GetValue()
1604 embed
= self
.EmbedCB
.GetValue()
1605 genGettext
= self
.GettextCB
.GetValue()
1606 frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
1610 def OnSaveOpts(self
, evt
=None):
1611 self
.cfg
.Write("filename", self
.FileNameTC
.GetValue())
1612 self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue())
1613 self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue())
1614 self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue())
1615 self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue())
1617 self
.EndModal(wx
.ID_OK
)
1619 ################################################################################
1621 class PrefsDialog(wx
.Dialog
):
1623 def __init__(self
, parent
):
1624 pre
= wx
.PreDialog()
1625 g
.frame
.res
.LoadOnDialog(pre
, parent
, "DIALOG_PREFS")
1626 self
.PostCreate(pre
)
1627 self
.checkControls
= {} # map of check IDs to (control,dict,param)
1629 ##xxx = sys.modules['xxx']
1631 d
= xxx
.xxxSizerItem
.defaults_panel
1633 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_panel')
1634 id = self
.check_proportion_panel
.GetId()
1635 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1636 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_panel'),
1639 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_panel')
1640 id = self
.check_flag_panel
.GetId()
1641 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1642 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_panel'),
1645 d
= xxx
.xxxSizerItem
.defaults_control
1647 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_control')
1648 id = self
.check_proportion_panel
.GetId()
1649 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1650 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_control'),
1653 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_control')
1654 id = self
.check_flag_panel
.GetId()
1655 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1656 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_control'),
1659 for id,cdp
in self
.checkControls
.items():
1662 if isinstance(c
, wx
.SpinCtrl
):
1663 c
.SetValue(int(d
[p
]))
1666 self
.FindWindowById(id).SetValue(True)
1670 self
.radio_allow_exec
= xrc
.XRCCTRL(self
, 'radio_allow_exec')
1672 radio
= {'ask': 0, 'yes':1, 'no':2}
[g
.conf
.allowExec
]
1675 self
.radio_allow_exec
.SetSelection(radio
)
1677 def OnCheck(self
, evt
):
1678 self
.checkControls
[evt
.GetId()][0].Enable(evt
.IsChecked())
1681 ################################################################################
1683 # Parse string in form var1=val1[,var2=val2]* as dictionary
1684 def ReadDictFromString(s
):
1686 for vv
in s
.split(','):
1687 var
,val
= vv
.split(':')
1688 d
[var
.strip()] = val
1691 # Transform dictionary with strings into one string
1692 def DictToString(d
):
1693 return ','.join(map(':'.join
, d
.items()))
1696 print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]'
1701 if wx
.VERSION
[:3] < MinWxVersion
:
1703 This version of XRCed may not work correctly on your version of wxWidgets. \
1704 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
)
1706 # Process comand-line
1709 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dhiv')
1717 print 'XRCed version', version
1720 except getopt
.GetoptError
:
1721 if wx
.Platform
!= '__WXMAC__': # macs have some extra parameters
1722 print >> sys
.stderr
, 'Unknown option'
1726 self
.SetAppName('xrced')
1729 conf
= g
.conf
= wx
.Config(style
= wx
.CONFIG_USE_LOCAL_FILE
)
1730 conf
.localconf
= None
1731 conf
.autoRefresh
= conf
.ReadInt('autorefresh', True)
1732 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1733 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1734 conf
.embedPanel
= conf
.ReadInt('embedPanel', True)
1735 conf
.showTools
= conf
.ReadInt('showTools', True)
1736 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1738 # read recently used files
1739 g
.fileHistory
= wx
.FileHistory()
1740 g
.fileHistory
.Load(conf
)
1742 if not conf
.embedPanel
:
1743 conf
.panelX
= conf
.ReadInt('panelX', -1)
1744 conf
.panelY
= conf
.ReadInt('panelY', -1)
1746 conf
.panelX
= conf
.panelY
= -1
1747 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1748 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1749 conf
.panic
= not conf
.HasEntry('nopanic')
1751 conf
.allowExec
= conf
.Read('Prefs/allowExec', 'ask')
1752 p
= 'Prefs/sizeritem_defaults_panel'
1754 if conf
.HasEntry(p
):
1755 ##sys.modules['xxx'].xxxSizerItem.defaults_panel = ReadDictFromString(conf.Read(p))
1756 xxx
.xxxSizerItem
.defaults_panel
= ReadDictFromString(conf
.Read(p
))
1757 p
= 'Prefs/sizeritem_defaults_control'
1758 if conf
.HasEntry(p
):
1759 ##sys.modules['xxx'].xxxSizerItem.defaults_control = ReadDictFromString(conf.Read(p))
1760 xxx
.xxxSizerItem
.defaults_control
= ReadDictFromString(conf
.Read(p
))
1763 wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler())
1765 frame
= Frame(pos
, size
)
1766 frame
.SetClientSize(size
)
1770 plugins
= os
.getenv('XRCEDPATH')
1774 for dir in plugins
.split(':'):
1775 if os
.path
.isdir(dir) and \
1776 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1778 dir = os
.path
.abspath(os
.path
.normpath(dir))
1779 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1782 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1784 print traceback
.print_exc()
1787 # Store important data
1788 frame
.handlers
= getHandlers()[:]
1789 frame
.custom
= g
.pullDownMenu
.custom
[:]
1790 frame
.modules
= sys
.modules
.copy()
1795 # Load file after showing
1798 frame
.open = frame
.Open(args
[0])
1806 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1807 wc
.WriteInt('x', conf
.x
)
1808 wc
.WriteInt('y', conf
.y
)
1809 wc
.WriteInt('width', conf
.width
)
1810 wc
.WriteInt('height', conf
.height
)
1811 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1812 wc
.WriteInt('showTools', conf
.showTools
)
1813 if not conf
.embedPanel
:
1814 wc
.WriteInt('panelX', conf
.panelX
)
1815 wc
.WriteInt('panelY', conf
.panelY
)
1816 wc
.WriteInt('sashPos', conf
.sashPos
)
1817 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1818 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1819 wc
.WriteInt('nopanic', 1)
1820 g
.fileHistory
.Save(wc
)
1822 wc
.DeleteGroup('Prefs')
1823 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1825 ##v = sys.modules['xxx'].xxxSizerItem.defaults_panel
1826 v
= xxx
.xxxSizerItem
.defaults_panel
1827 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1828 ###v = sys.modules['xxx'].xxxSizerItem.defaults_control
1829 v
= xxx
.xxxSizerItem
.defaults_control
1830 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1835 app
= App(0, useBestVisual
=False)
1836 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1842 if __name__
== '__main__':