]>
Commit | Line | Data |
---|---|---|
1f780e48 RD |
1 | #---------------------------------------------------------------------------- |
2 | # Name: DebuggerService.py | |
3 | # Purpose: Debugger Service for Python. | |
4 | # | |
5 | # Author: Matt Fryer | |
6 | # | |
7 | # Created: 12/9/04 | |
8 | # CVS-ID: $Id$ | |
9 | # Copyright: (c) 2004-2005 ActiveGrid, Inc. | |
10 | # License: wxWindows License | |
11 | #---------------------------------------------------------------------------- | |
12 | ||
13 | import wx | |
14 | import wx.lib.intctrl | |
15 | import wx.lib.docview | |
16 | import wx.lib.dialogs | |
17 | import wx.gizmos | |
18 | import wx._core | |
19 | import wx.lib.pydocview | |
20 | import Service | |
21 | import STCTextEditor | |
22 | import CodeEditor | |
23 | import PythonEditor | |
24 | from IDE import ACTIVEGRID_BASE_IDE | |
25 | if not ACTIVEGRID_BASE_IDE: | |
26 | import ProcessModelEditor | |
27 | import wx.lib.scrolledpanel as scrolled | |
28 | import sys | |
29 | import time | |
30 | import SimpleXMLRPCServer | |
31 | import xmlrpclib | |
32 | import os | |
33 | import threading | |
1f780e48 RD |
34 | import Queue |
35 | import SocketServer | |
36 | import ProjectEditor | |
37 | import types | |
38 | from xml.dom.minidom import parse, parseString | |
39 | import bz2 | |
40 | import pickle | |
41 | import DebuggerHarness | |
42 | import traceback | |
43 | import StringIO | |
2eeaec19 | 44 | import UICommon |
1f780e48 | 45 | if wx.Platform == '__WXMSW__': |
b792147d RD |
46 | try: |
47 | import win32api | |
48 | _PYWIN32_INSTALLED = True | |
49 | except ImportError: | |
50 | _PYWIN32_INSTALLED = False | |
1f780e48 RD |
51 | _WINDOWS = True |
52 | else: | |
53 | _WINDOWS = False | |
b792147d RD |
54 | |
55 | if not _WINDOWS or _PYWIN32_INSTALLED: | |
56 | import process | |
57 | ||
1f780e48 RD |
58 | _ = wx.GetTranslation |
59 | ||
60 | _VERBOSE = False | |
61 | _WATCHES_ON = False | |
62 | ||
63 | # Class to read from stdout or stderr and write the result to a text control. | |
64 | # Args: file=file-like object | |
65 | # callback_function= function that takes a single argument, the line of text | |
66 | # read. | |
67 | class OutputReaderThread(threading.Thread): | |
68 | def __init__(self, file, callback_function, callbackOnExit=None, accumulate=True): | |
69 | threading.Thread.__init__(self) | |
70 | self._file = file | |
71 | self._callback_function = callback_function | |
72 | self._keepGoing = True | |
73 | self._lineCount = 0 | |
74 | self._accumulate = accumulate | |
75 | self._callbackOnExit = callbackOnExit | |
26ee3a06 RD |
76 | self.setDaemon(True) |
77 | ||
78 | def __del__(self): | |
79 | # See comment on DebugCommandUI.StopExecution | |
80 | self._keepGoing = False | |
81 | ||
1f780e48 RD |
82 | def run(self): |
83 | file = self._file | |
84 | start = time.time() | |
85 | output = "" | |
86 | while self._keepGoing: | |
87 | try: | |
88 | # This could block--how to handle that? | |
89 | text = file.readline() | |
90 | if text == '' or text == None: | |
91 | self._keepGoing = False | |
26ee3a06 | 92 | elif not self._accumulate and self._keepGoing: |
1f780e48 RD |
93 | self._callback_function(text) |
94 | else: | |
95 | # Should use a buffer? StringIO? | |
96 | output += text | |
97 | # Seems as though the read blocks if we got an error, so, to be | |
98 | # sure that at least some of the exception gets printed, always | |
99 | # send the first hundred lines back as they come in. | |
26ee3a06 | 100 | if self._lineCount < 100 and self._keepGoing: |
1f780e48 RD |
101 | self._callback_function(output) |
102 | self._lineCount += 1 | |
103 | output = "" | |
26ee3a06 | 104 | elif time.time() - start > 0.25 and self._keepGoing: |
1f780e48 RD |
105 | try: |
106 | self._callback_function(output) | |
107 | except wx._core.PyDeadObjectError: | |
108 | # GUI was killed while we were blocked. | |
109 | self._keepGoing = False | |
110 | start = time.time() | |
111 | output = "" | |
26ee3a06 RD |
112 | #except TypeError: |
113 | # pass | |
1f780e48 RD |
114 | except: |
115 | tp, val, tb = sys.exc_info() | |
116 | print "Exception in OutputReaderThread.run():", tp, val | |
117 | self._keepGoing = False | |
118 | if self._callbackOnExit: | |
119 | try: | |
120 | self._callbackOnExit() | |
121 | except wx._core.PyDeadObjectError: | |
122 | pass | |
123 | if _VERBOSE: print "Exiting OutputReaderThread" | |
124 | ||
125 | def AskToStop(self): | |
126 | self._keepGoing = False | |
26ee3a06 | 127 | |
1f780e48 RD |
128 | import wx.lib.newevent |
129 | (UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent() | |
130 | (UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent() | |
131 | ||
132 | class Executor: | |
133 | ||
134 | def GetPythonExecutablePath(): | |
2eeaec19 | 135 | path = UICommon.GetPythonExecPath() |
1f780e48 RD |
136 | if path: |
137 | return path | |
138 | wx.MessageBox(_("To proceed I need to know the location of the python.exe you would like to use.\nTo set this, go to Tools-->Options and use the 'Python' tab to enter a value.\n"), _("Python Executable Location Unknown")) | |
139 | return None | |
140 | GetPythonExecutablePath = staticmethod(GetPythonExecutablePath) | |
141 | ||
142 | def __init__(self, fileName, wxComponent, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None, arg6=None, arg7=None, arg8=None, arg9=None, callbackOnExit=None): | |
143 | self._fileName = fileName | |
144 | self._stdOutCallback = self.OutCall | |
145 | self._stdErrCallback = self.ErrCall | |
146 | self._callbackOnExit = callbackOnExit | |
147 | self._wxComponent = wxComponent | |
148 | path = Executor.GetPythonExecutablePath() | |
149 | self._cmd = '"' + path + '" -u \"' + fileName + '\"' | |
150 | #Better way to do this? Quotes needed for windows file paths. | |
2eeaec19 RD |
151 | def spaceAndQuote(text): |
152 | if text.startswith("\"") and text.endswith("\""): | |
153 | return ' ' + text | |
154 | else: | |
155 | return ' \"' + text + '\"' | |
1f780e48 | 156 | if(arg1 != None): |
2eeaec19 | 157 | self._cmd += spaceAndQuote(arg1) |
1f780e48 | 158 | if(arg2 != None): |
2eeaec19 | 159 | self._cmd += spaceAndQuote(arg2) |
1f780e48 | 160 | if(arg3 != None): |
2eeaec19 | 161 | self._cmd += spaceAndQuote(arg3) |
1f780e48 | 162 | if(arg4 != None): |
2eeaec19 | 163 | self._cmd += spaceAndQuote(arg4) |
1f780e48 | 164 | if(arg5 != None): |
2eeaec19 | 165 | self._cmd += spaceAndQuote(arg5) |
1f780e48 | 166 | if(arg6 != None): |
2eeaec19 | 167 | self._cmd += spaceAndQuote(arg6) |
1f780e48 | 168 | if(arg7 != None): |
2eeaec19 | 169 | self._cmd += spaceAndQuote(arg7) |
1f780e48 | 170 | if(arg8 != None): |
2eeaec19 | 171 | self._cmd += spaceAndQuote(arg8) |
1f780e48 | 172 | if(arg9 != None): |
2eeaec19 | 173 | self._cmd += spaceAndQuote(arg9) |
1f780e48 RD |
174 | |
175 | self._stdOutReader = None | |
176 | self._stdErrReader = None | |
177 | self._process = None | |
178 | ||
179 | def OutCall(self, text): | |
180 | evt = UpdateTextEvent(value = text) | |
181 | wx.PostEvent(self._wxComponent, evt) | |
182 | ||
183 | def ErrCall(self, text): | |
184 | evt = UpdateErrorEvent(value = text) | |
185 | wx.PostEvent(self._wxComponent, evt) | |
186 | ||
187 | def Execute(self, arguments, startIn=None, environment=None): | |
188 | if not startIn: | |
189 | startIn = str(os.getcwd()) | |
190 | startIn = os.path.abspath(startIn) | |
191 | command = self._cmd + ' ' + arguments | |
1f780e48 RD |
192 | self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment) |
193 | # Kick off threads to read stdout and stderr and write them | |
194 | # to our text control. | |
195 | self._stdOutReader = OutputReaderThread(self._process.stdout, self._stdOutCallback, callbackOnExit=self._callbackOnExit) | |
196 | self._stdOutReader.start() | |
197 | self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False) | |
198 | self._stdErrReader.start() | |
26ee3a06 | 199 | |
1f780e48 | 200 | def DoStopExecution(self): |
26ee3a06 | 201 | # See comment on DebugCommandUI.StopExecution |
1f780e48 | 202 | if(self._process != None): |
1f780e48 | 203 | self._stdOutReader.AskToStop() |
1f780e48 | 204 | self._stdErrReader.AskToStop() |
26ee3a06 RD |
205 | try: |
206 | self._process.kill(gracePeriod=2.0) | |
207 | except: | |
208 | pass | |
209 | self._process = None | |
1f780e48 RD |
210 | |
211 | class RunCommandUI(wx.Panel): | |
26ee3a06 RD |
212 | runners = [] |
213 | ||
214 | def ShutdownAllRunners(): | |
215 | # See comment on DebugCommandUI.StopExecution | |
216 | for runner in RunCommandUI.runners: | |
217 | try: | |
218 | runner.StopExecution(None) | |
219 | except wx._core.PyDeadObjectError: | |
220 | pass | |
221 | RunCommandUI.runners = [] | |
222 | ShutdownAllRunners = staticmethod(ShutdownAllRunners) | |
1f780e48 RD |
223 | |
224 | def __init__(self, parent, id, fileName): | |
225 | wx.Panel.__init__(self, parent, id) | |
226 | self._noteBook = parent | |
227 | ||
26ee3a06 RD |
228 | threading._VERBOSE = _VERBOSE |
229 | ||
1f780e48 RD |
230 | self.KILL_PROCESS_ID = wx.NewId() |
231 | self.CLOSE_TAB_ID = wx.NewId() | |
232 | ||
1f780e48 RD |
233 | |
234 | # GUI Initialization follows | |
235 | sizer = wx.BoxSizer(wx.HORIZONTAL) | |
236 | self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" ) | |
237 | tb.SetToolBitmapSize((16,16)) | |
26ee3a06 | 238 | sizer.Add(tb, 0, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL, 1) |
1f780e48 RD |
239 | |
240 | close_bmp = getCloseBitmap() | |
241 | tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window')) | |
242 | wx.EVT_TOOL(self, self.CLOSE_TAB_ID, self.OnToolClicked) | |
243 | ||
244 | stop_bmp = getStopBitmap() | |
245 | tb.AddSimpleTool(self.KILL_PROCESS_ID, stop_bmp, _("Stop the Run.")) | |
246 | wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.OnToolClicked) | |
247 | ||
248 | tb.Realize() | |
249 | self._textCtrl = STCTextEditor.TextCtrl(self, wx.NewId()) #id) | |
250 | sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
251 | self._textCtrl.SetViewLineNumbers(False) | |
252 | self._textCtrl.SetReadOnly(True) | |
253 | if wx.Platform == '__WXMSW__': | |
254 | font = "Courier New" | |
255 | else: | |
256 | font = "Courier" | |
257 | self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font)) | |
258 | self._textCtrl.SetFontColor(wx.BLACK) | |
259 | self._textCtrl.StyleClearAll() | |
260 | ||
261 | #Disabling for now...may interfere with file open. wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick) | |
262 | ||
263 | self.SetSizer(sizer) | |
264 | sizer.Fit(self) | |
265 | ||
26ee3a06 | 266 | self._stopped = False |
1f780e48 RD |
267 | # Executor initialization |
268 | self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished) | |
269 | self.Bind(EVT_UPDATE_STDTEXT, self.AppendText) | |
270 | self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText) | |
271 | ||
26ee3a06 RD |
272 | RunCommandUI.runners.append(self) |
273 | ||
1f780e48 | 274 | def __del__(self): |
26ee3a06 | 275 | # See comment on DebugCommandUI.StopExecution |
1f780e48 RD |
276 | self._executor.DoStopExecution() |
277 | ||
278 | def Execute(self, initialArgs, startIn, environment): | |
279 | self._executor.Execute(initialArgs, startIn, environment) | |
280 | ||
281 | def ExecutorFinished(self): | |
282 | self._tb.EnableTool(self.KILL_PROCESS_ID, False) | |
283 | nb = self.GetParent() | |
284 | for i in range(0,nb.GetPageCount()): | |
285 | if self == nb.GetPage(i): | |
286 | text = nb.GetPageText(i) | |
287 | newText = text.replace("Running", "Finished") | |
288 | nb.SetPageText(i, newText) | |
289 | break | |
290 | ||
291 | def StopExecution(self): | |
26ee3a06 RD |
292 | if not self._stopped: |
293 | self._stopped = True | |
294 | self.Unbind(EVT_UPDATE_STDTEXT) | |
295 | self.Unbind(EVT_UPDATE_ERRTEXT) | |
296 | self._executor.DoStopExecution() | |
1f780e48 RD |
297 | |
298 | def AppendText(self, event): | |
299 | self._textCtrl.SetReadOnly(False) | |
300 | self._textCtrl.AddText(event.value) | |
301 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
302 | self._textCtrl.SetReadOnly(True) | |
303 | ||
304 | def AppendErrorText(self, event): | |
305 | self._textCtrl.SetReadOnly(False) | |
306 | self._textCtrl.SetFontColor(wx.RED) | |
307 | self._textCtrl.StyleClearAll() | |
308 | self._textCtrl.AddText(event.value) | |
309 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
310 | self._textCtrl.SetFontColor(wx.BLACK) | |
311 | self._textCtrl.StyleClearAll() | |
312 | self._textCtrl.SetReadOnly(True) | |
02b800ce RD |
313 | |
314 | def StopAndRemoveUI(self, event): | |
315 | self.StopExecution() | |
316 | self.StopExecution() | |
317 | index = self._noteBook.GetSelection() | |
318 | self._noteBook.GetPage(index).Show(False) | |
319 | self._noteBook.RemovePage(index) | |
1f780e48 RD |
320 | |
321 | #------------------------------------------------------------------------------ | |
322 | # Event handling | |
323 | #----------------------------------------------------------------------------- | |
324 | ||
325 | def OnToolClicked(self, event): | |
326 | id = event.GetId() | |
327 | ||
328 | if id == self.KILL_PROCESS_ID: | |
26ee3a06 | 329 | self.StopExecution() |
1f780e48 RD |
330 | |
331 | elif id == self.CLOSE_TAB_ID: | |
02b800ce | 332 | self.StopAndRemoveUI(event) |
1f780e48 RD |
333 | |
334 | def OnDoubleClick(self, event): | |
335 | # Looking for a stack trace line. | |
336 | lineText, pos = self._textCtrl.GetCurLine() | |
337 | fileBegin = lineText.find("File \"") | |
338 | fileEnd = lineText.find("\", line ") | |
339 | lineEnd = lineText.find(", in ") | |
340 | if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1: | |
341 | # Check the line before the one that was clicked on | |
342 | lineNumber = self._textCtrl.GetCurrentLine() | |
343 | if(lineNumber == 0): | |
344 | return | |
345 | lineText = self._textCtrl.GetLine(lineNumber - 1) | |
346 | fileBegin = lineText.find("File \"") | |
347 | fileEnd = lineText.find("\", line ") | |
348 | lineEnd = lineText.find(", in ") | |
349 | if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1: | |
350 | return | |
351 | ||
352 | filename = lineText[fileBegin + 6:fileEnd] | |
353 | lineNum = int(lineText[fileEnd + 8:lineEnd]) | |
354 | ||
355 | foundView = None | |
356 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
357 | for openDoc in openDocs: | |
358 | if openDoc.GetFilename() == filename: | |
359 | foundView = openDoc.GetFirstView() | |
360 | break | |
361 | ||
362 | if not foundView: | |
363 | doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT) | |
364 | foundView = doc.GetFirstView() | |
365 | ||
366 | if foundView: | |
367 | foundView.GetFrame().SetFocus() | |
368 | foundView.Activate() | |
369 | foundView.GotoLine(lineNum) | |
370 | startPos = foundView.PositionFromLine(lineNum) | |
371 | ||
372 | # FACTOR THIS INTO DocManager | |
373 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
374 | for openDoc in openDocs: | |
02b800ce | 375 | if(isinstance(openDoc, CodeEditor.CodeDocument)): |
1f780e48 RD |
376 | openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() |
377 | ||
378 | foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM) | |
379 | ||
1f780e48 RD |
380 | |
381 | DEFAULT_PORT = 32032 | |
382 | DEFAULT_HOST = 'localhost' | |
383 | PORT_COUNT = 21 | |
384 | ||
385 | class DebugCommandUI(wx.Panel): | |
386 | debuggerPortList = None | |
387 | debuggers = [] | |
388 | ||
389 | def NotifyDebuggersOfBreakpointChange(): | |
390 | for debugger in DebugCommandUI.debuggers: | |
391 | debugger.BreakPointChange() | |
392 | ||
393 | NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange) | |
394 | ||
395 | def DebuggerRunning(): | |
396 | for debugger in DebugCommandUI.debuggers: | |
397 | if debugger._executor: | |
398 | return True | |
399 | return False | |
400 | DebuggerRunning = staticmethod(DebuggerRunning) | |
401 | ||
402 | def ShutdownAllDebuggers(): | |
26ee3a06 | 403 | # See comment on DebugCommandUI.StopExecution |
1f780e48 | 404 | for debugger in DebugCommandUI.debuggers: |
26ee3a06 RD |
405 | try: |
406 | debugger.StopExecution(None) | |
407 | except wx._core.PyDeadObjectError: | |
408 | pass | |
409 | DebugCommandUI.debuggers = [] | |
1f780e48 | 410 | ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers) |
6f1a3f9c | 411 | |
1f780e48 RD |
412 | def GetAvailablePort(): |
413 | for index in range( 0, len(DebugCommandUI.debuggerPortList)): | |
414 | port = DebugCommandUI.debuggerPortList[index] | |
415 | if DebugCommandUI.PortAvailable(port): | |
416 | DebugCommandUI.debuggerPortList.pop(index) | |
417 | return port | |
418 | wx.MessageBox(_("Out of ports for debugging! Please restart the application builder.\nIf that does not work, check for and remove running instances of python."), _("Out of Ports")) | |
419 | assert False, "Out of ports for debugger." | |
420 | ||
421 | GetAvailablePort = staticmethod(GetAvailablePort) | |
422 | ||
423 | def ReturnPortToPool(port): | |
424 | config = wx.ConfigBase_Get() | |
425 | startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) | |
02b800ce RD |
426 | val = int(startingPort) + int(PORT_COUNT) |
427 | if int(port) >= startingPort and (int(port) <= val): | |
428 | DebugCommandUI.debuggerPortList.append(int(port)) | |
1f780e48 RD |
429 | |
430 | ReturnPortToPool = staticmethod(ReturnPortToPool) | |
431 | ||
432 | def PortAvailable(port): | |
433 | config = wx.ConfigBase_Get() | |
434 | hostname = config.Read("DebuggerHostName", DEFAULT_HOST) | |
435 | try: | |
436 | server = AGXMLRPCServer((hostname, port)) | |
437 | server.server_close() | |
438 | if _VERBOSE: print "Port ", str(port), " available." | |
439 | return True | |
440 | except: | |
441 | tp,val,tb = sys.exc_info() | |
442 | if _VERBOSE: traceback.print_exception(tp, val, tb) | |
443 | if _VERBOSE: print "Port ", str(port), " unavailable." | |
444 | return False | |
445 | ||
446 | PortAvailable = staticmethod(PortAvailable) | |
447 | ||
448 | def NewPortRange(): | |
449 | config = wx.ConfigBase_Get() | |
450 | startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) | |
451 | DebugCommandUI.debuggerPortList = range(startingPort, startingPort + PORT_COUNT) | |
452 | NewPortRange = staticmethod(NewPortRange) | |
453 | ||
454 | def __init__(self, parent, id, command, service): | |
455 | # Check for ports before creating the panel. | |
456 | if not DebugCommandUI.debuggerPortList: | |
457 | DebugCommandUI.NewPortRange() | |
458 | self._debuggerPort = str(DebugCommandUI.GetAvailablePort()) | |
459 | self._guiPort = str(DebugCommandUI.GetAvailablePort()) | |
460 | self._debuggerBreakPort = str(DebugCommandUI.GetAvailablePort()) | |
461 | ||
462 | wx.Panel.__init__(self, parent, id) | |
463 | ||
464 | self._parentNoteBook = parent | |
465 | self._command = command | |
1f780e48 RD |
466 | self._service = service |
467 | self._executor = None | |
468 | self.STEP_ID = wx.NewId() | |
469 | self.CONTINUE_ID = wx.NewId() | |
470 | self.STEP_OUT_ID = wx.NewId() | |
471 | self.NEXT_ID = wx.NewId() | |
472 | self.KILL_PROCESS_ID = wx.NewId() | |
473 | self.CLOSE_WINDOW_ID = wx.NewId() | |
474 | self.BREAK_INTO_DEBUGGER_ID = wx.NewId() | |
475 | self.CLEAR_ID = wx.NewId() | |
476 | self.ADD_WATCH_ID = wx.NewId() | |
477 | sizer = wx.BoxSizer(wx.VERTICAL) | |
478 | self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (1000,30), wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT| wx.TB_TEXT, "Debugger" ) | |
479 | sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) | |
480 | tb.SetToolBitmapSize((16,16)) | |
481 | ||
482 | close_bmp = getCloseBitmap() | |
483 | tb.AddSimpleTool( self.CLOSE_WINDOW_ID, close_bmp, _('Close Window')) | |
484 | wx.EVT_TOOL(self, self.CLOSE_WINDOW_ID, self.StopAndRemoveUI) | |
485 | ||
486 | stop_bmp = getStopBitmap() | |
487 | tb.AddSimpleTool( self.KILL_PROCESS_ID, stop_bmp, _("Stop Debugging")) | |
488 | wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.StopExecution) | |
489 | ||
490 | tb.AddSeparator() | |
491 | ||
492 | break_bmp = getBreakBitmap() | |
493 | tb.AddSimpleTool( self.BREAK_INTO_DEBUGGER_ID, break_bmp, _("Break into Debugger")) | |
494 | wx.EVT_TOOL(self, self.BREAK_INTO_DEBUGGER_ID, self.BreakExecution) | |
495 | ||
496 | tb.AddSeparator() | |
497 | ||
498 | continue_bmp = getContinueBitmap() | |
499 | tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution")) | |
500 | wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue) | |
501 | ||
502 | tb.AddSeparator() | |
503 | ||
504 | next_bmp = getNextBitmap() | |
505 | tb.AddSimpleTool( self.NEXT_ID, next_bmp, _("Step to next line")) | |
506 | wx.EVT_TOOL(self, self.NEXT_ID, self.OnNext) | |
507 | ||
508 | step_bmp = getStepInBitmap() | |
509 | tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in")) | |
510 | wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep) | |
511 | ||
512 | stepOut_bmp = getStepReturnBitmap() | |
513 | tb.AddSimpleTool(self.STEP_OUT_ID, stepOut_bmp, _("Stop at function return")) | |
514 | wx.EVT_TOOL(self, self.STEP_OUT_ID, self.OnStepOut) | |
515 | ||
516 | tb.AddSeparator() | |
517 | if _WATCHES_ON: | |
518 | watch_bmp = getAddWatchBitmap() | |
519 | tb.AddSimpleTool(self.ADD_WATCH_ID, watch_bmp, _("Add a watch")) | |
520 | wx.EVT_TOOL(self, self.ADD_WATCH_ID, self.OnAddWatch) | |
521 | tb.AddSeparator() | |
522 | ||
523 | clear_bmp = getClearOutputBitmap() | |
524 | tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane")) | |
525 | wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput) | |
526 | ||
1f780e48 RD |
527 | self.framesTab = None |
528 | self.DisableWhileDebuggerRunning() | |
6f1a3f9c RD |
529 | self.framesTab = self.MakeFramesUI(self, wx.NewId(), None) |
530 | sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
1f780e48 RD |
531 | self._statusBar = wx.StatusBar( self, -1) |
532 | self._statusBar.SetFieldsCount(1) | |
533 | sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) | |
534 | ||
535 | self.SetStatusText("Starting debug...") | |
536 | ||
537 | self.SetSizer(sizer) | |
6f1a3f9c | 538 | tb.Realize() |
1f780e48 RD |
539 | sizer.Fit(self) |
540 | config = wx.ConfigBase_Get() | |
541 | self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST) | |
542 | url = 'http://' + self._debuggerHost + ':' + self._debuggerPort + '/' | |
543 | self._breakURL = 'http://' + self._debuggerHost + ':' + self._debuggerBreakPort + '/' | |
544 | self._callback = DebuggerCallback(self._guiHost, self._guiPort, url, self._breakURL, self) | |
545 | if DebuggerHarness.__file__.find('library.zip') > 0: | |
546 | try: | |
547 | fname = DebuggerHarness.__file__ | |
548 | parts = fname.split('library.zip') | |
549 | path = os.path.join(parts[0],'activegrid', 'tool', 'DebuggerHarness.py') | |
550 | except: | |
551 | tp, val, tb = sys.exc_info() | |
552 | traceback.print_exception(tp, val, tb) | |
553 | ||
554 | else: | |
555 | print "Starting debugger on these ports: %s, %s, %s" % (str(self._debuggerPort) , str(self._guiPort) , str(self._debuggerBreakPort)) | |
556 | path = DebuggerService.ExpandPath(DebuggerHarness.__file__) | |
557 | self._executor = Executor(path, self, self._debuggerHost, \ | |
558 | self._debuggerPort, self._debuggerBreakPort, self._guiHost, self._guiPort, self._command, callbackOnExit=self.ExecutorFinished) | |
559 | ||
560 | self.Bind(EVT_UPDATE_STDTEXT, self.AppendText) | |
561 | self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText) | |
562 | DebugCommandUI.debuggers.append(self) | |
563 | self._stopped = False | |
564 | ||
565 | def OnSingleStep(self, event): | |
566 | self._callback.SingleStep() | |
567 | ||
568 | def OnContinue(self, event): | |
569 | self._callback.Continue() | |
570 | ||
571 | def OnStepOut(self, event): | |
572 | self._callback.Return() | |
573 | ||
574 | def OnNext(self, event): | |
575 | self._callback.Next() | |
576 | ||
577 | def BreakPointChange(self): | |
578 | if not self._stopped: | |
579 | self._callback.pushBreakpoints() | |
6f1a3f9c | 580 | self.framesTab.PopulateBPList() |
1f780e48 RD |
581 | |
582 | def __del__(self): | |
26ee3a06 RD |
583 | # See comment on DebugCommandUI.StopExecution |
584 | self.StopExecution(None) | |
1f780e48 RD |
585 | |
586 | def DisableWhileDebuggerRunning(self): | |
587 | self._tb.EnableTool(self.STEP_ID, False) | |
588 | self._tb.EnableTool(self.CONTINUE_ID, False) | |
589 | self._tb.EnableTool(self.STEP_OUT_ID, False) | |
590 | self._tb.EnableTool(self.NEXT_ID, False) | |
591 | self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, True) | |
592 | if _WATCHES_ON: | |
593 | self._tb.EnableTool(self.ADD_WATCH_ID, False) | |
594 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
595 | for openDoc in openDocs: | |
02b800ce | 596 | if(isinstance(openDoc, CodeEditor.CodeDocument)): |
1f780e48 RD |
597 | openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() |
598 | if self.framesTab: | |
599 | self.framesTab.ClearWhileRunning() | |
1f780e48 RD |
600 | |
601 | def EnableWhileDebuggerStopped(self): | |
602 | self._tb.EnableTool(self.STEP_ID, True) | |
603 | self._tb.EnableTool(self.CONTINUE_ID, True) | |
604 | self._tb.EnableTool(self.STEP_OUT_ID, True) | |
605 | self._tb.EnableTool(self.NEXT_ID, True) | |
606 | if _WATCHES_ON: | |
607 | self._tb.EnableTool(self.ADD_WATCH_ID, True) | |
608 | self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False) | |
1f780e48 RD |
609 | |
610 | def ExecutorFinished(self): | |
611 | if _VERBOSE: print "In ExectorFinished" | |
612 | try: | |
613 | self.DisableAfterStop() | |
614 | except wx._core.PyDeadObjectError: | |
615 | pass | |
616 | try: | |
617 | nb = self.GetParent() | |
618 | for i in range(0, nb.GetPageCount()): | |
619 | if self == nb.GetPage(i): | |
620 | text = nb.GetPageText(i) | |
621 | newText = text.replace("Debugging", "Finished") | |
622 | nb.SetPageText(i, newText) | |
623 | if _VERBOSE: print "In ExectorFinished, changed tab title." | |
624 | break | |
625 | except: | |
626 | if _VERBOSE: print "In ExectorFinished, got exception" | |
627 | ||
628 | def DisableAfterStop(self): | |
629 | self.DisableWhileDebuggerRunning() | |
630 | self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False) | |
631 | self._tb.EnableTool(self.KILL_PROCESS_ID, False) | |
632 | ||
2eeaec19 | 633 | def SynchCurrentLine(self, filename, lineNum, noArrow=False): |
1f780e48 RD |
634 | # FACTOR THIS INTO DocManager |
635 | self.DeleteCurrentLineMarkers() | |
636 | ||
637 | # Filename will be <string> if we're in a bit of code that was executed from | |
638 | # a string (rather than a file). I haven't been able to get the original string | |
639 | # for display. | |
640 | if filename == '<string>': | |
641 | return | |
642 | foundView = None | |
643 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
644 | for openDoc in openDocs: | |
645 | # This ugliness to prevent comparison failing because the drive letter | |
646 | # gets lowercased occasionally. Don't know why that happens or why it | |
647 | # only happens occasionally. | |
648 | if DebuggerService.ComparePaths(openDoc.GetFilename(),filename): | |
649 | foundView = openDoc.GetFirstView() | |
650 | break | |
651 | ||
652 | if not foundView: | |
653 | if _VERBOSE: | |
654 | print "filename=", filename | |
655 | doc = wx.GetApp().GetDocumentManager().CreateDocument(DebuggerService.ExpandPath(filename), wx.lib.docview.DOC_SILENT) | |
656 | foundView = doc.GetFirstView() | |
657 | ||
658 | if foundView: | |
659 | foundView.GetFrame().SetFocus() | |
660 | foundView.Activate() | |
661 | foundView.GotoLine(lineNum) | |
662 | startPos = foundView.PositionFromLine(lineNum) | |
2eeaec19 RD |
663 | |
664 | if not noArrow: | |
665 | foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM) | |
1f780e48 RD |
666 | |
667 | def DeleteCurrentLineMarkers(self): | |
668 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
669 | for openDoc in openDocs: | |
02b800ce | 670 | if(isinstance(openDoc, CodeEditor.CodeDocument)): |
1f780e48 RD |
671 | openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() |
672 | ||
673 | def LoadFramesListXML(self, framesXML): | |
674 | self.framesTab.LoadFramesListXML(framesXML) | |
675 | ||
676 | def SetStatusText(self, text): | |
677 | self._statusBar.SetStatusText(text,0) | |
678 | ||
679 | def Execute(self, initialArgs, startIn, environment): | |
680 | self._callback.start() | |
681 | self._executor.Execute(initialArgs, startIn, environment) | |
682 | self._callback.waitForRPC() | |
683 | ||
684 | def BreakExecution(self, event): | |
685 | self._callback.BreakExecution() | |
686 | ||
687 | ||
688 | def StopExecution(self, event): | |
26ee3a06 RD |
689 | # This is a general comment on shutdown for the running and debugged processes. Basically, the |
690 | # current state of this is the result of trial and error coding. The common problems were memory | |
691 | # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems | |
692 | # to have side-stepped the hung thread issue. Being very careful not to touch things after calling | |
693 | # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there | |
694 | # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send | |
695 | # it on to mfryer@activegrid.com. | |
696 | if not self._stopped: | |
697 | self._stopped = True | |
698 | try: | |
699 | self.DisableAfterStop() | |
700 | except wx._core.PyDeadObjectError: | |
701 | pass | |
702 | try: | |
703 | self._callback.ShutdownServer() | |
704 | except: | |
705 | tp,val,tb = sys.exc_info() | |
706 | traceback.print_exception(tp, val, tb) | |
1f780e48 | 707 | |
26ee3a06 RD |
708 | try: |
709 | self.DeleteCurrentLineMarkers() | |
710 | except: | |
711 | pass | |
712 | try: | |
713 | DebugCommandUI.ReturnPortToPool(self._debuggerPort) | |
714 | DebugCommandUI.ReturnPortToPool(self._guiPort) | |
715 | DebugCommandUI.ReturnPortToPool(self._debuggerBreakPort) | |
716 | except: | |
717 | pass | |
718 | try: | |
719 | if self._executor: | |
720 | self._executor.DoStopExecution() | |
721 | self._executor = None | |
722 | except: | |
723 | tp,val,tb = sys.exc_info() | |
724 | traceback.print_exception(tp, val, tb) | |
1f780e48 RD |
725 | def StopAndRemoveUI(self, event): |
726 | self.StopExecution(None) | |
727 | if self in DebugCommandUI.debuggers: | |
728 | DebugCommandUI.debuggers.remove(self) | |
729 | index = self._parentNoteBook.GetSelection() | |
730 | self._parentNoteBook.GetPage(index).Show(False) | |
6f1a3f9c | 731 | self._parentNoteBook.RemovePage(index) |
1f780e48 RD |
732 | |
733 | def OnAddWatch(self, event): | |
734 | if self.framesTab: | |
735 | self.framesTab.OnWatch(event) | |
6f1a3f9c RD |
736 | |
737 | def MakeFramesUI(self, parent, id, debugger): | |
1f780e48 RD |
738 | panel = FramesUI(parent, id, self) |
739 | return panel | |
740 | ||
1f780e48 | 741 | def AppendText(self, event): |
6f1a3f9c | 742 | self.framesTab.AppendText(event.value) |
1f780e48 RD |
743 | |
744 | def AppendErrorText(self, event): | |
6f1a3f9c RD |
745 | self.framesTab.AppendErrorText(event.value) |
746 | ||
747 | def OnClearOutput(self, event): | |
26ee3a06 | 748 | self.framesTab.ClearOutput(None) |
6f1a3f9c RD |
749 | |
750 | def SwitchToOutputTab(self): | |
751 | self.framesTab.SwitchToOutputTab() | |
1f780e48 RD |
752 | |
753 | class BreakpointsUI(wx.Panel): | |
754 | def __init__(self, parent, id, ui): | |
755 | wx.Panel.__init__(self, parent, id) | |
756 | self._ui = ui | |
757 | self.currentItem = None | |
758 | self.clearBPID = wx.NewId() | |
759 | self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID) | |
760 | self.syncLineID = wx.NewId() | |
761 | self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID) | |
1f780e48 RD |
762 | sizer = wx.BoxSizer(wx.VERTICAL) |
763 | p1 = self | |
764 | self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT) | |
765 | sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
766 | self._bpListCtrl.InsertColumn(0, "File") | |
767 | self._bpListCtrl.InsertColumn(1, "Line") | |
768 | self._bpListCtrl.InsertColumn(2, "Path") | |
769 | self._bpListCtrl.SetColumnWidth(0, 150) | |
770 | self._bpListCtrl.SetColumnWidth(1, 50) | |
771 | self._bpListCtrl.SetColumnWidth(2, 450) | |
772 | self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick) | |
773 | self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl) | |
774 | self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl) | |
6f1a3f9c RD |
775 | |
776 | def OnLeftDoubleClick(event): | |
777 | self.SyncBPLine(event) | |
778 | ||
779 | wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick) | |
1f780e48 RD |
780 | |
781 | self.PopulateBPList() | |
782 | ||
783 | p1.SetSizer(sizer) | |
784 | sizer.Fit(p1) | |
785 | p1.Layout() | |
786 | ||
787 | def PopulateBPList(self): | |
788 | list = self._bpListCtrl | |
789 | list.DeleteAllItems() | |
790 | ||
791 | bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict() | |
792 | index = 0 | |
793 | for fileName in bps.keys(): | |
794 | shortFile = os.path.basename(fileName) | |
795 | lines = bps[fileName] | |
796 | if lines: | |
797 | for line in lines: | |
798 | list.InsertStringItem(index, shortFile) | |
799 | list.SetStringItem(index, 1, str(line)) | |
800 | list.SetStringItem(index, 2, fileName) | |
801 | ||
802 | def OnListRightClick(self, event): | |
803 | menu = wx.Menu() | |
804 | item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint") | |
805 | menu.AppendItem(item) | |
806 | item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line") | |
807 | menu.AppendItem(item) | |
808 | self.PopupMenu(menu, event.GetPosition()) | |
809 | menu.Destroy() | |
810 | ||
811 | def SyncBPLine(self, event): | |
812 | if self.currentItem != -1: | |
813 | list = self._bpListCtrl | |
814 | fileName = list.GetItem(self.currentItem, 2).GetText() | |
815 | lineNumber = list.GetItem(self.currentItem, 1).GetText() | |
2eeaec19 | 816 | self._ui.SynchCurrentLine( fileName, int(lineNumber) , noArrow=True) |
1f780e48 RD |
817 | |
818 | def ClearBreakPoint(self, event): | |
819 | if self.currentItem >= 0: | |
820 | list = self._bpListCtrl | |
821 | fileName = list.GetItem(self.currentItem, 2).GetText() | |
822 | lineNumber = list.GetItem(self.currentItem, 1).GetText() | |
823 | wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName ) | |
824 | ||
825 | def ListItemSelected(self, event): | |
826 | self.currentItem = event.m_itemIndex | |
827 | ||
828 | def ListItemDeselected(self, event): | |
829 | self.currentItem = -1 | |
830 | ||
831 | class Watch: | |
832 | CODE_ALL_FRAMES = 1 | |
833 | CODE_THIS_BLOCK = 2 | |
834 | CODE_THIS_LINE = 4 | |
835 | CODE_RUN_ONCE = 8 | |
836 | ||
837 | def __init__(self, name, command, show_code=CODE_ALL_FRAMES): | |
838 | self._name = name | |
839 | self._command = command | |
840 | self._show_code = show_code | |
841 | ||
842 | class WatchDialog(wx.Dialog): | |
843 | WATCH_ALL_FRAMES = "Watch in all frames" | |
844 | WATCH_THIS_FRAME = "Watch in this frame only" | |
845 | WATCH_ONCE = "Watch once and delete" | |
846 | def __init__(self, parent, title, chain): | |
847 | wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE) | |
848 | self._chain = chain | |
849 | self.label_2 = wx.StaticText(self, -1, "Watch Name:") | |
850 | self._watchNameTextCtrl = wx.TextCtrl(self, -1, "") | |
851 | self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT) | |
852 | self._watchValueTextCtrl = wx.TextCtrl(self, -1, "") | |
853 | self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)") | |
854 | self.radio_box_1 = wx.RadioBox(self, -1, "Watch Information", choices=[WatchDialog.WATCH_ALL_FRAMES, WatchDialog.WATCH_THIS_FRAME, WatchDialog.WATCH_ONCE], majorDimension=0, style=wx.RA_SPECIFY_ROWS) | |
855 | ||
02b800ce | 856 | self._okButton = wx.Button(self, wx.ID_OK, "OK") |
1f780e48 RD |
857 | self._okButton.SetDefault() |
858 | self._okButton.SetHelpText(_("The OK button completes the dialog")) | |
859 | def OnOkClick(event): | |
860 | if self._watchNameTextCtrl.GetValue() == "": | |
861 | wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch")) | |
862 | return | |
863 | if self._watchValueTextCtrl.GetValue() == "": | |
864 | wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch")) | |
865 | return | |
866 | self.EndModal(wx.ID_OK) | |
867 | self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton) | |
868 | ||
02b800ce | 869 | self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel")) |
1f780e48 RD |
870 | self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog.")) |
871 | ||
872 | self.__set_properties() | |
873 | self.__do_layout() | |
874 | ||
875 | def GetSettings(self): | |
876 | return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce() | |
877 | ||
878 | def GetSendFrame(self): | |
879 | return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection()) | |
880 | ||
881 | def GetRunOnce(self): | |
882 | return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection()) | |
883 | ||
884 | def __set_properties(self): | |
885 | self.SetTitle("Add a Watch") | |
886 | #self.SetSize((400, 250)) | |
887 | self.radio_box_1.SetSelection(0) | |
888 | ||
889 | def __do_layout(self): | |
890 | sizer_1 = wx.BoxSizer(wx.VERTICAL) | |
891 | grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5) | |
892 | grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5) | |
893 | grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) | |
894 | grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0) | |
895 | grid_sizer_2.AddGrowableCol(1) | |
896 | sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0) | |
897 | grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) | |
898 | grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0) | |
899 | grid_sizer_4.AddGrowableCol(1) | |
900 | grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) | |
901 | sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0) | |
902 | sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0) | |
903 | ||
904 | box = wx.BoxSizer(wx.HORIZONTAL) | |
905 | box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) | |
906 | box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) | |
907 | sizer_1.Add(box, 1, wx.EXPAND, 0) | |
1f780e48 RD |
908 | self.SetSizer(sizer_1) |
909 | self.Layout() | |
910 | ||
911 | class FramesUI(wx.SplitterWindow): | |
912 | def __init__(self, parent, id, ui): | |
913 | wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D) | |
914 | self._ui = ui | |
1f780e48 | 915 | self._p1 = p1 = wx.ScrolledWindow(self, -1) |
1f780e48 | 916 | |
6f1a3f9c RD |
917 | sizer = wx.BoxSizer(wx.HORIZONTAL) |
918 | framesLabel = wx.StaticText(self, -1, "Stack Frame:") | |
919 | sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2) | |
920 | ||
921 | self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "]) | |
922 | sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
923 | self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick) | |
924 | self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl) | |
1f780e48 RD |
925 | |
926 | sizer2 = wx.BoxSizer(wx.VERTICAL) | |
6f1a3f9c RD |
927 | p1.SetSizer(sizer2) |
928 | ||
929 | self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT) | |
1f780e48 | 930 | self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick) |
6f1a3f9c RD |
931 | sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) |
932 | sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
1f780e48 RD |
933 | tree = self._treeCtrl |
934 | tree.AddColumn("Thing") | |
935 | tree.AddColumn("Value") | |
936 | tree.SetMainColumn(0) # the one with the tree in it... | |
937 | tree.SetColumnWidth(0, 175) | |
938 | tree.SetColumnWidth(1, 355) | |
939 | self._root = tree.AddRoot("Frame") | |
940 | tree.SetItemText(self._root, "", 1) | |
6f1a3f9c RD |
941 | tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback) |
942 | ||
943 | self._p2 = p2 = wx.Window(self, -1) | |
944 | sizer3 = wx.BoxSizer(wx.HORIZONTAL) | |
945 | p2.SetSizer(sizer3) | |
946 | p2.Bind(wx.EVT_SIZE, self.OnSize) | |
947 | self._notebook = wx.Notebook(p2, -1, size=(20,20)) | |
948 | self._notebook.Hide() | |
949 | sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) | |
950 | self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId()) | |
26ee3a06 | 951 | self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId()) |
6f1a3f9c RD |
952 | self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId()) |
953 | self._notebook.AddPage(self.consoleTab, "Output") | |
26ee3a06 | 954 | self._notebook.AddPage(self.inspectConsoleTab, "Interact") |
6f1a3f9c | 955 | self._notebook.AddPage(self.breakPointsTab, "Break Points") |
1f780e48 RD |
956 | |
957 | self.SetMinimumPaneSize(20) | |
6f1a3f9c | 958 | self.SplitVertically(p1, p2, 550) |
1f780e48 | 959 | self.currentItem = None |
6f1a3f9c RD |
960 | self._notebook.Show(True) |
961 | ||
962 | def PopulateBPList(self): | |
963 | self.breakPointsTab.PopulateBPList() | |
964 | ||
965 | def OnSize(self, event): | |
966 | self._notebook.SetSize(self._p2.GetSize()) | |
967 | ||
968 | def MakeConsoleTab(self, parent, id): | |
969 | panel = wx.Panel(parent, id) | |
970 | sizer = wx.BoxSizer(wx.HORIZONTAL) | |
971 | self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId()) | |
972 | sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2) | |
973 | self._textCtrl.SetViewLineNumbers(False) | |
974 | self._textCtrl.SetReadOnly(True) | |
975 | if wx.Platform == '__WXMSW__': | |
976 | font = "Courier New" | |
977 | else: | |
978 | font = "Courier" | |
979 | self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font)) | |
980 | self._textCtrl.SetFontColor(wx.BLACK) | |
981 | self._textCtrl.StyleClearAll() | |
982 | panel.SetSizer(sizer) | |
983 | #sizer.Fit(panel) | |
984 | ||
985 | return panel | |
02b800ce RD |
986 | |
987 | def ReplaceLastLine(self, command): | |
988 | line = self._interCtrl.GetLineCount() - 1 | |
989 | self._interCtrl.GotoLine(line) | |
990 | start = self._interCtrl.GetCurrentPos() | |
991 | self._interCtrl.SetTargetStart(start) | |
992 | end = self._interCtrl.GetLineEndPosition(line) | |
993 | self._interCtrl.SetTargetEnd(end) | |
994 | self._interCtrl.ReplaceTarget(">>> " + command) | |
995 | self._interCtrl.GotoLine(line) | |
996 | self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line)) | |
997 | ||
998 | def ExecuteCommand(self, command): | |
999 | if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]: | |
1000 | self.command_list.append(command) | |
1001 | self.command_index = len(self.command_list) - 1 | |
1002 | retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command) | |
1003 | self._interCtrl.AddText("\n" + str(retval)) | |
1004 | self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount()) | |
1005 | # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items. | |
1006 | self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection()) | |
6f1a3f9c RD |
1007 | |
1008 | def MakeInspectConsoleTab(self, parent, id): | |
26ee3a06 RD |
1009 | self.command_list = [] |
1010 | self.command_index = 0 | |
6f1a3f9c | 1011 | |
26ee3a06 RD |
1012 | def OnKeyPressed(event): |
1013 | key = event.KeyCode() | |
1014 | if key == wx.WXK_DELETE or key == wx.WXK_BACK: | |
1015 | if self._interCtrl.GetLine(self._interCtrl.GetCurrentLine()) == ">>> ": | |
1016 | return | |
1017 | elif key == wx.WXK_RETURN: | |
1018 | command = self._interCtrl.GetLine(self._interCtrl.GetCurrentLine())[4:] | |
02b800ce | 1019 | self.ExecuteCommand(command) |
26ee3a06 RD |
1020 | self._interCtrl.AddText("\n>>> ") |
1021 | return | |
1022 | elif key == wx.WXK_UP: | |
1023 | if not len(self.command_list): | |
1024 | return | |
02b800ce | 1025 | self.ReplaceLastLine(self.command_list[self.command_index]) |
26ee3a06 RD |
1026 | if self.command_index == 0: |
1027 | self.command_index = len(self.command_list) - 1 | |
1028 | else: | |
1029 | self.command_index = self.command_index - 1 | |
1030 | return | |
1031 | elif key == wx.WXK_DOWN: | |
1032 | if not len(self.command_list): | |
1033 | return | |
1034 | if self.command_index < len(self.command_list) - 1: | |
1035 | self.command_index = self.command_index + 1 | |
1036 | else: | |
1037 | self.command_index = 0 | |
02b800ce | 1038 | self.ReplaceLastLine(self.command_list[self.command_index]) |
26ee3a06 RD |
1039 | return |
1040 | event.Skip() | |
1041 | ||
1042 | try: | |
1043 | panel = wx.Panel(parent, id) | |
6f1a3f9c | 1044 | sizer = wx.BoxSizer(wx.HORIZONTAL) |
26ee3a06 RD |
1045 | self._interCtrl = STCTextEditor.TextCtrl(panel, wx.NewId()) |
1046 | sizer.Add(self._interCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2) | |
1047 | self._interCtrl.SetViewLineNumbers(False) | |
6f1a3f9c RD |
1048 | if wx.Platform == '__WXMSW__': |
1049 | font = "Courier New" | |
1050 | else: | |
1051 | font = "Courier" | |
26ee3a06 RD |
1052 | self._interCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font)) |
1053 | self._interCtrl.SetFontColor(wx.BLACK) | |
1054 | self._interCtrl.StyleClearAll() | |
1055 | wx.EVT_KEY_DOWN(self._interCtrl, OnKeyPressed) | |
1056 | self._interCtrl.AddText(">>> ") | |
6f1a3f9c RD |
1057 | panel.SetSizer(sizer) |
1058 | except: | |
1059 | tp, val, tb = sys.exc_info() | |
1060 | traceback.print_exception(tp, val, tb) | |
1061 | ||
1062 | return panel | |
1063 | ||
1064 | def MakeBreakPointsTab(self, parent, id): | |
1065 | panel = BreakpointsUI(parent, id, self._ui) | |
1066 | return panel | |
1f780e48 RD |
1067 | |
1068 | def OnRightClick(self, event): | |
1069 | #Refactor this... | |
1070 | self._introspectItem = event.GetItem() | |
1071 | self._parentChain = self.GetItemChain(event.GetItem()) | |
1072 | watchOnly = len(self._parentChain) < 1 | |
1073 | if not _WATCHES_ON and watchOnly: | |
1074 | return | |
1075 | menu = wx.Menu() | |
1f780e48 RD |
1076 | if _WATCHES_ON: |
1077 | if not hasattr(self, "watchID"): | |
1078 | self.watchID = wx.NewId() | |
1079 | self.Bind(wx.EVT_MENU, self.OnWatch, id=self.watchID) | |
1080 | item = wx.MenuItem(menu, self.watchID, "Create a Watch") | |
1081 | menu.AppendItem(item) | |
1082 | menu.AppendSeparator() | |
1083 | if not watchOnly: | |
1084 | if not hasattr(self, "viewID"): | |
1085 | self.viewID = wx.NewId() | |
1086 | self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID) | |
1087 | item = wx.MenuItem(menu, self.viewID, "View in Dialog") | |
1088 | menu.AppendItem(item) | |
02b800ce RD |
1089 | if not hasattr(self, "toInteractID"): |
1090 | self.toInteractID = wx.NewId() | |
1091 | self.Bind(wx.EVT_MENU, self.OnSendToInteract, id=self.toInteractID) | |
1092 | item = wx.MenuItem(menu, self.toInteractID, "Send to Interact") | |
1093 | menu.AppendItem(item) | |
1094 | ||
1f780e48 RD |
1095 | offset = wx.Point(x=0, y=20) |
1096 | menuSpot = event.GetPoint() + offset | |
1097 | self._treeCtrl.PopupMenu(menu, menuSpot) | |
1098 | menu.Destroy() | |
1099 | self._parentChain = None | |
1100 | self._introspectItem = None | |
1101 | ||
1102 | def GetItemChain(self, item): | |
1103 | parentChain = [] | |
1104 | if item: | |
1105 | if _VERBOSE: print 'Exploding: %s' % self._treeCtrl.GetItemText(item, 0) | |
1106 | while item != self._root: | |
1107 | text = self._treeCtrl.GetItemText(item, 0) | |
1108 | if _VERBOSE: print "Appending ", text | |
1109 | parentChain.append(text) | |
1110 | item = self._treeCtrl.GetItemParent(item) | |
1111 | parentChain.reverse() | |
1112 | return parentChain | |
1113 | ||
1114 | def OnView(self, event): | |
1115 | title = self._treeCtrl.GetItemText(self._introspectItem,0) | |
1116 | value = self._treeCtrl.GetItemText(self._introspectItem,1) | |
1117 | dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER) | |
1118 | dlg.Show() | |
02b800ce RD |
1119 | |
1120 | def OnSendToInteract(self, event): | |
1121 | value = "" | |
1122 | prevItem = "" | |
1123 | for item in self._parentChain: | |
1124 | ||
1125 | if item.find(prevItem + '[') != -1: | |
1126 | value += item[item.find('['):] | |
1127 | continue | |
1128 | if value != "": | |
1129 | value = value + '.' | |
1130 | if item == 'globals': | |
1131 | item = 'globals()' | |
1132 | if item != 'locals': | |
1133 | value += item | |
1134 | prevItem = item | |
1135 | print value | |
1136 | self.ReplaceLastLine(value) | |
1137 | self.ExecuteCommand(value) | |
1138 | ||
1f780e48 RD |
1139 | def OnWatch(self, event): |
1140 | try: | |
1141 | if hasattr(self, '_parentChain'): | |
1142 | wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain) | |
1143 | else: | |
1144 | wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None) | |
02b800ce | 1145 | wd.CenterOnParent() |
1f780e48 RD |
1146 | if wd.ShowModal() == wx.ID_OK: |
1147 | name, text, send_frame, run_once = wd.GetSettings() | |
1148 | if send_frame: | |
1149 | frameNode = self._stack[int(self.currentItem)] | |
1150 | message = frameNode.getAttribute("message") | |
1151 | else: | |
1152 | message = "" | |
1153 | binType = self._ui._callback._debuggerServer.add_watch(name, text, message, run_once) | |
1154 | xmldoc = bz2.decompress(binType.data) | |
1155 | domDoc = parseString(xmldoc) | |
1156 | nodeList = domDoc.getElementsByTagName('watch') | |
1157 | if len(nodeList) == 1: | |
1158 | watchValue = nodeList.item(0).getAttribute("message") | |
02b800ce | 1159 | wd.Destroy() |
1f780e48 RD |
1160 | except: |
1161 | tp, val, tb = sys.exc_info() | |
1162 | traceback.print_exception(tp, val, tb) | |
1163 | ||
1164 | def OnIntrospect(self, event): | |
1165 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
1166 | ||
1167 | try: | |
6f1a3f9c | 1168 | list = self._framesChoiceCtrl |
1f780e48 RD |
1169 | frameNode = self._stack[int(self.currentItem)] |
1170 | message = frameNode.getAttribute("message") | |
1171 | binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain) | |
1172 | xmldoc = bz2.decompress(binType.data) | |
1f780e48 | 1173 | domDoc = parseString(xmldoc) |
6f1a3f9c | 1174 | #wx.MessageBox(xmldoc, "result of introspection") |
1f780e48 RD |
1175 | nodeList = domDoc.getElementsByTagName('replacement') |
1176 | replacementNode = nodeList.item(0) | |
1177 | if len(replacementNode.childNodes): | |
1178 | thingToWalk = replacementNode.childNodes.item(0) | |
1179 | tree = self._treeCtrl | |
1180 | parent = tree.GetItemParent(self._introspectItem) | |
1181 | treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem) | |
02b800ce RD |
1182 | if thingToWalk.getAttribute('name').find('[') == -1: |
1183 | self._treeCtrl.SortChildren(treeNode) | |
6f1a3f9c | 1184 | self._treeCtrl.Expand(treeNode) |
1f780e48 RD |
1185 | tree.Delete(self._introspectItem) |
1186 | except: | |
1187 | tp,val,tb = sys.exc_info() | |
1188 | traceback.print_exception(tp, val, tb) | |
1189 | ||
1190 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
1191 | ||
1f780e48 | 1192 | def ClearWhileRunning(self): |
6f1a3f9c RD |
1193 | list = self._framesChoiceCtrl |
1194 | list.Clear() | |
1195 | list.Enable(False) | |
1196 | tree = self._treeCtrl | |
1197 | root = self._root | |
1198 | tree.DeleteChildren(root) | |
26ee3a06 | 1199 | self._interCtrl.Enable(False) |
6f1a3f9c RD |
1200 | |
1201 | #tree.Hide() | |
1f780e48 RD |
1202 | |
1203 | def OnListRightClick(self, event): | |
1204 | if not hasattr(self, "syncFrameID"): | |
1205 | self.syncFrameID = wx.NewId() | |
1206 | self.Bind(wx.EVT_MENU, self.OnSyncFrame, id=self.syncFrameID) | |
1207 | menu = wx.Menu() | |
1208 | item = wx.MenuItem(menu, self.syncFrameID, "Goto Source Line") | |
1209 | menu.AppendItem(item) | |
1210 | self.PopupMenu(menu, event.GetPosition()) | |
1211 | menu.Destroy() | |
1212 | ||
1213 | def OnSyncFrame(self, event): | |
6f1a3f9c | 1214 | list = self._framesChoiceCtrl |
1f780e48 RD |
1215 | frameNode = self._stack[int(self.currentItem)] |
1216 | file = frameNode.getAttribute("file") | |
1217 | line = frameNode.getAttribute("line") | |
1218 | self._ui.SynchCurrentLine( file, int(line) ) | |
1219 | ||
1220 | def LoadFramesListXML(self, framesXML): | |
1221 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
26ee3a06 RD |
1222 | self._interCtrl.Enable(True) |
1223 | ||
1f780e48 RD |
1224 | try: |
1225 | domDoc = parseString(framesXML) | |
6f1a3f9c RD |
1226 | list = self._framesChoiceCtrl |
1227 | list.Clear() | |
1f780e48 RD |
1228 | self._stack = [] |
1229 | nodeList = domDoc.getElementsByTagName('frame') | |
1230 | frame_count = -1 | |
1231 | for index in range(0, nodeList.length): | |
1232 | frameNode = nodeList.item(index) | |
1233 | message = frameNode.getAttribute("message") | |
6f1a3f9c | 1234 | list.Append(message) |
1f780e48 RD |
1235 | self._stack.append(frameNode) |
1236 | frame_count += 1 | |
6f1a3f9c RD |
1237 | index = len(self._stack) - 1 |
1238 | list.SetSelection(index) | |
26ee3a06 | 1239 | |
6f1a3f9c RD |
1240 | node = self._stack[index] |
1241 | self.currentItem = index | |
1242 | self.PopulateTreeFromFrameNode(node) | |
1243 | self.OnSyncFrame(None) | |
1244 | ||
1f780e48 RD |
1245 | self._p1.FitInside() |
1246 | frameNode = nodeList.item(index) | |
1247 | file = frameNode.getAttribute("file") | |
1248 | line = frameNode.getAttribute("line") | |
1249 | self._ui.SynchCurrentLine( file, int(line) ) | |
1250 | except: | |
1251 | tp,val,tb=sys.exc_info() | |
1252 | traceback.print_exception(tp, val, tb) | |
1253 | ||
1254 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
1255 | ||
1f780e48 RD |
1256 | |
1257 | def ListItemSelected(self, event): | |
26ee3a06 RD |
1258 | self.PopulateTreeFromFrameMessage(event.GetString()) |
1259 | self.OnSyncFrame(None) | |
1260 | ||
1261 | def PopulateTreeFromFrameMessage(self, message): | |
6f1a3f9c RD |
1262 | index = 0 |
1263 | for node in self._stack: | |
1264 | if node.getAttribute("message") == message: | |
26ee3a06 RD |
1265 | binType = self._ui._callback._debuggerServer.request_frame_document(message) |
1266 | xmldoc = bz2.decompress(binType.data) | |
1267 | domDoc = parseString(xmldoc) | |
1268 | nodeList = domDoc.getElementsByTagName('frame') | |
6f1a3f9c | 1269 | self.currentItem = index |
26ee3a06 RD |
1270 | if len(nodeList): |
1271 | self.PopulateTreeFromFrameNode(nodeList[0]) | |
6f1a3f9c RD |
1272 | return |
1273 | index = index + 1 | |
1274 | ||
1f780e48 | 1275 | def PopulateTreeFromFrameNode(self, frameNode): |
6f1a3f9c RD |
1276 | list = self._framesChoiceCtrl |
1277 | list.Enable(True) | |
1f780e48 | 1278 | tree = self._treeCtrl |
6f1a3f9c | 1279 | #tree.Show(True) |
1f780e48 RD |
1280 | root = self._root |
1281 | tree.DeleteChildren(root) | |
1282 | children = frameNode.childNodes | |
1283 | firstChild = None | |
1284 | for index in range(0, children.length): | |
1285 | subNode = children.item(index) | |
1286 | treeNode = self.AppendSubTreeFromNode(subNode, subNode.getAttribute('name'), root) | |
1287 | if not firstChild: | |
1288 | firstChild = treeNode | |
1289 | tree.Expand(root) | |
26ee3a06 RD |
1290 | if firstChild: |
1291 | tree.Expand(firstChild) | |
1f780e48 | 1292 | self._p2.FitInside() |
6f1a3f9c RD |
1293 | |
1294 | def IntrospectCallback(self, event): | |
1295 | tree = self._treeCtrl | |
1296 | item = event.GetItem() | |
1297 | if _VERBOSE: | |
1298 | print "In introspectCallback item is %s, pydata is %s" % (event.GetItem(), tree.GetPyData(item)) | |
1299 | if tree.GetPyData(item) != "Introspect": | |
1300 | event.Skip() | |
1301 | return | |
1302 | self._introspectItem = item | |
1303 | self._parentChain = self.GetItemChain(item) | |
1304 | self.OnIntrospect(event) | |
1305 | event.Skip() | |
1f780e48 RD |
1306 | |
1307 | def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None): | |
1308 | tree = self._treeCtrl | |
1309 | if insertBefore != None: | |
1310 | treeNode = tree.InsertItem(parent, insertBefore, name) | |
1311 | else: | |
1312 | treeNode = tree.AppendItem(parent, name) | |
1313 | children = node.childNodes | |
6f1a3f9c RD |
1314 | intro = node.getAttribute('intro') |
1315 | ||
1316 | if intro == "True": | |
1317 | tree.SetItemHasChildren(treeNode, True) | |
1318 | tree.SetPyData(treeNode, "Introspect") | |
1319 | if node.getAttribute("value"): | |
1f780e48 RD |
1320 | tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1) |
1321 | for index in range(0, children.length): | |
1322 | subNode = children.item(index) | |
1323 | if self.HasChildren(subNode): | |
1324 | self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode) | |
1325 | else: | |
1326 | name = subNode.getAttribute("name") | |
1327 | value = self.StripOuterSingleQuotes(subNode.getAttribute("value")) | |
1328 | n = tree.AppendItem(treeNode, name) | |
1329 | tree.SetItemText(n, value, 1) | |
6f1a3f9c RD |
1330 | intro = subNode.getAttribute('intro') |
1331 | if intro == "True": | |
1332 | tree.SetItemHasChildren(n, True) | |
1333 | tree.SetPyData(n, "Introspect") | |
02b800ce RD |
1334 | if name.find('[') == -1: |
1335 | self._treeCtrl.SortChildren(treeNode) | |
1f780e48 RD |
1336 | return treeNode |
1337 | ||
1338 | def StripOuterSingleQuotes(self, string): | |
1339 | if string.startswith("'") and string.endswith("'"): | |
6f1a3f9c RD |
1340 | retval = string[1:-1] |
1341 | elif string.startswith("\"") and string.endswith("\""): | |
1342 | retval = string[1:-1] | |
1f780e48 | 1343 | else: |
6f1a3f9c RD |
1344 | retval = string |
1345 | if retval.startswith("u'") and retval.endswith("'"): | |
1346 | retval = retval[1:] | |
1347 | return retval | |
1f780e48 RD |
1348 | |
1349 | def HasChildren(self, node): | |
1350 | try: | |
1351 | return node.childNodes.length > 0 | |
1352 | except: | |
1353 | tp,val,tb=sys.exc_info() | |
1354 | return False | |
6f1a3f9c RD |
1355 | |
1356 | def AppendText(self, text): | |
1357 | self._textCtrl.SetReadOnly(False) | |
1358 | self._textCtrl.AddText(text) | |
1359 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
1360 | self._textCtrl.SetReadOnly(True) | |
1361 | ||
1362 | def AppendErrorText(self, text): | |
1363 | self._textCtrl.SetReadOnly(False) | |
1364 | self._textCtrl.SetFontColor(wx.RED) | |
1365 | self._textCtrl.StyleClearAll() | |
1366 | self._textCtrl.AddText(text) | |
1367 | self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount()) | |
1368 | self._textCtrl.SetFontColor(wx.BLACK) | |
1369 | self._textCtrl.StyleClearAll() | |
1370 | self._textCtrl.SetReadOnly(True) | |
1371 | ||
1372 | def ClearOutput(self, event): | |
1373 | self._textCtrl.SetReadOnly(False) | |
1374 | self._textCtrl.ClearAll() | |
1375 | self._textCtrl.SetReadOnly(True) | |
1376 | ||
1377 | def SwitchToOutputTab(self): | |
1378 | self._notebook.SetSelection(0) | |
1379 | ||
1f780e48 RD |
1380 | class DebuggerView(Service.ServiceView): |
1381 | ||
1382 | #---------------------------------------------------------------------------- | |
1383 | # Overridden methods | |
1384 | #---------------------------------------------------------------------------- | |
1385 | ||
1386 | def __init__(self, service): | |
1387 | Service.ServiceView.__init__(self, service) | |
1388 | ||
1389 | def _CreateControl(self, parent, id): | |
1390 | return None | |
1391 | ||
1392 | #------------------------------------------------------------------------------ | |
1393 | # Event handling | |
1394 | #----------------------------------------------------------------------------- | |
1395 | ||
1396 | def OnToolClicked(self, event): | |
1397 | self.GetFrame().ProcessEvent(event) | |
26ee3a06 RD |
1398 | |
1399 | def ProcessUpdateUIEvent(self, event): | |
1400 | return False | |
1401 | ||
1402 | def ProcessEvent(self, event): | |
1403 | return False | |
1404 | ||
1f780e48 RD |
1405 | #------------------------------------------------------------------------------ |
1406 | # Class methods | |
1407 | #----------------------------------------------------------------------------- | |
1408 | ||
1409 | class Interaction: | |
1410 | def __init__(self, message, framesXML, info=None, quit=False): | |
1411 | self._framesXML = framesXML | |
1412 | self._message = message | |
1413 | self._info = info | |
1414 | self._quit = quit | |
1415 | ||
1416 | def getFramesXML(self): | |
1417 | return self._framesXML | |
1418 | ||
1419 | def getMessage(self): | |
1420 | return self._message | |
1421 | ||
1422 | def getInfo(self): | |
1423 | return self._info | |
1424 | ||
1425 | def getQuit(self): | |
1426 | return self._quit | |
1427 | ||
1428 | class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): | |
1429 | def __init__(self, address, logRequests=0): | |
1430 | SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests) | |
1431 | ||
1432 | class RequestHandlerThread(threading.Thread): | |
1433 | def __init__(self, queue, address): | |
1434 | threading.Thread.__init__(self) | |
1435 | self._keepGoing = True | |
1436 | self._queue = queue | |
1437 | self._address = address | |
1438 | self._server = AGXMLRPCServer(self._address,logRequests=0) | |
1439 | self._server.register_function(self.interaction) | |
1440 | self._server.register_function(self.quit) | |
1441 | self._server.register_function(self.dummyOperation) | |
1442 | if _VERBOSE: print "RequestHandlerThread on fileno %s" % str(self._server.fileno()) | |
1443 | ||
1444 | def run(self): | |
1445 | while self._keepGoing: | |
1446 | try: | |
1447 | self._server.handle_request() | |
1448 | except: | |
1449 | tp, val, tb = sys.exc_info() | |
1450 | traceback.print_exception(tp, val, tb) | |
1451 | self._keepGoing = False | |
1452 | if _VERBOSE: print "Exiting Request Handler Thread." | |
1453 | ||
1454 | def interaction(self, message, frameXML, info): | |
1455 | if _VERBOSE: print "In RequestHandlerThread.interaction -- adding to queue" | |
1456 | interaction = Interaction(message, frameXML, info) | |
1457 | self._queue.put(interaction) | |
1458 | return "" | |
1459 | ||
1460 | def quit(self): | |
1461 | interaction = Interaction(None, None, info=None, quit=True) | |
1462 | self._queue.put(interaction) | |
1463 | return "" | |
1464 | ||
1465 | def dummyOperation(self): | |
1466 | return "" | |
1467 | ||
1468 | def AskToStop(self): | |
1469 | self._keepGoing = False | |
1470 | if type(self._server) is not types.NoneType: | |
1471 | try: | |
1472 | # This is a really ugly way to make sure this thread isn't blocked in | |
1473 | # handle_request. | |
1474 | url = 'http://' + self._address[0] + ':' + str(self._address[1]) + '/' | |
1475 | tempServer = xmlrpclib.ServerProxy(url, allow_none=1) | |
1476 | tempServer.dummyOperation() | |
1477 | except: | |
1478 | tp, val, tb = sys.exc_info() | |
1479 | traceback.print_exception(tp, val, tb) | |
1480 | self._server.server_close() | |
1481 | ||
1482 | ||
1483 | class RequestBreakThread(threading.Thread): | |
1484 | def __init__(self, server, interrupt=False, pushBreakpoints=False, breakDict=None, kill=False): | |
1485 | threading.Thread.__init__(self) | |
1486 | self._server = server | |
1487 | ||
1488 | self._interrupt = interrupt | |
1489 | self._pushBreakpoints = pushBreakpoints | |
1490 | self._breakDict = breakDict | |
1491 | self._kill = kill | |
1492 | ||
1493 | def run(self): | |
1494 | try: | |
1495 | if _VERBOSE: print "RequestBreakThread, before call" | |
1496 | if self._interrupt: | |
1497 | self._server.break_requested() | |
1498 | if self._pushBreakpoints: | |
1499 | self._server.update_breakpoints(xmlrpclib.Binary(pickle.dumps(self._breakDict))) | |
1500 | if self._kill: | |
1501 | try: | |
1502 | self._server.die() | |
1503 | except: | |
1504 | pass | |
1505 | if _VERBOSE: print "RequestBreakThread, after call" | |
1506 | except: | |
1507 | tp,val,tb = sys.exc_info() | |
1508 | traceback.print_exception(tp, val, tb) | |
1509 | ||
1510 | class DebuggerOperationThread(threading.Thread): | |
1511 | def __init__(self, function): | |
1512 | threading.Thread.__init__(self) | |
1513 | self._function = function | |
1514 | ||
1515 | def run(self): | |
1516 | if _VERBOSE: print "In DOT, before call" | |
1517 | try: | |
1518 | self._function() | |
1519 | except: | |
1520 | tp,val,tb = sys.exc_info() | |
1521 | traceback.print_exception(tp, val, tb) | |
1522 | if _VERBOSE: print "In DOT, after call" | |
1523 | ||
1524 | class DebuggerCallback: | |
1525 | ||
1526 | def __init__(self, host, port, debugger_url, break_url, debuggerUI): | |
1527 | if _VERBOSE: print "+++++++ Creating server on port, ", str(port) | |
1528 | ||
1529 | self._queue = Queue.Queue(50) | |
1530 | self._host = host | |
1531 | self._port = int(port) | |
1532 | threading._VERBOSE = _VERBOSE | |
1533 | self._serverHandlerThread = RequestHandlerThread(self._queue, (self._host, self._port)) | |
1534 | ||
1535 | self._debugger_url = debugger_url | |
1536 | self._debuggerServer = None | |
1537 | self._waiting = False | |
1538 | self._service = wx.GetApp().GetService(DebuggerService) | |
1539 | self._debuggerUI = debuggerUI | |
1540 | self._break_url = break_url | |
1541 | self._breakServer = None | |
1542 | self._firstInteraction = True | |
1543 | self._pendingBreak = False | |
1544 | ||
1545 | def start(self): | |
1546 | self._serverHandlerThread.start() | |
1547 | ||
26ee3a06 RD |
1548 | def ShutdownServer(self): |
1549 | #rbt = RequestBreakThread(self._breakServer, kill=True) | |
1550 | #rbt.start() | |
1f780e48 RD |
1551 | self.setWaiting(False) |
1552 | if self._serverHandlerThread: | |
1553 | self._serverHandlerThread.AskToStop() | |
1554 | self._serverHandlerThread = None | |
1555 | ||
1556 | def BreakExecution(self): | |
1557 | rbt = RequestBreakThread(self._breakServer, interrupt=True) | |
1558 | rbt.start() | |
1559 | ||
1560 | def SingleStep(self): | |
1561 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1f780e48 RD |
1562 | self._debuggerServer.set_step() # Figure out where to set allowNone |
1563 | self.waitForRPC() | |
1564 | ||
1565 | def Next(self): | |
1566 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1f780e48 RD |
1567 | self._debuggerServer.set_next() |
1568 | self.waitForRPC() | |
1569 | ||
1570 | def Continue(self): | |
1571 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1f780e48 RD |
1572 | self._debuggerServer.set_continue() |
1573 | self.waitForRPC() | |
1574 | ||
1575 | def Return(self): | |
1576 | self._debuggerUI.DisableWhileDebuggerRunning() | |
1f780e48 RD |
1577 | self._debuggerServer.set_return() |
1578 | self.waitForRPC() | |
1579 | ||
1580 | def setWaiting(self, value): | |
1581 | self._waiting = value | |
1582 | ||
1583 | def getWaiting(self): | |
1584 | return self._waiting | |
1585 | ||
1586 | def readQueue(self): | |
1587 | if self._queue.qsize(): | |
1588 | try: | |
1589 | item = self._queue.get_nowait() | |
1590 | if item.getQuit(): | |
1591 | self.interaction(None, None, None, True) | |
1592 | else: | |
1593 | data = bz2.decompress(item.getFramesXML().data) | |
1594 | self.interaction(item.getMessage().data, data, item.getInfo(), False) | |
1595 | except Queue.Empty: | |
1596 | pass | |
1597 | ||
1598 | def pushBreakpoints(self): | |
1599 | rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict()) | |
1600 | rbt.start() | |
1601 | ||
1602 | ||
1603 | def waitForRPC(self): | |
1604 | self.setWaiting(True) | |
1605 | while self.getWaiting(): | |
1606 | try: | |
1607 | self.readQueue() | |
1608 | import time | |
1609 | time.sleep(0.02) | |
1610 | except: | |
1611 | tp, val, tb = sys.exc_info() | |
1612 | traceback.print_exception(tp, val, tb) | |
1613 | wx.GetApp().Yield(True) | |
1614 | if _VERBOSE: print "Exiting waitForRPC." | |
1615 | ||
1616 | def interaction(self, message, frameXML, info, quit): | |
1617 | ||
1618 | #This method should be hit as the debugger starts. | |
1619 | if self._firstInteraction: | |
1620 | self._firstInteraction = False | |
1621 | self._debuggerServer = xmlrpclib.ServerProxy(self._debugger_url, allow_none=1) | |
1622 | self._breakServer = xmlrpclib.ServerProxy(self._break_url, allow_none=1) | |
1623 | self.pushBreakpoints() | |
1624 | self.setWaiting(False) | |
1625 | if _VERBOSE: print "+"*40 | |
1626 | if(quit): | |
1627 | self._debuggerUI.StopExecution(None) | |
1628 | return "" | |
1629 | if(info != ""): | |
1630 | if _VERBOSE: print "Hit interaction with exception" | |
1631 | #self._debuggerUI.StopExecution(None) | |
1632 | #self._debuggerUI.SetStatusText("Got exception: " + str(info)) | |
1633 | self._debuggerUI.SwitchToOutputTab() | |
1634 | else: | |
1635 | if _VERBOSE: print "Hit interaction no exception" | |
1636 | self._debuggerUI.SetStatusText(message) | |
1637 | self._debuggerUI.LoadFramesListXML(frameXML) | |
1638 | self._debuggerUI.EnableWhileDebuggerStopped() | |
1639 | if _VERBOSE: print "+"*40 | |
1640 | ||
1641 | class DebuggerService(Service.Service): | |
1642 | ||
1643 | #---------------------------------------------------------------------------- | |
1644 | # Constants | |
1645 | #---------------------------------------------------------------------------- | |
1646 | TOGGLE_BREAKPOINT_ID = wx.NewId() | |
1647 | CLEAR_ALL_BREAKPOINTS = wx.NewId() | |
1648 | RUN_ID = wx.NewId() | |
1649 | DEBUG_ID = wx.NewId() | |
bbf7159c | 1650 | DEBUG_WEBSERVER_ID = wx.NewId() |
02b800ce | 1651 | RUN_WEBSERVER_ID = wx.NewId() |
6f1a3f9c | 1652 | |
1f780e48 RD |
1653 | def ComparePaths(first, second): |
1654 | one = DebuggerService.ExpandPath(first) | |
1655 | two = DebuggerService.ExpandPath(second) | |
1656 | if _WINDOWS: | |
1657 | return one.lower() == two.lower() | |
1658 | else: | |
1659 | return one == two | |
1660 | ComparePaths = staticmethod(ComparePaths) | |
1661 | ||
1662 | # Make sure we're using an expanded path on windows. | |
1663 | def ExpandPath(path): | |
1664 | if _WINDOWS: | |
1665 | try: | |
1666 | return win32api.GetLongPathName(path) | |
1667 | except: | |
26ee3a06 RD |
1668 | if _VERBOSE: |
1669 | print "Cannot get long path for %s" % path | |
1f780e48 RD |
1670 | |
1671 | return path | |
1672 | ||
1673 | ExpandPath = staticmethod(ExpandPath) | |
1674 | ||
1675 | #---------------------------------------------------------------------------- | |
1676 | # Overridden methods | |
1677 | #---------------------------------------------------------------------------- | |
1678 | ||
1679 | def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT): | |
1680 | Service.Service.__init__(self, serviceName, embeddedWindowLocation) | |
1681 | self.BREAKPOINT_DICT_STRING = "MasterBreakpointDict" | |
1682 | config = wx.ConfigBase_Get() | |
1683 | pickledbps = config.Read(self.BREAKPOINT_DICT_STRING) | |
1684 | if pickledbps: | |
1685 | try: | |
1686 | self._masterBPDict = pickle.loads(pickledbps.encode('ascii')) | |
1687 | except: | |
1688 | tp, val, tb = sys.exc_info() | |
1689 | traceback.print_exception(tp,val,tb) | |
1690 | self._masterBPDict = {} | |
1691 | else: | |
1692 | self._masterBPDict = {} | |
1693 | ||
1694 | def OnCloseFrame(self, event): | |
1695 | # IS THIS THE RIGHT PLACE? | |
1696 | try: | |
1697 | config = wx.ConfigBase_Get() | |
1698 | config.Write(self.BREAKPOINT_DICT_STRING, pickle.dumps(self._masterBPDict)) | |
1699 | except: | |
1700 | tp,val,tb = sys.exc_info() | |
1701 | traceback.print_exception(tp, val, tb) | |
1702 | return True | |
1703 | ||
1704 | def _CreateView(self): | |
1705 | return DebuggerView(self) | |
1706 | ||
1707 | ||
1708 | #---------------------------------------------------------------------------- | |
1709 | # Service specific methods | |
1710 | #---------------------------------------------------------------------------- | |
1711 | ||
1712 | def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): | |
1713 | #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document) | |
1714 | ||
1715 | config = wx.ConfigBase_Get() | |
1716 | ||
1717 | debuggerMenu = wx.Menu() | |
1718 | if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS): | |
1719 | ||
1720 | debuggerMenu.Append(DebuggerService.RUN_ID, _("&Run...\tCtrl+R"), _("Runs a file")) | |
1721 | wx.EVT_MENU(frame, DebuggerService.RUN_ID, frame.ProcessEvent) | |
1722 | wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_ID, frame.ProcessUpdateUIEvent) | |
1723 | ||
1724 | debuggerMenu.Append(DebuggerService.DEBUG_ID, _("&Debug...\tCtrl+D"), _("Debugs a file")) | |
1725 | wx.EVT_MENU(frame, DebuggerService.DEBUG_ID, frame.ProcessEvent) | |
1726 | wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_ID, frame.ProcessUpdateUIEvent) | |
1727 | ||
bbf7159c RD |
1728 | if not ACTIVEGRID_BASE_IDE: |
1729 | debuggerMenu.AppendSeparator() | |
1730 | debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier")) | |
1731 | wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent) | |
1732 | wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent) | |
02b800ce RD |
1733 | debuggerMenu.Append(DebuggerService.RUN_WEBSERVER_ID, _("Restart Internal Web Server"), _("Restarts the internal webservier")) |
1734 | wx.EVT_MENU(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessEvent) | |
1735 | wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessUpdateUIEvent) | |
bbf7159c | 1736 | |
1f780e48 RD |
1737 | debuggerMenu.AppendSeparator() |
1738 | ||
1739 | debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint...\tCtrl+B"), _("Toggle a breakpoint")) | |
1740 | wx.EVT_MENU(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessEvent) | |
1741 | wx.EVT_UPDATE_UI(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessUpdateUIEvent) | |
1742 | ||
1743 | debuggerMenu.Append(DebuggerService.CLEAR_ALL_BREAKPOINTS, _("&Clear All Breakpoints"), _("Clear All Breakpoints")) | |
1744 | wx.EVT_MENU(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessEvent) | |
1745 | wx.EVT_UPDATE_UI(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessUpdateUIEvent) | |
1746 | ||
1747 | ||
1748 | viewMenuIndex = menuBar.FindMenu(_("&Project")) | |
1749 | menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run")) | |
02b800ce RD |
1750 | |
1751 | toolBar.AddSeparator() | |
1752 | toolBar.AddTool(DebuggerService.RUN_ID, getRunningManBitmap(), shortHelpString = _("Run"), longHelpString = _("Run")) | |
1753 | toolBar.AddTool(DebuggerService.DEBUG_ID, getDebuggingManBitmap(), shortHelpString = _("Debug"), longHelpString = _("Debug")) | |
1754 | toolBar.Realize() | |
1f780e48 RD |
1755 | |
1756 | return True | |
1757 | ||
1758 | ||
1759 | ||
1760 | #---------------------------------------------------------------------------- | |
1761 | # Event Processing Methods | |
1762 | #---------------------------------------------------------------------------- | |
1763 | ||
1764 | def ProcessEventBeforeWindows(self, event): | |
1765 | return False | |
1766 | ||
1767 | ||
1768 | def ProcessEvent(self, event): | |
1769 | if Service.Service.ProcessEvent(self, event): | |
1770 | return True | |
1771 | ||
1772 | an_id = event.GetId() | |
1773 | if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID: | |
1774 | self.OnToggleBreakpoint(event) | |
1775 | return True | |
1776 | elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS: | |
1777 | self.ClearAllBreakpoints() | |
1778 | return True | |
1779 | elif an_id == DebuggerService.RUN_ID: | |
1780 | self.OnRunProject(event) | |
1781 | return True | |
1782 | elif an_id == DebuggerService.DEBUG_ID: | |
1783 | self.OnDebugProject(event) | |
1784 | return True | |
bbf7159c RD |
1785 | elif an_id == DebuggerService.DEBUG_WEBSERVER_ID: |
1786 | self.OnDebugWebServer(event) | |
1787 | return True | |
02b800ce RD |
1788 | elif an_id == DebuggerService.RUN_WEBSERVER_ID: |
1789 | self.OnRunWebServer(event) | |
1790 | return True | |
1f780e48 RD |
1791 | return False |
1792 | ||
1793 | def ProcessUpdateUIEvent(self, event): | |
1794 | if Service.Service.ProcessUpdateUIEvent(self, event): | |
1795 | return True | |
1796 | ||
1797 | an_id = event.GetId() | |
1798 | if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID: | |
1799 | currentView = self.GetDocumentManager().GetCurrentView() | |
1800 | event.Enable(isinstance(currentView, PythonEditor.PythonView)) | |
1801 | return True | |
1802 | elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS: | |
1803 | event.Enable(self.HasBreakpointsSet()) | |
1804 | return True | |
b792147d RD |
1805 | elif (an_id == DebuggerService.RUN_ID |
1806 | or an_id == DebuggerService.DEBUG_ID): | |
1f780e48 RD |
1807 | event.Enable(self.HasAnyFiles()) |
1808 | return True | |
1809 | else: | |
1810 | return False | |
1811 | ||
1812 | #---------------------------------------------------------------------------- | |
1813 | # Class Methods | |
1814 | #---------------------------------------------------------------------------- | |
1815 | ||
1816 | def OnDebugProject(self, event): | |
b792147d RD |
1817 | if _WINDOWS and not _PYWIN32_INSTALLED: |
1818 | wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) | |
1819 | return | |
1f780e48 RD |
1820 | if not Executor.GetPythonExecutablePath(): |
1821 | return | |
1822 | if DebugCommandUI.DebuggerRunning(): | |
1823 | wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running")) | |
1824 | return | |
1825 | self.ShowWindow(True) | |
1826 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | |
bbf7159c RD |
1827 | try: |
1828 | dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug Python File', projectService, None, pythonOnly=True, okButtonName="Debug", debugging=True) | |
1829 | except: | |
1830 | return | |
02b800ce | 1831 | dlg.CenterOnParent() |
1f780e48 | 1832 | if dlg.ShowModal() == wx.ID_OK: |
02b800ce | 1833 | projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings() |
1f780e48 RD |
1834 | dlg.Destroy() |
1835 | else: | |
1836 | dlg.Destroy() | |
1837 | return | |
1838 | self.PromptToSaveFiles() | |
1839 | ||
1840 | shortFile = os.path.basename(fileToDebug) | |
1841 | fileToDebug = DebuggerService.ExpandPath(fileToDebug) | |
1842 | try: | |
1843 | page = DebugCommandUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self) | |
1844 | count = Service.ServiceView.bottomTab.GetPageCount() | |
bbf7159c | 1845 | Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile) |
1f780e48 RD |
1846 | Service.ServiceView.bottomTab.SetSelection(count) |
1847 | page.Execute(initialArgs, startIn, environment) | |
1848 | except: | |
1849 | pass | |
bbf7159c RD |
1850 | |
1851 | def OnDebugWebServer(self, event): | |
6f1a3f9c RD |
1852 | if _WINDOWS and not _PYWIN32_INSTALLED: |
1853 | wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) | |
1854 | return | |
1855 | if not Executor.GetPythonExecutablePath(): | |
1856 | return | |
1857 | if DebugCommandUI.DebuggerRunning(): | |
1858 | wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running")) | |
1859 | return | |
bbf7159c RD |
1860 | import WebServerService |
1861 | wsService = wx.GetApp().GetService(WebServerService.WebServerService) | |
1862 | fileName, args = wsService.StopAndPrepareToDebug() | |
1863 | try: | |
2eeaec19 | 1864 | page = DebugCommandUI(Service.ServiceView.bottomTab, -1, fileName, self) |
bbf7159c RD |
1865 | count = Service.ServiceView.bottomTab.GetPageCount() |
1866 | Service.ServiceView.bottomTab.AddPage(page, _("Debugging: Internal WebServer")) | |
1867 | Service.ServiceView.bottomTab.SetSelection(count) | |
1868 | page.Execute(args, startIn=os.getcwd(), environment=os.environ) | |
1869 | except: | |
1870 | pass | |
02b800ce RD |
1871 | |
1872 | def OnRunWebServer(self, event): | |
1873 | if not Executor.GetPythonExecutablePath(): | |
1874 | return | |
1875 | import WebServerService | |
1876 | wsService = wx.GetApp().GetService(WebServerService.WebServerService) | |
1877 | wsService.ShutDownAndRestart() | |
bbf7159c | 1878 | |
1f780e48 RD |
1879 | def HasAnyFiles(self): |
1880 | docs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1881 | return len(docs) > 0 | |
1882 | ||
1883 | def PromptToSaveFiles(self, running=True): | |
1884 | filesModified = False | |
1885 | docs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1886 | for doc in docs: | |
1887 | if doc.IsModified(): | |
1888 | filesModified = True | |
1889 | break | |
1890 | if filesModified: | |
1891 | frame = self.GetView().GetFrame() | |
1892 | if running: | |
1893 | yesNoMsg = wx.MessageDialog(frame, | |
1894 | _("Files have been modified.\nWould you like to save all files before running?"), | |
1895 | _("Run"), | |
b792147d | 1896 | wx.YES_NO|wx.ICON_QUESTION |
1f780e48 RD |
1897 | ) |
1898 | else: | |
1899 | yesNoMsg = wx.MessageDialog(frame, | |
1900 | _("Files have been modified.\nWould you like to save all files before debugging?"), | |
1901 | _("Debug"), | |
b792147d | 1902 | wx.YES_NO|wx.ICON_QUESTION |
1f780e48 | 1903 | ) |
02b800ce | 1904 | yesNoMsg.CenterOnParent() |
1f780e48 RD |
1905 | if yesNoMsg.ShowModal() == wx.ID_YES: |
1906 | docs = wx.GetApp().GetDocumentManager().GetDocuments() | |
1907 | for doc in docs: | |
1908 | doc.Save() | |
02b800ce | 1909 | yesNoMsg.Destroy() |
1f780e48 RD |
1910 | |
1911 | def OnExit(self): | |
1912 | DebugCommandUI.ShutdownAllDebuggers() | |
26ee3a06 | 1913 | RunCommandUI.ShutdownAllRunners() |
1f780e48 RD |
1914 | |
1915 | def OnRunProject(self, event): | |
b792147d RD |
1916 | if _WINDOWS and not _PYWIN32_INSTALLED: |
1917 | wx.MessageBox(_("Python for Windows extensions (pywin32) is required to run on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) | |
1918 | return | |
1f780e48 RD |
1919 | if not Executor.GetPythonExecutablePath(): |
1920 | return | |
1921 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | |
bbf7159c RD |
1922 | try: |
1923 | dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None) | |
1924 | except: | |
1925 | return | |
02b800ce | 1926 | dlg.CenterOnParent() |
1f780e48 | 1927 | if dlg.ShowModal() == wx.ID_OK: |
02b800ce | 1928 | projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings() |
1f780e48 RD |
1929 | dlg.Destroy() |
1930 | else: | |
1931 | dlg.Destroy() | |
1932 | return | |
1933 | self.PromptToSaveFiles() | |
1934 | # This will need to change when we can run more than .py and .bpel files. | |
1935 | if not isPython: | |
02b800ce RD |
1936 | projects = projectService.FindProjectByFile(projectPath) |
1937 | if not projects: | |
1938 | return | |
1939 | project = projects[0] | |
1940 | deployFilePath = project.GenerateDeployment() | |
1941 | projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath) | |
1f780e48 RD |
1942 | return |
1943 | ||
1944 | self.ShowWindow(True) | |
1945 | shortFile = os.path.basename(fileToRun) | |
1946 | page = RunCommandUI(Service.ServiceView.bottomTab, -1, str(fileToRun)) | |
1947 | count = Service.ServiceView.bottomTab.GetPageCount() | |
1948 | Service.ServiceView.bottomTab.AddPage(page, "Running: " + shortFile) | |
1949 | Service.ServiceView.bottomTab.SetSelection(count) | |
1950 | page.Execute(initialArgs, startIn, environment) | |
1951 | ||
1952 | def OnToggleBreakpoint(self, event, line=-1, fileName=None): | |
1953 | if not fileName: | |
1954 | view = wx.GetApp().GetDocumentManager().GetCurrentView() | |
1955 | # Test to make sure we aren't the project view. | |
1956 | if not hasattr(view, 'MarkerExists'): | |
1957 | return | |
1958 | fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename() | |
1959 | if line < 0: | |
1960 | line = view.GetCtrl().GetCurrentLine() | |
02b800ce RD |
1961 | else: |
1962 | view = None | |
1f780e48 RD |
1963 | if self.BreakpointSet(fileName, line + 1): |
1964 | self.ClearBreak(fileName, line + 1) | |
02b800ce RD |
1965 | if view: |
1966 | view.GetCtrl().Refresh() | |
1f780e48 RD |
1967 | else: |
1968 | self.SetBreak(fileName, line + 1) | |
02b800ce RD |
1969 | if view: |
1970 | view.GetCtrl().Refresh() | |
1f780e48 RD |
1971 | # Now refresh all the markers icons in all the open views. |
1972 | self.ClearAllBreakpointMarkers() | |
1973 | self.SetAllBreakpointMarkers() | |
1974 | ||
1975 | def SilentToggleBreakpoint(self, fileName, line): | |
1976 | found = False | |
1977 | for lineNumber in self.GetBreakpointList(fileName): | |
1978 | if int(lineNumber) == int(line): | |
1979 | found = True | |
1980 | break | |
1981 | if found: | |
1982 | self.SetBreak(fileName, line) | |
1983 | else: | |
1984 | self.ClearBreak(fileName, line) | |
1985 | ||
1986 | def SetBreak(self, fileName, line): | |
1987 | expandedName = DebuggerService.ExpandPath(fileName) | |
1988 | if not self._masterBPDict.has_key(expandedName): | |
1989 | self._masterBPDict[expandedName] = [line] | |
1990 | else: | |
1991 | self._masterBPDict[expandedName] += [line] | |
1992 | # If we're already debugging, pass this bp off to the DebuggerCallback | |
1993 | self.NotifyDebuggersOfBreakpointChange() | |
1994 | ||
1995 | def NotifyDebuggersOfBreakpointChange(self): | |
1996 | DebugCommandUI.NotifyDebuggersOfBreakpointChange() | |
1997 | ||
1998 | def GetBreakpointList(self, fileName): | |
1999 | expandedName = DebuggerService.ExpandPath(fileName) | |
2000 | if not self._masterBPDict.has_key(expandedName): | |
2001 | return [] | |
2002 | else: | |
2003 | return self._masterBPDict[expandedName] | |
2004 | ||
02b800ce RD |
2005 | def SetBreakpointList(self, fileName, bplist): |
2006 | expandedName = DebuggerService.ExpandPath(fileName) | |
2007 | self._masterBPDict[expandedName] = bplist | |
2008 | ||
1f780e48 RD |
2009 | def BreakpointSet(self, fileName, line): |
2010 | expandedName = DebuggerService.ExpandPath(fileName) | |
2011 | if not self._masterBPDict.has_key(expandedName): | |
2012 | return False | |
2013 | else: | |
2014 | newList = [] | |
2015 | for number in self._masterBPDict[expandedName]: | |
2016 | if(int(number) == int(line)): | |
2017 | return True | |
2018 | return False | |
2019 | ||
2020 | def ClearBreak(self, fileName, line): | |
2021 | expandedName = DebuggerService.ExpandPath(fileName) | |
2022 | if not self._masterBPDict.has_key(expandedName): | |
2023 | print "In ClearBreak: no key" | |
2024 | return | |
2025 | else: | |
2026 | newList = [] | |
2027 | for number in self._masterBPDict[expandedName]: | |
2028 | if(int(number) != int(line)): | |
2029 | newList.append(number) | |
2030 | self._masterBPDict[expandedName] = newList | |
2031 | self.NotifyDebuggersOfBreakpointChange() | |
2032 | ||
2033 | def HasBreakpointsSet(self): | |
2034 | for key, value in self._masterBPDict.items(): | |
2035 | if len(value) > 0: | |
2036 | return True | |
2037 | return False | |
2038 | ||
2039 | def ClearAllBreakpoints(self): | |
2040 | self._masterBPDict = {} | |
2041 | self.NotifyDebuggersOfBreakpointChange() | |
2042 | self.ClearAllBreakpointMarkers() | |
2043 | ||
2044 | def ClearAllBreakpointMarkers(self): | |
2045 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
2046 | for openDoc in openDocs: | |
02b800ce | 2047 | if isinstance(openDoc, CodeEditor.CodeDocument): |
1f780e48 | 2048 | openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) |
02b800ce RD |
2049 | |
2050 | def UpdateBreakpointsFromMarkers(self, view, fileName): | |
2051 | newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) | |
2052 | self.SetBreakpointList(fileName, newbpLines) | |
2053 | ||
1f780e48 RD |
2054 | def GetMasterBreakpointDict(self): |
2055 | return self._masterBPDict | |
2056 | ||
2057 | def SetAllBreakpointMarkers(self): | |
2058 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
2059 | for openDoc in openDocs: | |
02b800ce | 2060 | if(isinstance(openDoc, CodeEditor.CodeDocument)): |
1f780e48 RD |
2061 | self.SetCurrentBreakpointMarkers(openDoc.GetFirstView()) |
2062 | ||
2063 | def SetCurrentBreakpointMarkers(self, view): | |
2064 | if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'): | |
2065 | view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) | |
2066 | for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()): | |
2067 | view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) | |
2068 | ||
2069 | class DebuggerOptionsPanel(wx.Panel): | |
2070 | ||
2071 | ||
2072 | def __init__(self, parent, id): | |
2073 | wx.Panel.__init__(self, parent, id) | |
2074 | SPACE = 10 | |
2075 | config = wx.ConfigBase_Get() | |
2076 | localHostStaticText = wx.StaticText(self, -1, _("Local Host Name:")) | |
2077 | self._LocalHostTextCtrl = wx.TextCtrl(self, -1, config.Read("DebuggerHostName", DEFAULT_HOST), size = (150, -1)) | |
2078 | portNumberStaticText = wx.StaticText(self, -1, _("Port Range:")) | |
2079 | dashStaticText = wx.StaticText(self, -1, _("through to")) | |
2080 | startingPort=config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) | |
2081 | self._PortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort, size = (50, -1)) | |
2082 | self._PortNumberTextCtrl.SetMin(1)#What are real values? | |
2083 | self._PortNumberTextCtrl.SetMax(65514) #What are real values? | |
2084 | self.Bind(wx.lib.intctrl.EVT_INT, self.MinPortChange, self._PortNumberTextCtrl) | |
2085 | ||
2086 | self._EndPortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort + PORT_COUNT, size = (50, -1)) | |
2087 | self._EndPortNumberTextCtrl.SetMin(22)#What are real values? | |
2088 | self._EndPortNumberTextCtrl.SetMax(65535)#What are real values? | |
2089 | self._EndPortNumberTextCtrl.Enable( False ) | |
2090 | debuggerPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) | |
2091 | debuggerPanelSizer = wx.GridBagSizer(hgap = 5, vgap = 5) | |
2092 | debuggerPanelSizer.Add( localHostStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | |
2093 | debuggerPanelSizer.Add( self._LocalHostTextCtrl, (0,1), (1,3), flag=wx.EXPAND|wx.ALIGN_CENTER) | |
2094 | debuggerPanelSizer.Add( portNumberStaticText, (1,0), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) | |
2095 | debuggerPanelSizer.Add( self._PortNumberTextCtrl, (1,1), flag=wx.ALIGN_CENTER) | |
2096 | debuggerPanelSizer.Add( dashStaticText, (1,2), flag=wx.ALIGN_CENTER) | |
2097 | debuggerPanelSizer.Add( self._EndPortNumberTextCtrl, (1,3), flag=wx.ALIGN_CENTER) | |
2098 | FLUSH_PORTS_ID = wx.NewId() | |
2099 | self._flushPortsButton = wx.Button(self, FLUSH_PORTS_ID, "Reset Port List") | |
2100 | wx.EVT_BUTTON(parent, FLUSH_PORTS_ID, self.FlushPorts) | |
2101 | debuggerPanelSizer.Add(self._flushPortsButton, (2,2), (1,2), flag=wx.ALIGN_RIGHT) | |
2102 | ||
2103 | debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE) | |
2104 | self.SetSizer(debuggerPanelBorderSizer) | |
2105 | self.Layout() | |
2106 | parent.AddPage(self, _("Debugger")) | |
2107 | ||
2108 | def FlushPorts(self, event): | |
2109 | if self._PortNumberTextCtrl.IsInBounds(): | |
2110 | config = wx.ConfigBase_Get() | |
2111 | config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue()) | |
2112 | DebugCommandUI.NewPortRange() | |
2113 | else: | |
2114 | wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number")) | |
2115 | ||
2116 | def MinPortChange(self, event): | |
2117 | self._EndPortNumberTextCtrl.Enable( True ) | |
2118 | self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT) | |
2119 | self._EndPortNumberTextCtrl.Enable( False ) | |
2120 | ||
2121 | def OnOK(self, optionsDialog): | |
2122 | config = wx.ConfigBase_Get() | |
2123 | config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue()) | |
2124 | if self._PortNumberTextCtrl.IsInBounds(): | |
2125 | config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue()) | |
02b800ce RD |
2126 | |
2127 | ||
2128 | def GetIcon(self): | |
2129 | return getContinueIcon() | |
2130 | ||
1f780e48 RD |
2131 | |
2132 | class CommandPropertiesDialog(wx.Dialog): | |
2133 | ||
2134 | def __init__(self, parent, title, projectService, currentProjectDocument, pythonOnly=False, okButtonName="Run", debugging=False): | |
1f780e48 RD |
2135 | self._projService = projectService |
2136 | self._pmext = None | |
2137 | self._pyext = None | |
2138 | for template in self._projService.GetDocumentManager().GetTemplates(): | |
2139 | if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument: | |
2140 | self._pmext = template.GetDefaultExtension() | |
2141 | if template.GetDocumentType() == PythonEditor.PythonDocument: | |
2142 | self._pyext = template.GetDefaultExtension() | |
2143 | self._pythonOnly = pythonOnly | |
1f780e48 | 2144 | self._currentProj = currentProjectDocument |
bbf7159c RD |
2145 | self._projectNameList, self._projectDocumentList, selectedIndex = self.GetProjectList() |
2146 | if not self._projectNameList: | |
2147 | wx.MessageBox(_("To run or debug you must have an open runnable file or project containing runnable files. Use File->Open to open the file you wish to run or debug."), _("Nothing to Run")) | |
2148 | raise BadBadBad | |
02b800ce RD |
2149 | |
2150 | wx.Dialog.__init__(self, parent, -1, title) | |
bbf7159c | 2151 | |
1f780e48 RD |
2152 | projStaticText = wx.StaticText(self, -1, _("Project:")) |
2153 | fileStaticText = wx.StaticText(self, -1, _("File:")) | |
2154 | argsStaticText = wx.StaticText(self, -1, _("Arguments:")) | |
2155 | startInStaticText = wx.StaticText(self, -1, _("Start in:")) | |
2156 | pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:")) | |
2157 | postpendStaticText = _("Postpend win32api path") | |
2158 | cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) | |
02b800ce | 2159 | self._projList = wx.Choice(self, -1, choices=self._projectNameList) |
1f780e48 RD |
2160 | self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList) |
2161 | HALF_SPACE = 5 | |
02b800ce RD |
2162 | GAP = HALF_SPACE |
2163 | if wx.Platform == "__WXMAC__": | |
2164 | GAP = 10 | |
2165 | flexGridSizer = wx.GridBagSizer(GAP, GAP) | |
1f780e48 | 2166 | |
02b800ce RD |
2167 | flexGridSizer.Add(projStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) |
2168 | flexGridSizer.Add(self._projList, (0,1), (1,2), flag=wx.EXPAND) | |
1f780e48 | 2169 | |
02b800ce RD |
2170 | flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) |
2171 | self._fileList = wx.Choice(self, -1) | |
1f780e48 | 2172 | self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList) |
02b800ce | 2173 | flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND) |
1f780e48 RD |
2174 | |
2175 | config = wx.ConfigBase_Get() | |
2176 | self._lastArguments = config.Read("LastRunArguments") | |
2177 | self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments)) | |
2178 | self._argsEntry.SetToolTipString(str(self._lastArguments)) | |
1f780e48 | 2179 | |
02b800ce RD |
2180 | flexGridSizer.Add(argsStaticText, (2,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) |
2181 | flexGridSizer.Add(self._argsEntry, (2,1), (1,2), flag=wx.EXPAND) | |
1f780e48 | 2182 | |
02b800ce | 2183 | flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) |
1f780e48 RD |
2184 | self._lastStartIn = config.Read("LastRunStartIn") |
2185 | if not self._lastStartIn: | |
2186 | self._lastStartIn = str(os.getcwd()) | |
2187 | self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn) | |
2188 | self._startEntry.SetToolTipString(self._lastStartIn) | |
1f780e48 | 2189 | |
02b800ce | 2190 | flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND) |
b792147d | 2191 | self._findDir = wx.Button(self, -1, _("Browse...")) |
1f780e48 | 2192 | self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir) |
02b800ce | 2193 | flexGridSizer.Add(self._findDir, (3,2)) |
1f780e48 | 2194 | |
02b800ce | 2195 | flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) |
1f780e48 RD |
2196 | if os.environ.has_key('PYTHONPATH'): |
2197 | startval = os.environ['PYTHONPATH'] | |
2198 | else: | |
2199 | startval = "" | |
2200 | self._lastPythonPath = config.Read("LastPythonPath", startval) | |
2201 | self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath) | |
2202 | self._pythonPathEntry.SetToolTipString(self._lastPythonPath) | |
02b800ce RD |
2203 | flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND) |
2204 | ||
2eeaec19 | 2205 | if debugging and _WINDOWS: |
1f780e48 RD |
2206 | self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText) |
2207 | checked = bool(config.ReadInt("PythonPathPostpend", 1)) | |
2208 | self._postpendCheckBox.SetValue(checked) | |
02b800ce RD |
2209 | flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND) |
2210 | cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10) | |
1f780e48 | 2211 | |
02b800ce | 2212 | box = wx.StdDialogButtonSizer() |
b792147d | 2213 | self._okButton = wx.Button(self, wx.ID_OK, okButtonName) |
1f780e48 RD |
2214 | self._okButton.SetDefault() |
2215 | self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog")) | |
02b800ce | 2216 | box.AddButton(self._okButton) |
1f780e48 | 2217 | self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton) |
b792147d | 2218 | btn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) |
1f780e48 | 2219 | btn.SetHelpText(_("The Cancel button cancels the dialog.")) |
02b800ce RD |
2220 | box.AddButton(btn) |
2221 | box.Realize() | |
2222 | cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5) | |
1f780e48 RD |
2223 | |
2224 | self.SetSizer(cpPanelBorderSizer) | |
02b800ce | 2225 | |
1f780e48 RD |
2226 | # Set up selections based on last values used. |
2227 | self._fileNameList = None | |
2228 | self._selectedFileIndex = 0 | |
2229 | lastProject = config.Read("LastRunProject") | |
2230 | lastFile = config.Read("LastRunFile") | |
2231 | ||
2232 | if lastProject in self._projectNameList: | |
2233 | selectedIndex = self._projectNameList.index(lastProject) | |
2234 | elif selectedIndex < 0: | |
2235 | selectedIndex = 0 | |
2236 | self._projList.Select(selectedIndex) | |
2237 | self._selectedProjectIndex = selectedIndex | |
2238 | self._selectedProjectDocument = self._projectDocumentList[selectedIndex] | |
2239 | self.PopulateFileList(self._selectedProjectDocument, lastFile) | |
02b800ce RD |
2240 | |
2241 | cpPanelBorderSizer.Fit(self) | |
2242 | ||
1f780e48 RD |
2243 | |
2244 | def OnOKClick(self, event): | |
2245 | startIn = self._startEntry.GetValue() | |
2246 | fileToRun = self._fileList.GetStringSelection() | |
2247 | if not fileToRun: | |
2248 | wx.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged.")) | |
2249 | return | |
2250 | isPython = fileToRun.endswith(self._pyext) | |
2251 | if isPython and not os.path.exists(startIn): | |
2252 | wx.MessageBox(_("Starting directory does not exist. Please change this value.")) | |
2253 | return | |
2254 | config = wx.ConfigBase_Get() | |
2255 | config.Write("LastRunProject", self._projectNameList[self._selectedProjectIndex]) | |
2256 | config.Write("LastRunFile", fileToRun) | |
2257 | # Don't update the arguments or starting directory unless we're runing python. | |
2258 | if isPython: | |
2259 | config.Write("LastRunArguments", self._argsEntry.GetValue()) | |
2260 | config.Write("LastRunStartIn", self._startEntry.GetValue()) | |
2261 | config.Write("LastPythonPath",self._pythonPathEntry.GetValue()) | |
2262 | if hasattr(self, "_postpendCheckBox"): | |
2263 | config.WriteInt("PythonPathPostpend", int(self._postpendCheckBox.GetValue())) | |
2264 | ||
2265 | self.EndModal(wx.ID_OK) | |
2266 | ||
2267 | def GetSettings(self): | |
02b800ce | 2268 | projectPath = self._selectedProjectDocument.GetFilename() |
1f780e48 RD |
2269 | filename = self._fileNameList[self._selectedFileIndex] |
2270 | args = self._argsEntry.GetValue() | |
2271 | startIn = self._startEntry.GetValue() | |
2272 | isPython = filename.endswith(self._pyext) | |
2273 | env = os.environ | |
2274 | if hasattr(self, "_postpendCheckBox"): | |
2275 | postpend = self._postpendCheckBox.GetValue() | |
2276 | else: | |
2277 | postpend = False | |
2278 | if postpend: | |
2279 | env['PYTHONPATH'] = self._pythonPathEntry.GetValue() + os.pathsep + os.path.join(os.getcwd(), "3rdparty", "pywin32") | |
2280 | else: | |
2281 | env['PYTHONPATH'] = self._pythonPathEntry.GetValue() | |
2282 | ||
02b800ce | 2283 | return projectPath, filename, args, startIn, isPython, env |
1f780e48 RD |
2284 | |
2285 | def OnFileSelected(self, event): | |
2286 | self._selectedFileIndex = self._fileList.GetSelection() | |
2287 | self.EnableForFileType(event.GetString()) | |
2288 | ||
2289 | def EnableForFileType(self, fileName): | |
2290 | show = fileName.endswith(self._pyext) | |
2291 | self._startEntry.Enable(show) | |
2292 | self._findDir.Enable(show) | |
2293 | self._argsEntry.Enable(show) | |
2294 | ||
2295 | if not show: | |
2296 | self._lastStartIn = self._startEntry.GetValue() | |
2297 | self._startEntry.SetValue("") | |
2298 | self._lastArguments = self._argsEntry.GetValue() | |
2299 | self._argsEntry.SetValue("") | |
2300 | else: | |
2301 | self._startEntry.SetValue(self._lastStartIn) | |
2302 | self._argsEntry.SetValue(self._lastArguments) | |
2303 | ||
2304 | ||
1f780e48 RD |
2305 | def OnFindDirClick(self, event): |
2306 | dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(), | |
2307 | style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) | |
2308 | ||
02b800ce | 2309 | dlg.CenterOnParent() |
1f780e48 RD |
2310 | if dlg.ShowModal() == wx.ID_OK: |
2311 | self._startEntry.SetValue(dlg.GetPath()) | |
2312 | ||
2313 | dlg.Destroy() | |
2314 | ||
02b800ce | 2315 | |
1f780e48 RD |
2316 | def EvtListBox(self, event): |
2317 | if event.GetString(): | |
2318 | index = self._projectNameList.index(event.GetString()) | |
2319 | self._selectedProjectDocument = self._projectDocumentList[index] | |
2320 | self._selectedProjectIndex = index | |
2321 | self.PopulateFileList(self._selectedProjectDocument) | |
2322 | ||
2323 | def FilterFileList(self, list): | |
2324 | if self._pythonOnly: | |
2325 | files = filter(lambda f: f.endswith(self._pyext), list) | |
2326 | else: | |
2327 | files = filter(lambda f: (self._pmext and f.endswith(self._pmext)) or f.endswith(self._pyext), list) | |
2328 | return files | |
2329 | ||
2330 | def PopulateFileList(self, project, shortNameToSelect=None): | |
2331 | self._fileNameList = self.FilterFileList(project.GetFiles()[:]) | |
2332 | self._fileList.Clear() | |
2333 | if not self._fileNameList: | |
2334 | return | |
2335 | self._fileNameList.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower())) | |
2336 | strings = map(lambda file: os.path.basename(file), self._fileNameList) | |
2337 | for index in range(0, len(strings)): | |
2338 | if shortNameToSelect == strings[index]: | |
2339 | self._selectedFileIndex = index | |
2340 | break | |
2341 | self._fileList.Hide() | |
2342 | self._fileList.AppendItems(strings) | |
2343 | self._fileList.Show() | |
2344 | if self._selectedFileIndex not in range(0, len(strings)) : self._selectedFileIndex = 0 | |
2345 | self._fileList.SetSelection(self._selectedFileIndex) | |
2346 | self.EnableForFileType(strings[self._selectedFileIndex]) | |
2347 | ||
2348 | def GetProjectList(self): | |
2349 | docList = [] | |
2350 | nameList = [] | |
2351 | found = False | |
2352 | index = -1 | |
2353 | count = 0 | |
2354 | for document in self._projService.GetDocumentManager().GetDocuments(): | |
2355 | if document.GetDocumentTemplate().GetDocumentType() == ProjectEditor.ProjectDocument and len(document.GetFiles()): | |
2356 | docList.append(document) | |
2357 | nameList.append(os.path.basename(document.GetFilename())) | |
2358 | if document == self._currentProj: | |
2359 | found = True | |
2360 | index = count | |
2361 | count += 1 | |
bbf7159c RD |
2362 | #Check for open files not in any of these projects and add them to a default project |
2363 | def AlreadyInProject(fileName): | |
2364 | for projectDocument in docList: | |
2365 | if projectDocument.IsFileInProject(fileName): | |
2366 | return True | |
2367 | return False | |
2368 | ||
2369 | unprojectedFiles = [] | |
2370 | for document in self._projService.GetDocumentManager().GetDocuments(): | |
2371 | if not ACTIVEGRID_BASE_IDE and type(document) == ProcessModelEditor.ProcessModelDocument: | |
2372 | if not AlreadyInProject(document.GetFilename()): | |
2373 | unprojectedFiles.append(document.GetFilename()) | |
2374 | if type(document) == PythonEditor.PythonDocument: | |
2375 | if not AlreadyInProject(document.GetFilename()): | |
2376 | unprojectedFiles.append(document.GetFilename()) | |
2377 | ||
2378 | if unprojectedFiles: | |
2379 | unprojProj = ProjectEditor.ProjectDocument() | |
2380 | unprojProj.SetFilename(_("Not in any Project")) | |
2381 | unprojProj.AddFiles(unprojectedFiles) | |
2382 | docList.append(unprojProj) | |
2383 | nameList.append(_("Not in any Project")) | |
2384 | ||
1f780e48 | 2385 | return nameList, docList, index |
bbf7159c RD |
2386 | |
2387 | ||
1f780e48 RD |
2388 | #---------------------------------------------------------------------- |
2389 | from wx import ImageFromStream, BitmapFromImage | |
1f780e48 | 2390 | import cStringIO |
bbf7159c | 2391 | |
1f780e48 RD |
2392 | #---------------------------------------------------------------------- |
2393 | def getBreakData(): | |
2394 | return \ | |
b792147d RD |
2395 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\ |
2396 | \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ | |
2397 | \x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\ | |
2398 | \x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\ | |
2399 | \xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\ | |
2400 | \x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\ | |
2401 | 5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\ | |
2402 | \x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\ | |
2403 | \xaeB`\x82' | |
1f780e48 RD |
2404 | |
2405 | def getBreakBitmap(): | |
2406 | return BitmapFromImage(getBreakImage()) | |
2407 | ||
2408 | def getBreakImage(): | |
2409 | stream = cStringIO.StringIO(getBreakData()) | |
2410 | return ImageFromStream(stream) | |
2411 | ||
2412 | def getBreakIcon(): | |
bbf7159c | 2413 | return wx.IconFromBitmap(getBreakBitmap()) |
1f780e48 RD |
2414 | |
2415 | #---------------------------------------------------------------------- | |
26ee3a06 | 2416 | |
1f780e48 RD |
2417 | def getClearOutputData(): |
2418 | return \ | |
2419 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2420 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
26ee3a06 RD |
2421 | \x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\ |
2422 | \xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\ | |
2423 | \x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\ | |
2424 | \x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\ | |
2425 | \x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\ | |
2426 | \xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\ | |
2427 | \xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\ | |
2428 | \x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\ | |
2429 | \x00IEND\xaeB`\x82' | |
1f780e48 RD |
2430 | |
2431 | def getClearOutputBitmap(): | |
2432 | return BitmapFromImage(getClearOutputImage()) | |
2433 | ||
2434 | def getClearOutputImage(): | |
2435 | stream = cStringIO.StringIO(getClearOutputData()) | |
2436 | return ImageFromStream(stream) | |
2437 | ||
2438 | def getClearOutputIcon(): | |
bbf7159c | 2439 | return wx.IconFromBitmap(getClearOutputBitmap()) |
1f780e48 RD |
2440 | |
2441 | #---------------------------------------------------------------------- | |
2442 | def getCloseData(): | |
2443 | return \ | |
b792147d RD |
2444 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\ |
2445 | \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ | |
2446 | \x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\ | |
2447 | \x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\ | |
2448 | \xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\ | |
2449 | \xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\ | |
2450 | \x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\ | |
2451 | \xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\ | |
2452 | \x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\ | |
2453 | \xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\ | |
2454 | \xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\ | |
2455 | \xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82' | |
1f780e48 RD |
2456 | |
2457 | def getCloseBitmap(): | |
2458 | return BitmapFromImage(getCloseImage()) | |
2459 | ||
2460 | def getCloseImage(): | |
2461 | stream = cStringIO.StringIO(getCloseData()) | |
2462 | return ImageFromStream(stream) | |
2463 | ||
2464 | def getCloseIcon(): | |
bbf7159c | 2465 | return wx.IconFromBitmap(getCloseBitmap()) |
1f780e48 RD |
2466 | |
2467 | #---------------------------------------------------------------------- | |
2468 | def getContinueData(): | |
2469 | return \ | |
2470 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2471 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
26ee3a06 RD |
2472 | \x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\ |
2473 | \x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\ | |
2474 | !P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\ | |
2475 | \xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\ | |
2476 | \x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\ | |
2477 | \x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\ | |
2478 | \xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\ | |
2479 | \x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\ | |
2480 | \x00\x00\x00\x00IEND\xaeB`\x82' | |
1f780e48 RD |
2481 | |
2482 | def getContinueBitmap(): | |
2483 | return BitmapFromImage(getContinueImage()) | |
2484 | ||
2485 | def getContinueImage(): | |
2486 | stream = cStringIO.StringIO(getContinueData()) | |
2487 | return ImageFromStream(stream) | |
2488 | ||
2489 | def getContinueIcon(): | |
bbf7159c | 2490 | return wx.IconFromBitmap(getContinueBitmap()) |
1f780e48 RD |
2491 | |
2492 | #---------------------------------------------------------------------- | |
2493 | def getNextData(): | |
2494 | return \ | |
2495 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2496 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2497 | \x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\ | |
2498 | \x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\ | |
2499 | gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\ | |
2500 | \x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\ | |
2501 | \xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\ | |
2502 | )\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\ | |
2503 | `\x82' | |
2504 | ||
2505 | def getNextBitmap(): | |
2506 | return BitmapFromImage(getNextImage()) | |
2507 | ||
2508 | def getNextImage(): | |
2509 | stream = cStringIO.StringIO(getNextData()) | |
2510 | return ImageFromStream(stream) | |
2511 | ||
2512 | def getNextIcon(): | |
bbf7159c | 2513 | return wx.IconFromBitmap(getNextBitmap()) |
1f780e48 RD |
2514 | |
2515 | #---------------------------------------------------------------------- | |
2516 | def getStepInData(): | |
2517 | return \ | |
2518 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2519 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2520 | \x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\ | |
2521 | \x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\ | |
2522 | \x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\ | |
2523 | ]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\ | |
2524 | \x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\ | |
2525 | \x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82' | |
2526 | ||
2527 | def getStepInBitmap(): | |
2528 | return BitmapFromImage(getStepInImage()) | |
2529 | ||
2530 | def getStepInImage(): | |
2531 | stream = cStringIO.StringIO(getStepInData()) | |
2532 | return ImageFromStream(stream) | |
2533 | ||
2534 | def getStepInIcon(): | |
bbf7159c | 2535 | return wx.IconFromBitmap(getStepInBitmap()) |
1f780e48 RD |
2536 | |
2537 | #---------------------------------------------------------------------- | |
2538 | def getStopData(): | |
2539 | return \ | |
26ee3a06 | 2540 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ |
1f780e48 | 2541 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ |
26ee3a06 RD |
2542 | \x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\ |
2543 | \xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\ | |
2544 | \x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\ | |
2545 | \x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82' | |
1f780e48 RD |
2546 | |
2547 | def getStopBitmap(): | |
2548 | return BitmapFromImage(getStopImage()) | |
2549 | ||
2550 | def getStopImage(): | |
2551 | stream = cStringIO.StringIO(getStopData()) | |
2552 | return ImageFromStream(stream) | |
2553 | ||
2554 | def getStopIcon(): | |
bbf7159c | 2555 | return wx.IconFromBitmap(getStopBitmap()) |
1f780e48 RD |
2556 | |
2557 | #---------------------------------------------------------------------- | |
2558 | def getStepReturnData(): | |
2559 | return \ | |
2560 | "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2561 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2562 | \x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\ | |
2563 | \xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\ | |
2564 | \x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\ | |
2565 | \x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\ | |
2566 | \x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\ | |
2567 | \xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\ | |
2568 | \xaeB`\x82" | |
2569 | ||
2570 | def getStepReturnBitmap(): | |
2571 | return BitmapFromImage(getStepReturnImage()) | |
2572 | ||
2573 | def getStepReturnImage(): | |
2574 | stream = cStringIO.StringIO(getStepReturnData()) | |
2575 | return ImageFromStream(stream) | |
2576 | ||
2577 | def getStepReturnIcon(): | |
bbf7159c | 2578 | return wx.IconFromBitmap(getStepReturnBitmap()) |
1f780e48 | 2579 | |
bbf7159c | 2580 | #---------------------------------------------------------------------- |
1f780e48 RD |
2581 | def getAddWatchData(): |
2582 | return \ | |
2583 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2584 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2585 | \x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\ | |
2586 | \x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\ | |
2587 | \xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\ | |
2588 | \xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\ | |
2589 | \xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\ | |
2590 | \x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82' | |
2591 | ||
2592 | def getAddWatchBitmap(): | |
2593 | return BitmapFromImage(getAddWatchImage()) | |
2594 | ||
2595 | def getAddWatchImage(): | |
2596 | stream = cStringIO.StringIO(getAddWatchData()) | |
2597 | return ImageFromStream(stream) | |
2598 | ||
2599 | def getAddWatchIcon(): | |
bbf7159c | 2600 | return wx.IconFromBitmap(getAddWatchBitmap()) |
02b800ce RD |
2601 | |
2602 | #---------------------------------------------------------------------- | |
2603 | def getRunningManData(): | |
2604 | return \ | |
2605 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2606 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2607 | \x00\x01\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\ | |
2608 | \x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\ | |
2609 | %\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\ | |
2610 | \x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \ | |
2611 | \\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\ | |
2612 | \xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\ | |
2613 | CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\ | |
2614 | \x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\ | |
2615 | \x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\ | |
2616 | \x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\ | |
2617 | \x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\ | |
2618 | \r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\ | |
2619 | \x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\ | |
2620 | \xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\ | |
2621 | \xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\ | |
2622 | \xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82' | |
2623 | ||
2624 | def getRunningManBitmap(): | |
2625 | return BitmapFromImage(getRunningManImage()) | |
2626 | ||
2627 | def getRunningManImage(): | |
2628 | stream = cStringIO.StringIO(getRunningManData()) | |
2629 | return ImageFromStream(stream) | |
2630 | ||
2631 | def getRunningManIcon(): | |
2632 | icon = EmptyIcon() | |
2633 | icon.CopyFromBitmap(getRunningManBitmap()) | |
2634 | return icon | |
2635 | ||
2636 | #---------------------------------------------------------------------- | |
2637 | def getDebuggingManData(): | |
2638 | return \ | |
2639 | '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | |
2640 | \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | |
2641 | \x00\x01\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\ | |
2642 | \xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\ | |
2643 | \xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\ | |
2644 | \xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\ | |
2645 | \xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\ | |
2646 | ++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\ | |
2647 | f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\ | |
2648 | \x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\ | |
2649 | \xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\ | |
2650 | \xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\ | |
2651 | \x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\ | |
2652 | \x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\ | |
2653 | \xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\ | |
2654 | \xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\ | |
2655 | \x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\ | |
2656 | \x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\ | |
2657 | \x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\ | |
2658 | \xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82' | |
2659 | ||
2660 | def getDebuggingManBitmap(): | |
2661 | return BitmapFromImage(getDebuggingManImage()) | |
2662 | ||
2663 | def getDebuggingManImage(): | |
2664 | stream = cStringIO.StringIO(getDebuggingManData()) | |
2665 | return ImageFromStream(stream) | |
2666 | ||
2667 | def getDebuggingManIcon(): | |
2668 | icon = EmptyIcon() | |
2669 | icon.CopyFromBitmap(getDebuggingManBitmap()) | |
2670 | return icon | |
2671 | ||
2672 | #---------------------------------------------------------------------- | |
2673 |