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 # Hide some icons on Mac to reduce the toolbar size,
209 # and comply more with the Apple LnF, besides
210 # wxMac icons are ugly
211 if wx
.Platform
!= '__WXMAC__':
212 new_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
)
213 open_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
)
214 save_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
)
215 undo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
)
216 redo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
)
217 cut_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
)
218 copy_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
)
219 paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
)
220 tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file')
221 tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file')
222 tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file')
223 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
224 tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo')
225 tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo')
226 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
227 tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut')
228 tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy')
229 tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste')
230 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
231 tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
,
232 images
.getLocateBitmap(), #images.getLocateArmedBitmap(),
233 'Locate', 'Locate control in test window and select it', True)
234 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
235 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
236 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
237 'Refresh', 'Refresh view')
238 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
239 'Auto-refresh', 'Toggle auto-refresh mode', True)
240 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
241 tb
.AddSimpleTool(self
.ID_MOVEUP
, images
.getToolMoveUpBitmap(),
242 'Up', 'Move before previous sibling')
243 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, images
.getToolMoveDownBitmap(),
244 'Down', 'Move after next sibling')
245 tb
.AddSimpleTool(self
.ID_MOVELEFT
, images
.getToolMoveLeftBitmap(),
246 'Make Sibling', 'Make sibling of parent')
247 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, images
.getToolMoveRightBitmap(),
248 'Make Child', 'Make child of previous sibling')
249 # if wx.Platform == '__WXGTK__':
250 # tb.AddSeparator() # otherwise auto-refresh sticks in status line
251 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
255 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
258 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
)
259 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
)
260 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
)
261 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
)
262 wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
)
263 wx
.EVT_MENU(self
, self
.ID_PREFS
, self
.OnPrefs
)
264 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
266 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
267 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
268 wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
)
269 wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
)
270 wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
)
271 wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
)
272 wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
)
273 wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
)
274 wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
)
276 wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
277 wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
)
278 wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
279 wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
280 wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
281 wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
)
283 wx
.EVT_MENU(self
, self
.ID_MOVEUP
, self
.OnMoveUp
)
284 wx
.EVT_MENU(self
, self
.ID_MOVEDOWN
, self
.OnMoveDown
)
285 wx
.EVT_MENU(self
, self
.ID_MOVELEFT
, self
.OnMoveLeft
)
286 wx
.EVT_MENU(self
, self
.ID_MOVERIGHT
, self
.OnMoveRight
)
288 wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
)
289 wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
292 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
)
293 wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
)
294 wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
)
295 wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
)
296 wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
)
297 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
)
298 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
)
299 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
)
300 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
)
301 wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
302 wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
303 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
306 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
307 #sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
308 # Horizontal sizer for toolbar and splitter
309 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
310 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
311 self
.splitter
= splitter
312 splitter
.SetMinimumPaneSize(100)
315 g
.tree
= tree
= XML_Tree(splitter
, -1)
317 # Init pull-down menu data
319 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
321 # Vertical toolbar for GUI buttons
322 g
.tools
= tools
= Tools(self
)
323 tools
.Show(conf
.showTools
)
324 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
326 tree
.RegisterKeyEvents()
328 # Miniframe for split mode
329 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
330 (conf
.panelX
, conf
.panelY
),
331 (conf
.panelWidth
, conf
.panelHeight
))
332 self
.miniFrame
= miniFrame
333 sizer2
= wx
.BoxSizer()
334 miniFrame
.SetSizer(sizer2
)
335 # Create panel for parameters
338 panel
= Panel(splitter
)
339 # Set plitter windows
340 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
342 panel
= Panel(miniFrame
)
343 sizer2
.Add(panel
, 1, wx
.EXPAND
)
345 splitter
.Initialize(tree
)
346 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
347 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
348 self
.SetAutoLayout(True)
352 wx
.EVT_IDLE(self
, self
.OnIdle
)
353 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
354 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
355 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
356 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
358 def OnRecentFile(self
,evt
):
359 # open recently used file
360 if not self
.AskSave(): return
363 # get the pathname based on the menu ID
364 fileNum
= evt
.GetId() - wx
.ID_FILE1
365 path
= g
.fileHistory
.GetHistoryFile(fileNum
)
368 self
.SetStatusText('Data loaded')
369 # add it back to the history so it will be moved up the list
370 self
.SaveRecent(path
)
372 self
.SetStatusText('Failed')
376 def OnNew(self
, evt
):
377 if not self
.AskSave(): return
380 def OnOpen(self
, evt
):
381 if not self
.AskSave(): return
382 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
383 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
384 if dlg
.ShowModal() == wx
.ID_OK
:
386 self
.SetStatusText('Loading...')
390 self
.SetStatusText('Data loaded')
391 self
.SaveRecent(path
)
393 self
.SetStatusText('Failed')
398 def OnSaveOrSaveAs(self
, evt
):
399 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
400 if self
.dataFile
: name
= ''
401 else: name
= defaultName
402 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
403 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
404 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
405 if dlg
.ShowModal() == wx
.ID_OK
:
407 if isinstance(path
, unicode):
408 path
= path
.encode(sys
.getfilesystemencoding())
415 # if we already have a localconf then it needs to be
416 # copied to a new config with the new name
418 nc
= self
.CreateLocalConf(path
)
419 flag
, key
, idx
= lc
.GetFirstEntry()
421 nc
.Write(key
, lc
.Read(key
))
422 flag
, key
, idx
= lc
.GetNextEntry(idx
)
425 # otherwise create a new one
426 conf
.localconf
= self
.CreateLocalConf(path
)
429 self
.SetStatusText('Saving...')
433 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
435 self
.Save(tmpName
) # save temporary file first
436 shutil
.move(tmpName
, path
)
438 self
.SetModified(False)
439 if conf
.localconf
.ReadBool("autogenerate", False):
440 pypath
= conf
.localconf
.Read("filename")
441 embed
= conf
.localconf
.ReadBool("embedResource", False)
442 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
443 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
445 self
.SetStatusText('Data saved')
446 self
.SaveRecent(path
)
448 self
.SetStatusText('Failed')
452 def SaveRecent(self
,path
):
453 # append to recently used files
454 g
.fileHistory
.AddFileToHistory(path
)
456 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
458 import wx
.tools
.pywxrc
459 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
460 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
463 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
464 wx
.LogError('Error generating python code : %s' % pypath
)
468 def OnGeneratePython(self
, evt
):
469 if self
.modified
or not conf
.localconf
:
470 wx
.MessageBox("Save the XRC file first!", "Error")
473 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
477 def OnPrefs(self
, evt
):
478 dlg
= PrefsDialog(self
)
479 if dlg
.ShowModal() == wx
.ID_OK
:
480 # Fetch new preferences
481 for id,cdp
in dlg
.checkControls
.items():
483 if dlg
.FindWindowById(id).IsChecked():
484 d
[p
] = str(c
.GetValue())
485 elif p
in d
: del d
[p
]
486 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
489 def OnExit(self
, evt
):
492 def OnUndo(self
, evt
):
493 # Extra check to not mess with idle updating
494 if undoMan
.CanUndo():
496 g
.panel
.SetModified(False)
497 if not undoMan
.CanUndo():
498 self
.SetModified(False)
500 def OnRedo(self
, evt
):
501 if undoMan
.CanRedo():
503 self
.SetModified(True)
505 def OnCopy(self
, evt
):
506 selected
= tree
.selection
507 if not selected
: return # key pressed event
508 xxx
= tree
.GetPyData(selected
)
509 if wx
.TheClipboard
.Open():
511 data
= wx
.CustomDataObject('XRCED')
512 # Set encoding in header
514 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
516 data
= wx
.CustomDataObject('XRCED_node')
518 data
.SetData(cPickle
.dumps(s
))
519 wx
.TheClipboard
.SetData(data
)
520 wx
.TheClipboard
.Close()
521 self
.SetStatusText('Copied')
523 wx
.MessageBox("Unable to open the clipboard", "Error")
525 def OnPaste(self
, evt
):
526 selected
= tree
.selection
527 if not selected
: return # key pressed event
528 # For pasting with Ctrl pressed
530 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
531 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
532 if g
.tree
.ctrl
: appendChild
= False
533 else: appendChild
= not tree
.NeedInsert(selected
)
534 else: appendChild
= not tree
.NeedInsert(selected
)
535 xxx
= tree
.GetPyData(selected
)
537 # If has next item, insert, else append to parent
538 nextItem
= tree
.GetNextSibling(selected
)
539 parentLeaf
= tree
.GetItemParent(selected
)
540 # Expanded container (must have children)
541 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
542 # Insert as first child
543 nextItem
= tree
.GetFirstChild(selected
)[0]
544 parentLeaf
= selected
546 # No children or unexpanded item - appendChild stays True
547 nextItem
= wx
.TreeItemId() # no next item
548 parentLeaf
= selected
549 parent
= tree
.GetPyData(parentLeaf
).treeObject()
551 # Create a copy of clipboard pickled element
552 success
= success_node
= False
553 if wx
.TheClipboard
.Open():
555 data
= wx
.CustomDataObject('XRCED')
556 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
558 success
= wx
.TheClipboard
.GetData(data
)
560 # there is a problem if XRCED_node is in clipboard
561 # but previous SetData was for XRCED
563 if not success
: # try other format
564 data
= wx
.CustomDataObject('XRCED_node')
565 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
566 success_node
= wx
.TheClipboard
.GetData(data
)
568 wx
.TheClipboard
.Close()
570 if not success
and not success_node
:
572 "There is no data in the clipboard in the required format",
576 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
578 elem
= minidom
.parseString(xml
).childNodes
[0]
580 elem
= g
.tree
.dom
.createComment(xml
)
582 # Tempopary xxx object to test things
583 xxx
= MakeXXXFromDOM(parent
, elem
)
585 # Check compatibility
586 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
588 # Check parent and child relationships.
589 # If parent is sizer or notebook, child is of wrong class or
590 # parent is normal window, child is child container then detach child.
591 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
592 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
593 if isChildContainer
and \
594 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
595 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
596 not (parent
.isSizer
or parentIsBook
)):
597 elem
.removeChild(xxx
.child
.node
) # detach child
598 elem
.unlink() # delete child container
599 elem
= xxx
.child
.node
# replace
600 # This may help garbage collection
601 xxx
.child
.parent
= None
602 isChildContainer
= False
603 # Parent is sizer or notebook, child is not child container
604 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
605 # Create sizer item element
606 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
607 sizerItemElem
.appendChild(elem
)
609 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
610 pageElem
= MakeEmptyDOM('notebookpage')
611 pageElem
.appendChild(elem
)
613 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
614 pageElem
= MakeEmptyDOM('choicebookpage')
615 pageElem
.appendChild(elem
)
617 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
618 pageElem
= MakeEmptyDOM('listbookpage')
619 pageElem
.appendChild(elem
)
621 # Insert new node, register undo
622 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
623 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
624 # Scroll to show new item (!!! redundant?)
625 tree
.EnsureVisible(newItem
)
626 tree
.SelectItem(newItem
)
627 if not tree
.IsVisible(newItem
):
628 tree
.ScrollTo(newItem
)
631 if g
.testWin
and tree
.IsHighlatable(newItem
):
633 tree
.needUpdate
= True
634 tree
.pendingHighLight
= newItem
636 tree
.pendingHighLight
= None
638 self
.SetStatusText('Pasted')
641 def ItemsAreCompatible(self
, parent
, child
):
642 # Check compatibility
644 # Comments are always compatible
645 if child
.__class
__ == xxxComment
:
648 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
650 if parent
.__class
__ != xxxMainNode
: error
= True
651 elif child
.__class
__ == xxxMenuBar
:
652 # Menubar can be put in frame or dialog
653 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
654 elif child
.__class
__ == xxxToolBar
:
655 # Toolbar can be top-level of child of panel or frame
656 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
657 not parent
.isSizer
: error
= True
658 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
660 elif child
.__class
__ == xxxSpacer
:
661 if not parent
.isSizer
: error
= True
662 elif child
.__class
__ == xxxSeparator
:
663 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
664 elif child
.__class
__ == xxxTool
:
665 if parent
.__class
__ != xxxToolBar
: error
= True
666 elif child
.__class
__ == xxxMenu
:
667 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
668 elif child
.__class
__ == xxxMenuItem
:
669 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
670 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
672 else: # normal controls can be almost anywhere
673 if parent
.__class
__ == xxxMainNode
or \
674 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
676 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
677 else: parentClass
= parent
.className
678 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
679 (parentClass
, child
.className
))
683 def OnMoveUp(self
, evt
):
684 selected
= tree
.selection
685 if not selected
: return
687 index
= tree
.ItemIndex(selected
)
688 if index
== 0: return # No previous sibling found
690 # Remove highlight, update testWin
691 if g
.testWin
and g
.testWin
.highLight
:
692 g
.testWin
.highLight
.Remove()
693 tree
.needUpdate
= True
696 self
.lastOp
= 'MOVEUP'
697 status
= 'Moved before previous sibling'
703 parent
= tree
.GetItemParent(selected
)
704 elem
= tree
.RemoveLeaf(selected
)
705 nextItem
= tree
.GetFirstChild(parent
)[0]
706 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
707 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
708 newIndex
= tree
.ItemIndex(selected
)
709 tree
.SelectItem(selected
)
711 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
714 self
.SetStatusText(status
)
718 def OnMoveDown(self
, evt
):
719 selected
= tree
.selection
720 if not selected
: return
722 index
= tree
.ItemIndex(selected
)
723 next
= tree
.GetNextSibling(selected
)
726 # Remove highlight, update testWin
727 if g
.testWin
and g
.testWin
.highLight
:
728 g
.testWin
.highLight
.Remove()
729 tree
.needUpdate
= True
732 self
.lastOp
= 'MOVEDOWN'
733 status
= 'Moved after next sibling'
739 parent
= tree
.GetItemParent(selected
)
740 elem
= tree
.RemoveLeaf(selected
)
741 nextItem
= tree
.GetFirstChild(parent
)[0]
742 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
743 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
744 newIndex
= tree
.ItemIndex(selected
)
745 tree
.SelectItem(selected
)
747 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
750 self
.SetStatusText(status
)
754 def OnMoveLeft(self
, evt
):
755 selected
= tree
.selection
756 if not selected
: return
758 oldParent
= tree
.GetItemParent(selected
)
759 if not oldParent
: return
760 pparent
= tree
.GetItemParent(oldParent
)
761 if not pparent
: return
763 # Check compatibility
764 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
766 # Remove highlight, update testWin
767 if g
.testWin
and g
.testWin
.highLight
:
768 g
.testWin
.highLight
.Remove()
769 tree
.needUpdate
= True
772 self
.lastOp
= 'MOVELEFT'
773 status
= 'Made next sibling of parent'
775 oldIndex
= tree
.ItemIndex(selected
)
776 elem
= tree
.RemoveLeaf(selected
)
777 nextItem
= tree
.GetFirstChild(pparent
)[0]
778 parentIndex
= tree
.ItemIndex(oldParent
)
779 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
781 # Check parent and child relationships.
782 # If parent is sizer or notebook, child is of wrong class or
783 # parent is normal window, child is child container then detach child.
784 parent
= tree
.GetPyData(pparent
).treeObject()
785 xxx
= MakeXXXFromDOM(parent
, elem
)
786 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
787 if isChildContainer
and \
788 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
789 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
790 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
791 elem
.removeChild(xxx
.child
.node
) # detach child
792 elem
.unlink() # delete child container
793 elem
= xxx
.child
.node
# replace
794 # This may help garbage collection
795 xxx
.child
.parent
= None
796 isChildContainer
= False
797 # Parent is sizer or notebook, child is not child container
798 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
799 # Create sizer item element
800 sizerItemElem
= MakeEmptyDOM('sizeritem')
801 sizerItemElem
.appendChild(elem
)
803 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
804 pageElem
= MakeEmptyDOM('notebookpage')
805 pageElem
.appendChild(elem
)
808 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
809 newIndex
= tree
.ItemIndex(selected
)
811 tree
.SelectItem(selected
)
813 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
816 self
.SetStatusText(status
)
818 def OnMoveRight(self
, evt
):
819 selected
= tree
.selection
820 if not selected
: return
822 oldParent
= tree
.GetItemParent(selected
)
823 if not oldParent
: return
825 newParent
= tree
.GetPrevSibling(selected
)
826 if not newParent
: return
828 parent
= tree
.GetPyData(newParent
).treeObject()
830 # Check compatibility
831 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
833 # Remove highlight, update testWin
834 if g
.testWin
and g
.testWin
.highLight
:
835 g
.testWin
.highLight
.Remove()
836 tree
.needUpdate
= True
839 self
.lastOp
= 'MOVERIGHT'
840 status
= 'Made last child of previous sibling'
842 oldIndex
= tree
.ItemIndex(selected
)
843 elem
= tree
.RemoveLeaf(selected
)
845 # Check parent and child relationships.
846 # If parent is sizer or notebook, child is of wrong class or
847 # parent is normal window, child is child container then detach child.
848 xxx
= MakeXXXFromDOM(parent
, elem
)
849 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
850 if isChildContainer
and \
851 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
852 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
853 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
854 elem
.removeChild(xxx
.child
.node
) # detach child
855 elem
.unlink() # delete child container
856 elem
= xxx
.child
.node
# replace
857 # This may help garbage collection
858 xxx
.child
.parent
= None
859 isChildContainer
= False
860 # Parent is sizer or notebook, child is not child container
861 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
862 # Create sizer item element
863 sizerItemElem
= MakeEmptyDOM('sizeritem')
864 sizerItemElem
.appendChild(elem
)
866 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
867 pageElem
= MakeEmptyDOM('notebookpage')
868 pageElem
.appendChild(elem
)
871 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
873 newIndex
= tree
.ItemIndex(selected
)
875 tree
.SelectItem(selected
)
877 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
880 self
.SetStatusText(status
)
882 def OnCutDelete(self
, evt
):
883 selected
= tree
.selection
884 if not selected
: return # key pressed event
886 if evt
.GetId() == wx
.ID_CUT
:
888 status
= 'Removed to clipboard'
890 self
.lastOp
= 'DELETE'
894 # If deleting top-level item, delete testWin
895 if selected
== g
.testWin
.item
:
899 # Remove highlight, update testWin
900 if g
.testWin
.highLight
:
901 g
.testWin
.highLight
.Remove()
902 tree
.needUpdate
= True
905 index
= tree
.ItemFullIndex(selected
)
906 xxx
= tree
.GetPyData(selected
)
907 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
909 elem
= tree
.RemoveLeaf(selected
)
910 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
911 if evt
.GetId() == wx
.ID_CUT
:
912 if wx
.TheClipboard
.Open():
914 data
= wx
.CustomDataObject('XRCED')
916 s
= elem
.toxml(encoding
=expat
.native_encoding
)
918 data
= wx
.CustomDataObject('XRCED_node')
920 data
.SetData(cPickle
.dumps(s
))
921 wx
.TheClipboard
.SetData(data
)
922 wx
.TheClipboard
.Close()
924 wx
.MessageBox("Unable to open the clipboard", "Error")
925 tree
.pendingHighLight
= None
929 self
.SetStatusText(status
)
931 def OnSubclass(self
, evt
):
932 selected
= tree
.selection
933 xxx
= tree
.GetPyData(selected
).treeObject()
935 subclass
= xxx
.subclass
936 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
937 if dlg
.ShowModal() == wx
.ID_OK
:
938 subclass
= dlg
.GetValue()
940 elem
.setAttribute('subclass', subclass
)
941 elif elem
.hasAttribute('subclass'):
942 elem
.removeAttribute('subclass')
944 xxx
.subclass
= elem
.getAttribute('subclass')
945 tree
.SetItemText(selected
, xxx
.treeName())
946 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
949 def OnEmbedPanel(self
, evt
):
950 conf
.embedPanel
= evt
.IsChecked()
952 # Remember last dimentions
953 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
954 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
955 size
= self
.GetSize()
956 pos
= self
.GetPosition()
957 sizePanel
= panel
.GetSize()
958 panel
.Reparent(self
.splitter
)
959 self
.miniFrame
.GetSizer().Remove(panel
)
961 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
962 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
963 self
.miniFrame
.Show(False)
965 conf
.sashPos
= self
.splitter
.GetSashPosition()
966 pos
= self
.GetPosition()
967 size
= self
.GetSize()
968 sizePanel
= panel
.GetSize()
969 self
.splitter
.Unsplit(panel
)
970 sizer
= self
.miniFrame
.GetSizer()
971 panel
.Reparent(self
.miniFrame
)
973 sizer
.Add(panel
, 1, wx
.EXPAND
)
974 self
.miniFrame
.Show(True)
975 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
976 conf
.panelWidth
, conf
.panelHeight
)
977 self
.miniFrame
.Layout()
979 self
.SetDimensions(pos
.x
, pos
.y
,
980 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
982 def OnShowTools(self
, evt
):
983 conf
.showTools
= evt
.IsChecked()
984 g
.tools
.Show(conf
.showTools
)
986 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
988 self
.toolsSizer
.Remove(g
.tools
)
989 self
.toolsSizer
.Layout()
991 def OnTest(self
, evt
):
992 if not tree
.selection
: return # key pressed event
993 tree
.ShowTestWindow(tree
.selection
)
995 def OnTestHide(self
, evt
):
996 tree
.CloseTestWindow()
998 # Find object by relative position
999 def FindObject(self
, item
, obj
):
1000 # We simply perform depth-first traversal, sinse it's too much
1001 # hassle to deal with all sizer/window combinations
1002 w
= tree
.FindNodeObject(item
)
1003 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
1005 if tree
.ItemHasChildren(item
):
1006 child
= tree
.GetFirstChild(item
)[0]
1008 found
= self
.FindObject(child
, obj
)
1009 if found
: return found
1010 child
= tree
.GetNextSibling(child
)
1013 # Click event after locate activated
1014 def OnTestWinLeftDown(self
, evt
):
1015 # Restore normal event processing
1016 self
.SetHandler(g
.testWin
)
1017 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1018 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
1020 tree
.EnsureVisible(item
)
1021 tree
.SelectItem(item
)
1022 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1024 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1026 self
.SetStatusText('Locate failed!')
1028 def SetHandler(self
, w
, h
=None):
1030 w
.SetEventHandler(h
)
1031 w
.SetCursor(wx
.CROSS_CURSOR
)
1033 w
.SetEventHandler(w
)
1034 w
.SetCursor(wx
.NullCursor
)
1035 for ch
in w
.GetChildren():
1036 self
.SetHandler(ch
, h
)
1038 def OnLocate(self
, evt
):
1040 if evt
.GetId() == self
.ID_LOCATE
or \
1041 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1042 self
.SetHandler(g
.testWin
, g
.testWin
)
1043 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1044 if evt
.GetId() == self
.ID_LOCATE
:
1045 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1046 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1047 self
.SetHandler(g
.testWin
, None)
1048 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1049 self
.SetStatusText('Click somewhere in your test window now')
1051 def OnRefresh(self
, evt
):
1052 # If modified, apply first
1053 selection
= tree
.selection
1055 xxx
= tree
.GetPyData(selection
)
1056 if xxx
and panel
.IsModified():
1057 tree
.Apply(xxx
, selection
)
1060 tree
.CreateTestWin(g
.testWin
.item
)
1061 panel
.modified
= False
1062 tree
.needUpdate
= False
1064 def OnAutoRefresh(self
, evt
):
1065 conf
.autoRefresh
= evt
.IsChecked()
1066 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1067 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1069 def OnAbout(self
, evt
):
1073 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1074 Homepage: http://xrced.sourceforge.net\
1076 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1080 def OnReadme(self
, evt
):
1081 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1082 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1086 # Simple emulation of python command line
1087 def OnDebugCMD(self
, evt
):
1090 exec raw_input('C:\> ')
1095 (etype
, value
, tb
) =sys
.exc_info()
1096 tblist
=traceback
.extract_tb(tb
)[1:]
1097 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1098 +traceback
.format_list(tblist
))
1101 def OnCreate(self
, evt
):
1102 # Ignore fake events generated while dragging
1104 g
.tools
.drag
= False
1106 selected
= tree
.selection
1107 if tree
.ctrl
: appendChild
= False
1108 else: appendChild
= not tree
.NeedInsert(selected
)
1109 xxx
= tree
.GetPyData(selected
)
1113 # If has previous item, insert after it, else append to parent
1115 parentLeaf
= tree
.GetItemParent(selected
)
1117 # If has next item, insert, else append to parent
1118 nextItem
= tree
.GetNextSibling(selected
)
1119 parentLeaf
= tree
.GetItemParent(selected
)
1120 # Expanded container (must have children)
1121 elif tree
.shift
and tree
.IsExpanded(selected
) \
1122 and tree
.GetChildrenCount(selected
, False):
1123 nextItem
= tree
.GetFirstChild(selected
)[0]
1124 parentLeaf
= selected
1126 nextItem
= wx
.TreeItemId()
1127 parentLeaf
= selected
1128 parent
= tree
.GetPyData(parentLeaf
)
1129 if parent
.hasChild
: parent
= parent
.child
1131 self
.CreateXXX(parent
, parentLeaf
, nextItem
, evt
.GetId())
1133 # Actual method to create object and add to XML and wx trees
1134 def CreateXXX(self
, parent
, parentLeaf
, nextItem
, id):
1135 selected
= tree
.selection
1136 # Create object_ref?
1137 if id == ID_NEW
.REF
:
1138 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1140 xxx
= MakeEmptyRefXXX(parent
, ref
)
1141 elif id == ID_NEW
.COMMENT
:
1142 xxx
= MakeEmptyCommentXXX(parent
)
1144 # Create empty element
1145 if id >= ID_NEW
.CUSTOM
:
1146 className
= pullDownMenu
.customMap
[id]
1148 className
= pullDownMenu
.createMap
[id]
1149 xxx
= MakeEmptyXXX(parent
, className
)
1151 # Insert new node, register undo
1152 if xxx
.isElement
: # true object
1153 # Set default name for top-level windows
1154 if parent
.__class
__ == xxxMainNode
:
1155 cl
= xxx
.treeObject().__class
__
1156 frame
.maxIDs
[cl
] += 1
1157 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1158 # And for some other standard controls
1159 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1160 # ... we can even set automatically tree name
1161 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[id][0])
1162 obj
= xxx
.treeObject()
1164 elem
= g
.tree
.dom
.createElement('label')
1165 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[id][1]))
1166 obj
.params
['label'] = xxxParam(elem
)
1167 xxx
.treeObject().node
.appendChild(elem
)
1168 # Else, set label if exists to class name
1169 elif 'label' in xxx
.treeObject().allParams
:
1171 if label
[:2] == 'wx': label
= label
[2:]
1172 xxx
.treeObject().set('label', label
.upper())
1173 # For comment nodes, simply add node
1174 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1175 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1176 tree
.EnsureVisible(newItem
)
1177 tree
.SelectItem(newItem
)
1178 if not tree
.IsVisible(newItem
):
1179 tree
.ScrollTo(newItem
)
1182 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1183 if conf
.autoRefresh
:
1184 tree
.needUpdate
= True
1185 tree
.pendingHighLight
= newItem
1187 tree
.pendingHighLight
= None
1189 if not xxx
.isElement
:
1190 tree
.EditLabel(newItem
)
1194 # Replace one object with another
1195 def OnReplace(self
, evt
):
1196 selected
= tree
.selection
1197 xxx
= tree
.GetPyData(selected
).treeObject()
1199 parent
= elem
.parentNode
1200 undoMan
.RegisterUndo(UndoReplace(selected
))
1202 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1204 # Create temporary empty node (with default values)
1205 dummy
= MakeEmptyDOM(className
)
1206 if className
== 'spacer' and xxx
.className
!= 'spacer':
1208 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1209 klass
= xxxSizerItem
1211 klass
= xxxDict
[className
]
1212 # Remove non-compatible children
1213 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1214 tree
.DeleteChildren(selected
)
1215 nodes
= elem
.childNodes
[:]
1218 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1222 if not klass
.hasChildren
: remove
= True
1223 elif tag
not in klass
.allParams
and \
1224 (not klass
.hasStyle
or tag
not in klass
.styles
):
1229 elem
.removeChild(node
)
1232 # Remove sizeritem child if spacer
1233 if className
== 'spacer' and xxx
.className
!= 'spacer':
1234 sizeritem
= elem
.parentNode
1235 assert sizeritem
.getAttribute('class') == 'sizeritem'
1236 sizeritem
.removeChild(elem
)
1239 tree
.GetPyData(selected
).hasChild
= False
1240 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1241 # Create sizeritem element
1242 assert xxx
.parent
.isSizer
1243 elem
.setAttribute('class', 'sizeritem')
1244 node
= MakeEmptyDOM(className
)
1245 elem
.appendChild(node
)
1246 # Replace to point to new object
1247 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1249 tree
.SetPyData(selected
, xxx
)
1252 # Copy parameters present in dummy but not in elem
1253 for node
in dummy
.childNodes
:
1254 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1258 elem
.setAttribute('class', className
)
1259 if elem
.hasAttribute('subclass'):
1260 elem
.removeAttribute('subclass') # clear subclassing
1261 # Re-create xxx element
1262 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1263 # Remove incompatible style flags
1264 if 'style' in xxx
.params
:
1265 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1266 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1267 if newStyles
!= styles
:
1269 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1272 xxx
.params
['style'].update(value
)
1274 # Update parent in child objects
1275 if tree
.ItemHasChildren(selected
):
1276 i
, cookie
= tree
.GetFirstChild(selected
)
1278 x
= tree
.GetPyData(i
)
1280 if x
.hasChild
: x
.child
.parent
= xxx
1281 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1284 if tree
.GetPyData(selected
).hasChild
: # child container
1285 container
= tree
.GetPyData(selected
)
1286 container
.resetChild(xxx
)
1289 tree
.SetPyData(selected
, xxx
)
1290 tree
.SetItemText(selected
, xxx
.treeName())
1291 tree
.SetItemImage(selected
, xxx
.treeImage())
1293 # Set default name for top-level windows
1294 if parent
.__class
__ == xxxMainNode
:
1295 cl
= xxx
.treeObject().__class
__
1296 frame
.maxIDs
[cl
] += 1
1297 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1300 g
.panel
.SetData(xxx
)
1304 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1306 if g
.testWin
and tree
.IsHighlatable(selected
):
1307 if conf
.autoRefresh
:
1308 tree
.needUpdate
= True
1309 tree
.pendingHighLight
= selected
1311 tree
.pendingHighLight
= None
1315 # Expand/collapse subtree
1316 def OnExpand(self
, evt
):
1317 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1318 else: tree
.ExpandAll(tree
.root
)
1319 def OnCollapse(self
, evt
):
1320 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1321 else: tree
.CollapseAll(tree
.root
)
1323 def OnPullDownHighlight(self
, evt
):
1324 menuId
= evt
.GetMenuId()
1326 menu
= evt
.GetEventObject()
1327 help = menu
.GetHelpString(menuId
)
1328 self
.SetStatusText(help)
1330 self
.SetStatusText('')
1332 def OnUpdateUI(self
, evt
):
1333 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1334 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1335 elif evt
.GetId() == wx
.ID_SAVE
:
1336 evt
.Enable(self
.modified
)
1337 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1338 evt
.Enable(tree
.selection
is not None)
1339 elif evt
.GetId() == self
.ID_TEST
:
1340 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1341 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
]:
1342 evt
.Enable(g
.testWin
is not None)
1343 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1344 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1346 def OnIdle(self
, evt
):
1347 if self
.inIdle
: return # Recursive call protection
1351 if conf
.autoRefresh
:
1353 #self.SetStatusText('Refreshing test window...')
1355 tree
.CreateTestWin(g
.testWin
.item
)
1356 #self.SetStatusText('')
1357 tree
.needUpdate
= False
1358 elif tree
.pendingHighLight
:
1360 tree
.HighLight(tree
.pendingHighLight
)
1362 # Remove highlight if any problem
1363 if g
.testWin
and g
.testWin
.highLight
:
1364 g
.testWin
.highLight
.Remove()
1365 tree
.pendingHighLight
= None
1372 def OnIconize(self
, evt
):
1374 conf
.x
, conf
.y
= self
.GetPosition()
1375 conf
.width
, conf
.height
= self
.GetSize()
1377 conf
.sashPos
= self
.splitter
.GetSashPosition()
1379 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1380 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1381 self
.miniFrame
.Show(False)
1383 if not conf
.embedPanel
:
1384 self
.miniFrame
.Show(True)
1387 def OnCloseWindow(self
, evt
):
1388 if not self
.AskSave(): return
1389 if g
.testWin
: g
.testWin
.Destroy()
1390 if not panel
.GetPageCount() == 2:
1391 panel
.page2
.Destroy()
1393 # If we don't do this, page does not get destroyed (a bug?)
1395 if not self
.IsIconized():
1396 conf
.x
, conf
.y
= self
.GetPosition()
1397 if wx
.Platform
== '__WXMAC__':
1398 conf
.width
, conf
.height
= self
.GetClientSize()
1400 conf
.width
, conf
.height
= self
.GetSize()
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 # Mac does not set the correct size
1767 if wx
.Platform
== '__WXMAC__':
1768 frame
.SetClientSize(size
)
1772 plugins
= os
.getenv('XRCEDPATH')
1776 for dir in plugins
.split(':'):
1777 if os
.path
.isdir(dir) and \
1778 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1780 dir = os
.path
.abspath(os
.path
.normpath(dir))
1781 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1784 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1786 print traceback
.print_exc()
1789 # Store important data
1790 frame
.handlers
= getHandlers()[:]
1791 frame
.custom
= g
.pullDownMenu
.custom
[:]
1792 frame
.modules
= sys
.modules
.copy()
1797 # Load file after showing
1800 frame
.open = frame
.Open(args
[0])
1808 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1809 wc
.WriteInt('x', conf
.x
)
1810 wc
.WriteInt('y', conf
.y
)
1811 wc
.WriteInt('width', conf
.width
)
1812 wc
.WriteInt('height', conf
.height
)
1813 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1814 wc
.WriteInt('showTools', conf
.showTools
)
1815 if not conf
.embedPanel
:
1816 wc
.WriteInt('panelX', conf
.panelX
)
1817 wc
.WriteInt('panelY', conf
.panelY
)
1818 wc
.WriteInt('sashPos', conf
.sashPos
)
1819 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1820 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1821 wc
.WriteInt('nopanic', 1)
1822 g
.fileHistory
.Save(wc
)
1824 wc
.DeleteGroup('Prefs')
1825 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1827 ##v = sys.modules['xxx'].xxxSizerItem.defaults_panel
1828 v
= xxx
.xxxSizerItem
.defaults_panel
1829 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1830 ###v = sys.modules['xxx'].xxxSizerItem.defaults_control
1831 v
= xxx
.xxxSizerItem
.defaults_control
1832 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1837 app
= App(0, useBestVisual
=False)
1838 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1844 if __name__
== '__main__':