]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/tool/DebuggerService.py
fixed wxVsnprintf() to write as much as it can if the output buffer is too short
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / DebuggerService.py
1 #----------------------------------------------------------------------------
2 # Name: DebuggerService.py
3 # Purpose: Debugger Service for Python and PHP
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 import PHPEditor
25 import PHPDebugger
26 import activegrid.model.projectmodel as projectmodel
27 from IDE import ACTIVEGRID_BASE_IDE
28 if not ACTIVEGRID_BASE_IDE:
29 import ProcessModelEditor
30 import wx.lib.scrolledpanel as scrolled
31 import sys
32 import time
33 import SimpleXMLRPCServer
34 import xmlrpclib
35 import os
36 import threading
37 import Queue
38 import SocketServer
39 import ProjectEditor
40 import types
41 from xml.dom.minidom import parse, parseString
42 import bz2
43 import pickle
44 import DebuggerHarness
45 import traceback
46 import StringIO
47 import UICommon
48 import activegrid.util.sysutils as sysutilslib
49 import subprocess
50 import shutil
51
52 if wx.Platform == '__WXMSW__':
53 try:
54 import win32api
55 _PYWIN32_INSTALLED = True
56 except ImportError:
57 _PYWIN32_INSTALLED = False
58 _WINDOWS = True
59 else:
60 _WINDOWS = False
61
62 if not _WINDOWS or _PYWIN32_INSTALLED:
63 import process
64
65 _ = wx.GetTranslation
66
67 _VERBOSE = False
68 _WATCHES_ON = False
69
70 import wx.lib.newevent
71 (UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent()
72 (UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent()
73 (DebugInternalWebServer, EVT_DEBUG_INTERNAL) = wx.lib.newevent.NewEvent()
74
75 # Class to read from stdout or stderr and write the result to a text control.
76 # Args: file=file-like object
77 # callback_function= function that takes a single argument, the line of text
78 # read.
79 class OutputReaderThread(threading.Thread):
80 def __init__(self, file, callback_function, callbackOnExit=None, accumulate=True):
81 threading.Thread.__init__(self)
82 self._file = file
83 self._callback_function = callback_function
84 self._keepGoing = True
85 self._lineCount = 0
86 self._accumulate = accumulate
87 self._callbackOnExit = callbackOnExit
88 self.setDaemon(True)
89
90 def __del__(self):
91 # See comment on PythonDebuggerUI.StopExecution
92 self._keepGoing = False
93
94 def run(self):
95 file = self._file
96 start = time.time()
97 output = ""
98 while self._keepGoing:
99 try:
100 # This could block--how to handle that?
101 text = file.readline()
102 if text == '' or text == None:
103 self._keepGoing = False
104 elif not self._accumulate and self._keepGoing:
105 self._callback_function(text)
106 else:
107 # Should use a buffer? StringIO?
108 output += text
109 # Seems as though the read blocks if we got an error, so, to be
110 # sure that at least some of the exception gets printed, always
111 # send the first hundred lines back as they come in.
112 if self._lineCount < 100 and self._keepGoing:
113 self._callback_function(output)
114 self._lineCount += 1
115 output = ""
116 elif time.time() - start > 0.25 and self._keepGoing:
117 try:
118 self._callback_function(output)
119 except wx._core.PyDeadObjectError:
120 # GUI was killed while we were blocked.
121 self._keepGoing = False
122 start = time.time()
123 output = ""
124 #except TypeError:
125 # pass
126 except:
127 tp, val, tb = sys.exc_info()
128 print "Exception in OutputReaderThread.run():", tp, val
129 self._keepGoing = False
130 if self._callbackOnExit:
131 try:
132 self._callbackOnExit()
133 except wx._core.PyDeadObjectError:
134 pass
135 if _VERBOSE: print "Exiting OutputReaderThread"
136
137 def AskToStop(self):
138 self._keepGoing = False
139
140
141 class Executor:
142 PHP_CGI_BIN_PATH_WIN = "../../3rdparty/php"
143 PHP_CGI_BIN_PATH_UNIX = "../../../3rdparty/php/bin"
144 PHP_CGI_BIN_PATH_OSX = "../3rdparty/php/bin"
145 PHP_CGI_EXEC_WIN = "php-cgi.exe"
146 PHP_CGI_EXEC_UNIX = "php"
147 PHP_CGI_EXEC_OSX = "php-cgi"
148
149 def GetPythonExecutablePath():
150 path = UICommon.GetPythonExecPath()
151 if path:
152 return path
153 wx.MessageBox(_("To proceed we 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"))
154 return None
155 GetPythonExecutablePath = staticmethod(GetPythonExecutablePath)
156
157 def GetPHPExecutablePath():
158 if sysutilslib.isWindows():
159 phpCgiBinPath = Executor.PHP_CGI_BIN_PATH_WIN
160 phpCgiExec = Executor.PHP_CGI_EXEC_WIN
161 elif sys.platform == "darwin":
162 phpCgiBinPath = Executor.PHP_CGI_BIN_PATH_OSX
163 phpCgiExec = Executor.PHP_CGI_EXEC_OSX
164 else:
165 phpCgiBinPath = Executor.PHP_CGI_BIN_PATH_UNIX
166 phpCgiExec = Executor.PHP_CGI_EXEC_UNIX
167
168 if sysutilslib.isRelease():
169 phpCgiExecFullPath = os.path.normpath(os.path.join(sysutilslib.mainModuleDir, phpCgiBinPath, phpCgiExec))
170 else:
171 phpCgiExecFullPath = phpCgiExec
172
173 if _VERBOSE:
174 print "php cgi executable full path is: %s" % phpCgiExecFullPath
175
176 return phpCgiExecFullPath
177 GetPHPExecutablePath = staticmethod(GetPHPExecutablePath)
178
179 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):
180 self._fileName = fileName
181 self._stdOutCallback = self.OutCall
182 self._stdErrCallback = self.ErrCall
183 self._callbackOnExit = callbackOnExit
184 self._wxComponent = wxComponent
185 if fileName.endswith('.py') or fileName.endswith('.pyc'):
186 self._path = Executor.GetPythonExecutablePath()
187 self._cmd = '"' + self._path + '" -u \"' + fileName + '\"'
188 else:
189 self._path = Executor.GetPHPExecutablePath()
190 self._cmd = '"' + self._path + '"'
191 #Better way to do this? Quotes needed for windows file paths.
192 def spaceAndQuote(text):
193 if text.startswith("\"") and text.endswith("\""):
194 return ' ' + text
195 else:
196 return ' \"' + text + '\"'
197 if(arg1 != None):
198 self._cmd += spaceAndQuote(arg1)
199 if(arg2 != None):
200 self._cmd += spaceAndQuote(arg2)
201 if(arg3 != None):
202 self._cmd += spaceAndQuote(arg3)
203 if(arg4 != None):
204 self._cmd += spaceAndQuote(arg4)
205 if(arg5 != None):
206 self._cmd += spaceAndQuote(arg5)
207 if(arg6 != None):
208 self._cmd += spaceAndQuote(arg6)
209 if(arg7 != None):
210 self._cmd += spaceAndQuote(arg7)
211 if(arg8 != None):
212 self._cmd += spaceAndQuote(arg8)
213 if(arg9 != None):
214 self._cmd += spaceAndQuote(arg9)
215
216 self._stdOutReader = None
217 self._stdErrReader = None
218 self._process = None
219
220 def OutCall(self, text):
221 evt = UpdateTextEvent(value = text)
222 wx.PostEvent(self._wxComponent, evt)
223
224 def ErrCall(self, text):
225 evt = UpdateErrorEvent(value = text)
226 wx.PostEvent(self._wxComponent, evt)
227
228 def Execute(self, arguments, startIn=None, environment=None):
229 if not startIn:
230 startIn = str(os.getcwd())
231 startIn = os.path.abspath(startIn)
232
233 if arguments and arguments != " ":
234 command = self._cmd + ' ' + arguments
235 else:
236 command = self._cmd
237
238 if _VERBOSE: print "start debugger executable: " + command + "\n"
239 self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment)
240 # Kick off threads to read stdout and stderr and write them
241 # to our text control.
242 self._stdOutReader = OutputReaderThread(self._process.stdout, self._stdOutCallback, callbackOnExit=self._callbackOnExit)
243 self._stdOutReader.start()
244 self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False)
245 self._stdErrReader.start()
246
247 def DoStopExecution(self):
248 # See comment on PythonDebuggerUI.StopExecution
249 if(self._process != None):
250 self._stdOutReader.AskToStop()
251 self._stdErrReader.AskToStop()
252 try:
253 self._process.kill(gracePeriod=2.0)
254 except:
255 pass
256 self._process = None
257
258 def GetExecPath(self):
259 return self._path
260
261 class RunCommandUI(wx.Panel):
262 runners = []
263
264 def ShutdownAllRunners():
265 # See comment on PythonDebuggerUI.StopExecution
266 for runner in RunCommandUI.runners:
267 try:
268 runner.StopExecution(None)
269 except wx._core.PyDeadObjectError:
270 pass
271 RunCommandUI.runners = []
272 ShutdownAllRunners = staticmethod(ShutdownAllRunners)
273
274 def __init__(self, parent, id, fileName):
275 wx.Panel.__init__(self, parent, id)
276 self._noteBook = parent
277
278 threading._VERBOSE = _VERBOSE
279
280 self.KILL_PROCESS_ID = wx.NewId()
281 self.CLOSE_TAB_ID = wx.NewId()
282
283
284 # GUI Initialization follows
285 sizer = wx.BoxSizer(wx.HORIZONTAL)
286 self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" )
287 tb.SetToolBitmapSize((16,16))
288 sizer.Add(tb, 0, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL, 1)
289
290 close_bmp = getCloseBitmap()
291 tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window'))
292 wx.EVT_TOOL(self, self.CLOSE_TAB_ID, self.OnToolClicked)
293
294 stop_bmp = getStopBitmap()
295 tb.AddSimpleTool(self.KILL_PROCESS_ID, stop_bmp, _("Stop the Run."))
296 wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.OnToolClicked)
297
298 tb.Realize()
299 self._textCtrl = STCTextEditor.TextCtrl(self, wx.NewId()) #id)
300 sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
301 self._textCtrl.SetViewLineNumbers(False)
302 self._textCtrl.SetReadOnly(True)
303 if wx.Platform == '__WXMSW__':
304 font = "Courier New"
305 else:
306 font = "Courier"
307 self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
308 self._textCtrl.SetFontColor(wx.BLACK)
309 self._textCtrl.StyleClearAll()
310
311 wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
312
313 self.SetSizer(sizer)
314 sizer.Fit(self)
315
316 self._stopped = False
317 # Executor initialization
318 self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished)
319 self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
320 self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
321
322 RunCommandUI.runners.append(self)
323
324 def __del__(self):
325 # See comment on PythonDebuggerUI.StopExecution
326 self._executor.DoStopExecution()
327
328 def Execute(self, initialArgs, startIn, environment, onWebServer = False):
329 self._executor.Execute(initialArgs, startIn, environment)
330
331 def ExecutorFinished(self):
332 self._tb.EnableTool(self.KILL_PROCESS_ID, False)
333 nb = self.GetParent()
334 for i in range(0,nb.GetPageCount()):
335 if self == nb.GetPage(i):
336 text = nb.GetPageText(i)
337 newText = text.replace("Running", "Finished")
338 nb.SetPageText(i, newText)
339 break
340
341 def StopExecution(self):
342 if not self._stopped:
343 self._stopped = True
344 self.Unbind(EVT_UPDATE_STDTEXT)
345 self.Unbind(EVT_UPDATE_ERRTEXT)
346 self._executor.DoStopExecution()
347
348 def AppendText(self, event):
349 self._textCtrl.SetReadOnly(False)
350 self._textCtrl.AddText(event.value)
351 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
352 self._textCtrl.SetReadOnly(True)
353
354 def AppendErrorText(self, event):
355 self._textCtrl.SetReadOnly(False)
356 self._textCtrl.SetFontColor(wx.RED)
357 self._textCtrl.StyleClearAll()
358 self._textCtrl.AddText(event.value)
359 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
360 self._textCtrl.SetFontColor(wx.BLACK)
361 self._textCtrl.StyleClearAll()
362 self._textCtrl.SetReadOnly(True)
363
364 def StopAndRemoveUI(self, event):
365 self.StopExecution()
366 self.StopExecution()
367 index = self._noteBook.GetSelection()
368 self._noteBook.GetPage(index).Show(False)
369 self._noteBook.RemovePage(index)
370
371 #------------------------------------------------------------------------------
372 # Event handling
373 #-----------------------------------------------------------------------------
374
375 def OnToolClicked(self, event):
376 id = event.GetId()
377
378 if id == self.KILL_PROCESS_ID:
379 self.StopExecution()
380
381 elif id == self.CLOSE_TAB_ID:
382 self.StopAndRemoveUI(event)
383
384 def OnDoubleClick(self, event):
385 # Looking for a stack trace line.
386 lineText, pos = self._textCtrl.GetCurLine()
387 fileBegin = lineText.find("File \"")
388 fileEnd = lineText.find("\", line ")
389 lineEnd = lineText.find(", in ")
390 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
391 # Check the line before the one that was clicked on
392 lineNumber = self._textCtrl.GetCurrentLine()
393 if(lineNumber == 0):
394 return
395 lineText = self._textCtrl.GetLine(lineNumber - 1)
396 fileBegin = lineText.find("File \"")
397 fileEnd = lineText.find("\", line ")
398 lineEnd = lineText.find(", in ")
399 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
400 return
401
402 filename = lineText[fileBegin + 6:fileEnd]
403 lineNum = int(lineText[fileEnd + 8:lineEnd])
404
405 foundView = None
406 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
407 for openDoc in openDocs:
408 if openDoc.GetFilename() == filename:
409 foundView = openDoc.GetFirstView()
410 break
411
412 if not foundView:
413 doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
414 foundView = doc.GetFirstView()
415
416 if foundView:
417 foundView.GetFrame().SetFocus()
418 foundView.Activate()
419 foundView.GotoLine(lineNum)
420 startPos = foundView.PositionFromLine(lineNum)
421 lineText = foundView.GetCtrl().GetLine(lineNum - 1)
422 foundView.SetSelection(startPos, startPos + len(lineText.rstrip("\n")))
423 import OutlineService
424 wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
425
426
427 DEFAULT_PORT = 32032
428 DEFAULT_HOST = 'localhost'
429 PORT_COUNT = 21
430
431 class BaseDebuggerUI(wx.Panel):
432 debuggers = []
433
434 def NotifyDebuggersOfBreakpointChange():
435 for debugger in BaseDebuggerUI.debuggers:
436 debugger.BreakPointChange()
437
438 NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange)
439
440 def DebuggerRunning():
441 for debugger in BaseDebuggerUI.debuggers:
442 if debugger._executor:
443 return True
444 return False
445 DebuggerRunning = staticmethod(DebuggerRunning)
446
447 def DebuggerInWait():
448 for debugger in BaseDebuggerUI.debuggers:
449 if debugger._executor:
450 if debugger._callback._waiting:
451 return True
452 return False
453 DebuggerInWait = staticmethod(DebuggerInWait)
454
455 def DebuggerPastAutoContinue():
456 for debugger in BaseDebuggerUI.debuggers:
457 if debugger._executor:
458 if debugger._callback._waiting and not debugger._callback._autoContinue:
459 return True
460 return False
461 DebuggerPastAutoContinue = staticmethod(DebuggerPastAutoContinue)
462
463 def ShutdownAllDebuggers():
464 for debugger in BaseDebuggerUI.debuggers:
465 try:
466 debugger.StopExecution(None)
467 except wx._core.PyDeadObjectError:
468 pass
469 BaseDebuggerUI.debuggers = []
470 ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
471
472 def __init__(self, parent, id):
473 wx.Panel.__init__(self, parent, id)
474 self._parentNoteBook = parent
475
476 self._service = None
477 self._executor = None
478 self._callback = None
479 self._stopped = False
480
481 BaseDebuggerUI.debuggers.append(self)
482 self._stopped = True
483 self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
484 self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
485 self._executor = None
486
487 self.STEP_ID = wx.NewId()
488 self.CONTINUE_ID = wx.NewId()
489 self.STEP_OUT_ID = wx.NewId()
490 self.NEXT_ID = wx.NewId()
491 self.KILL_PROCESS_ID = wx.NewId()
492 self.CLOSE_WINDOW_ID = wx.NewId()
493 self.BREAK_INTO_DEBUGGER_ID = wx.NewId()
494 self.CLEAR_ID = wx.NewId()
495 self.ADD_WATCH_ID = wx.NewId()
496 sizer = wx.BoxSizer(wx.VERTICAL)
497 self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (1000,30), wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT| wx.TB_TEXT, "Debugger" )
498 sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
499 tb.SetToolBitmapSize((16,16))
500
501 close_bmp = getCloseBitmap()
502 tb.AddSimpleTool( self.CLOSE_WINDOW_ID, close_bmp, _('Close Window'))
503 wx.EVT_TOOL(self, self.CLOSE_WINDOW_ID, self.StopAndRemoveUI)
504
505 stop_bmp = getStopBitmap()
506 tb.AddSimpleTool( self.KILL_PROCESS_ID, stop_bmp, _("Stop Debugging"))
507 wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.StopExecution)
508
509 tb.AddSeparator()
510
511 break_bmp = getBreakBitmap()
512 tb.AddSimpleTool( self.BREAK_INTO_DEBUGGER_ID, break_bmp, _("Break into Debugger"))
513 wx.EVT_TOOL(self, self.BREAK_INTO_DEBUGGER_ID, self.BreakExecution)
514
515 tb.AddSeparator()
516
517 continue_bmp = getContinueBitmap()
518 tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution"))
519 wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue)
520 self.Bind(EVT_DEBUG_INTERNAL, self.OnContinue)
521
522 tb.AddSeparator()
523 next_bmp = getNextBitmap()
524 tb.AddSimpleTool( self.NEXT_ID, next_bmp, _("Step to next line"))
525 wx.EVT_TOOL(self, self.NEXT_ID, self.OnNext)
526
527 step_bmp = getStepInBitmap()
528 tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in"))
529 wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep)
530
531 stepOut_bmp = getStepReturnBitmap()
532 tb.AddSimpleTool(self.STEP_OUT_ID, stepOut_bmp, _("Stop at function return"))
533 wx.EVT_TOOL(self, self.STEP_OUT_ID, self.OnStepOut)
534
535 tb.AddSeparator()
536 if _WATCHES_ON:
537 watch_bmp = getAddWatchBitmap()
538 tb.AddSimpleTool(self.ADD_WATCH_ID, watch_bmp, _("Add a watch"))
539 wx.EVT_TOOL(self, self.ADD_WATCH_ID, self.OnAddWatch)
540 tb.AddSeparator()
541
542 clear_bmp = getClearOutputBitmap()
543 tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane"))
544 wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput)
545
546 self._toolEnabled = True
547 self.framesTab = None
548 self.DisableWhileDebuggerRunning()
549 self.framesTab = self.MakeFramesUI(self, wx.NewId(), None)
550 sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
551 self._statusBar = wx.StatusBar( self, -1)
552 self._statusBar.SetFieldsCount(1)
553 sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
554 self.SetStatusText("Starting debug...")
555 self.SetSizer(sizer)
556 tb.Realize()
557 sizer.Fit(self)
558
559 def OnSingleStep(self, event):
560 self._callback.SingleStep()
561
562 def OnContinue(self, event):
563 self._callback.Continue()
564
565 def OnStepOut(self, event):
566 self._callback.Return()
567
568 def OnNext(self, event):
569 self._callback.Next()
570
571 def BreakPointChange(self):
572 if not self._stopped:
573 self._callback.PushBreakpoints()
574 self.framesTab.PopulateBPList()
575
576 def __del__(self):
577 # See comment on PythonDebuggerUI.StopExecution
578 self.StopExecution(None)
579
580 def DisableWhileDebuggerRunning(self):
581 if self._toolEnabled:
582 self._tb.EnableTool(self.STEP_ID, False)
583 self._tb.EnableTool(self.CONTINUE_ID, False)
584 self._tb.EnableTool(self.STEP_OUT_ID, False)
585 self._tb.EnableTool(self.NEXT_ID, False)
586 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, True)
587
588 if _WATCHES_ON:
589 self._tb.EnableTool(self.ADD_WATCH_ID, False)
590
591 self.DeleteCurrentLineMarkers()
592
593 if self.framesTab:
594 self.framesTab.ClearWhileRunning()
595
596 self._toolEnabled = False
597
598 def EnableWhileDebuggerStopped(self):
599 self._tb.EnableTool(self.STEP_ID, True)
600 self._tb.EnableTool(self.CONTINUE_ID, True)
601 self._tb.EnableTool(self.STEP_OUT_ID, True)
602 self._tb.EnableTool(self.NEXT_ID, True)
603 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
604 self._tb.EnableTool(self.KILL_PROCESS_ID, True)
605
606 if _WATCHES_ON:
607 self._tb.EnableTool(self.ADD_WATCH_ID, True)
608
609 self._toolEnabled = True
610
611 def DisableAfterStop(self):
612 if self._toolEnabled:
613 self.DisableWhileDebuggerRunning()
614 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
615 self._tb.EnableTool(self.KILL_PROCESS_ID, False)
616
617 def ExecutorFinished(self):
618 if _VERBOSE: print "In ExectorFinished"
619 try:
620 self.DisableAfterStop()
621 except wx._core.PyDeadObjectError:
622 pass
623 try:
624 nb = self.GetParent()
625 for i in range(0, nb.GetPageCount()):
626 if self == nb.GetPage(i):
627 text = nb.GetPageText(i)
628 newText = text.replace("Debugging", "Finished")
629 nb.SetPageText(i, newText)
630 if _VERBOSE: print "In ExectorFinished, changed tab title."
631 break
632 except:
633 if _VERBOSE: print "In ExectorFinished, got exception"
634
635 def SetStatusText(self, text):
636 self._statusBar.SetStatusText(text,0)
637
638 def BreakExecution(self, event):
639 self._callback.BreakExecution()
640
641 def StopExecution(self, event):
642 self._callback.ShutdownServer()
643
644 def Execute(self, initialArgs, startIn, environment, onWebServer = False):
645 assert False, "Execute not overridden"
646
647 def SynchCurrentLine(self, filename, lineNum, noArrow=False):
648 self.DeleteCurrentLineMarkers()
649
650 # Filename will be <string> if we're in a bit of code that was executed from
651 # a string (rather than a file). I haven't been able to get the original string
652 # for display.
653 if filename == '<string>':
654 return
655 foundView = None
656 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
657 for openDoc in openDocs:
658 # This ugliness to prevent comparison failing because the drive letter
659 # gets lowercased occasionally. Don't know why that happens or why it
660 # only happens occasionally.
661 if DebuggerService.ComparePaths(openDoc.GetFilename(),filename):
662 foundView = openDoc.GetFirstView()
663 break
664
665 if not foundView:
666 if _VERBOSE:
667 print "filename=", filename
668 doc = wx.GetApp().GetDocumentManager().CreateDocument(DebuggerService.ExpandPath(filename), wx.lib.docview.DOC_SILENT)
669 foundView = doc.GetFirstView()
670
671 if foundView:
672 foundView.GetFrame().SetFocus()
673 foundView.Activate()
674 foundView.GotoLine(lineNum)
675 startPos = foundView.PositionFromLine(lineNum)
676
677 if not noArrow:
678 foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
679
680 def DeleteCurrentLineMarkers(self):
681 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
682 for openDoc in openDocs:
683 if(isinstance(openDoc, CodeEditor.CodeDocument)):
684 openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
685
686 def StopAndRemoveUI(self, event):
687 self.StopExecution(None)
688 if self in BaseDebuggerUI.debuggers:
689 BaseDebuggerUI.debuggers.remove(self)
690 index = self._parentNoteBook.GetSelection()
691 self._parentNoteBook.GetPage(index).Show(False)
692 self._parentNoteBook.RemovePage(index)
693
694 def OnAddWatch(self, event):
695 if self.framesTab:
696 self.framesTab.OnWatch(event)
697
698 def MakeFramesUI(self, parent, id, debugger):
699 assert False, "MakeFramesUI not overridden"
700
701 def AppendText(self, event):
702 self.framesTab.AppendText(event.value)
703
704 def AppendErrorText(self, event):
705 self.framesTab.AppendErrorText(event.value)
706
707 def OnClearOutput(self, event):
708 self.framesTab.ClearOutput(None)
709
710 def SwitchToOutputTab(self):
711 self.framesTab.SwitchToOutputTab()
712
713
714 class PHPDebuggerUI(BaseDebuggerUI):
715 DEFAULT_LISTENER_HOST = "127.0.0.1"
716 DEFAULT_LISTENER_PORT = 10001
717 DEFAULT_DBG_MOD_TIMEOUT = 300
718 DEFAULT_DBG_MAX_EXEC_TIME = 240
719 dbgSessSeqId = 1
720
721 def __init__(self, parent, id, command, service):
722 BaseDebuggerUI.__init__(self, parent, id)
723 #Note host and port need to come out of options or a pool.
724 self._dbgHost = PHPDebuggerUI.DEFAULT_LISTENER_HOST
725 self._dbgPort = PHPDebuggerUI.DEFAULT_LISTENER_PORT
726 self._dbgTimeout = PHPDebuggerUI.DEFAULT_DBG_MOD_TIMEOUT
727 self._dbgMaxExecTime = PHPDebuggerUI.DEFAULT_DBG_MAX_EXEC_TIME
728 self._dbgSessId = None
729 self._dbgSessParam = None
730 self._dbgPhpIniFile = None
731 self._callback = PHPDebugger.PHPDebuggerCallback(self, service, self._dbgHost, self._dbgPort)
732 self._executor = Executor(command, self)
733 self._service = service
734 self._stopped = False
735 self._allStopped = False
736
737 self._createPhpDbgSess()
738
739 def showErrorDialog(self, message, title):
740 wx.MessageBox(_(message), _(title))
741 return
742
743 def _createPhpDbgSess(self):
744 currTimeStr = str(time.time())
745 (secStr, usecStr) = currTimeStr.split('.')
746 secLongInt = long(secStr)
747 usecLongInt = long(usecStr)
748 self._dbgSessId = "%06ld%06ld%04d" % (secLongInt, usecLongInt, PHPDebuggerUI.dbgSessSeqId)
749 PHPDebuggerUI.dbgSessSeqId = PHPDebuggerUI.dbgSessSeqId + 1
750 self._dbgSessParam = "DBGSESSID=%s@clienthost:%d" % (self._dbgSessId, self._dbgPort)
751
752 if _VERBOSE:
753 print "phpDbgParam=%s" % self._dbgSessParam
754
755 self._service.SetPhpDbgParam(self._dbgSessParam)
756
757 def _preparePhpIniFile(self):
758 success = False
759
760 phpCgiExec = Executor.GetPHPExecutablePath()
761 phpExec = phpCgiExec.replace("php-cgi", "php")
762 iniPath = self._getPhpIniFromRunningPhp(phpExec)
763
764 try:
765 iniDbgPath = os.path.normpath(iniPath + ".ag_debug_enabled")
766 dbgFile = open(iniDbgPath, "w")
767 oriFile = open(iniPath, "r")
768
769 while True:
770 oneOriLine = oriFile.readline()
771 if oneOriLine == '':
772 break
773
774 if not oneOriLine.startswith("debugger.") and not oneOriLine.startswith("max_execution_time="):
775 dbgFile.write(oneOriLine)
776
777 oriFile.close()
778
779 if _WINDOWS:
780 dbgExtFile = "php_dbg.dll"
781 else:
782 dbgExtFile = "dbg.so"
783
784 #
785 # TODO: we should make all of these options configurable.
786 #
787 configStr = "\n; ===============================================================\n; The followings are added by ActiveGrid IDE PHP Debugger Runtime\n; ===============================================================\n\n; As we are running with the dbg module, it takes a much longer time for each script to run.\nmax_execution_time=%d\n\n[debugger]\nextension=%s\ndebugger.enabled=On\ndebugger.JIT_enabled=On\ndebugger.JIT_host=%s\ndebugger.JIT_port=%d\ndebugger.fail_silently=Off\ndebugger.timeout_seconds=%d\ndebugger.ignore_nops=Off\ndebugger.enable_session_cookie=On\ndebugger.session_nocache=On\ndebugger.profiler_enabled=Off\n" % (self._dbgMaxExecTime, dbgExtFile, self._dbgHost, self._dbgPort, self._dbgTimeout)
788 dbgFile.write(configStr)
789 dbgFile.close()
790 success = True
791 except:
792 #TODO: print stack trace.
793 print "Caught exceptions while minipulating php.ini files"
794
795 if success:
796 self._dbgPhpIniFile = iniDbgPath
797 else:
798 self._dbgPhpIniFile = None
799
800 def _getPhpIniFromRunningPhp(self, phpExec):
801 phpIniPath = None
802
803 cmdEnv = os.environ
804 if cmdEnv.has_key('PYTHONPATH'):
805 del cmdEnv['PYTHONPATH']
806
807 cmdLine = [phpExec, "-r", "phpinfo();"]
808 phpProc = subprocess.Popen(args=cmdLine, bufsize=0, executable=None, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=os.environ, universal_newlines=False, startupinfo=None, creationflags=0)
809 phpOutput = phpProc.stdout
810
811 phpIniPattern = "Configuration File (php.ini) Path => "
812 while True:
813 oneLine = phpOutput.readline()
814 if oneLine == '':
815 break
816
817 if oneLine.startswith(phpIniPattern):
818 if oneLine.endswith("\n"):
819 endIndex = oneLine.index("\n")
820 phpIniPath = oneLine[len(phpIniPattern):endIndex]
821 else:
822 phpIniPath = oneLine[len(phpIniPattern):]
823
824 if phpIniPath and len(phpIniPath) > 0:
825 phpIniPath = os.path.normpath(phpIniPath)
826 break
827
828 phpOutput.close()
829
830 if _VERBOSE:
831 print "php.ini path is: %s" % repr(phpIniPath)
832
833 return phpIniPath
834
835 def Execute(self, initialArgs, startIn, environment, onWebServer = False):
836 self._preparePhpIniFile()
837 self._callback.Start()
838
839 if not onWebServer:
840 if self._dbgPhpIniFile:
841 args = '-c "' + self._dbgPhpIniFile + '" ' + initialArgs
842 else:
843 args = initialArgs
844
845 self._executor.Execute(args, startIn, environment)
846
847 def StopExecution(self, event):
848 # This is a general comment on shutdown for the running and debugged processes. Basically, the
849 # current state of this is the result of trial and error coding. The common problems were memory
850 # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
851 # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
852 # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
853 # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
854 # it on to mfryer@activegrid.com.
855 if not self._allStopped:
856 self._stopped = True
857 try:
858 self.DisableAfterStop()
859 except wx._core.PyDeadObjectError:
860 pass
861
862 try:
863 #
864 # If this is called by clicking the "Stop" button, we only stop
865 # the current running php script, and keep the listener
866 # running.
867 #
868 if event:
869 self._callback.ShutdownServer(stopLsnr = False)
870 else:
871 self._callback.ShutdownServer(stopLsnr = True)
872 self._allStopped = True
873 except:
874 tp,val,tb = sys.exc_info()
875 traceback.print_exception(tp, val, tb)
876
877 try:
878 self.DeleteCurrentLineMarkers()
879 except:
880 pass
881
882 try:
883 if self._executor:
884 self._executor.DoStopExecution()
885 self._executor = None
886 except:
887 tp,val,tb = sys.exc_info()
888 traceback.print_exception(tp, val, tb)
889
890 def MakeFramesUI(self, parent, id, debugger):
891 return PHPFramesUI(parent, id, self)
892
893 def LoadPHPFramesList(self, stackList):
894 self.framesTab.LoadFramesList(stackList)
895
896 #
897 # TODO: this is a hack to overwrite BaseDebuggerUI's function. The purpose
898 # is to always push breakpoints no matter if a php is running or not. If
899 # no php is running, an exception will be thrown and handled like nothing
900 # happened.
901 #
902 def BreakPointChange(self):
903 self._callback.PushBreakpoints()
904 self.framesTab.PopulateBPList()
905
906
907 class PythonDebuggerUI(BaseDebuggerUI):
908 debuggerPortList = None
909
910 def GetAvailablePort():
911 for index in range( 0, len(PythonDebuggerUI.debuggerPortList)):
912 port = PythonDebuggerUI.debuggerPortList[index]
913 if PythonDebuggerUI.PortAvailable(port):
914 PythonDebuggerUI.debuggerPortList.pop(index)
915 return port
916 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"))
917 assert False, "Out of ports for debugger."
918
919 GetAvailablePort = staticmethod(GetAvailablePort)
920
921 def ReturnPortToPool(port):
922 config = wx.ConfigBase_Get()
923 startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
924 val = int(startingPort) + int(PORT_COUNT)
925 if int(port) >= startingPort and (int(port) <= val):
926 PythonDebuggerUI.debuggerPortList.append(int(port))
927
928 ReturnPortToPool = staticmethod(ReturnPortToPool)
929
930 def PortAvailable(port):
931 config = wx.ConfigBase_Get()
932 hostname = config.Read("DebuggerHostName", DEFAULT_HOST)
933 try:
934 server = AGXMLRPCServer((hostname, port))
935 server.server_close()
936 if _VERBOSE: print "Port ", str(port), " available."
937 return True
938 except:
939 tp,val,tb = sys.exc_info()
940 if _VERBOSE: traceback.print_exception(tp, val, tb)
941 if _VERBOSE: print "Port ", str(port), " unavailable."
942 return False
943
944 PortAvailable = staticmethod(PortAvailable)
945
946 def NewPortRange():
947 config = wx.ConfigBase_Get()
948 startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
949 PythonDebuggerUI.debuggerPortList = range(startingPort, startingPort + PORT_COUNT)
950 NewPortRange = staticmethod(NewPortRange)
951
952 def __init__(self, parent, id, command, service, autoContinue=True):
953 # Check for ports before creating the panel.
954 if not PythonDebuggerUI.debuggerPortList:
955 PythonDebuggerUI.NewPortRange()
956 self._debuggerPort = str(PythonDebuggerUI.GetAvailablePort())
957 self._guiPort = str(PythonDebuggerUI.GetAvailablePort())
958 self._debuggerBreakPort = str(PythonDebuggerUI.GetAvailablePort())
959 BaseDebuggerUI.__init__(self, parent, id)
960 self._command = command
961 self._service = service
962 config = wx.ConfigBase_Get()
963 self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST)
964
965 url = 'http://' + self._debuggerHost + ':' + self._debuggerPort + '/'
966 self._breakURL = 'http://' + self._debuggerHost + ':' + self._debuggerBreakPort + '/'
967 self._callback = PythonDebuggerCallback(self._guiHost, self._guiPort, url, self._breakURL, self, autoContinue)
968 if DebuggerHarness.__file__.find('library.zip') > 0:
969 try:
970 fname = DebuggerHarness.__file__
971 parts = fname.split('library.zip')
972 path = os.path.join(parts[0],'activegrid', 'tool', 'DebuggerHarness.py')
973 except:
974 tp, val, tb = sys.exc_info()
975 traceback.print_exception(tp, val, tb)
976
977 else:
978 print "Starting debugger on these ports: %s, %s, %s" % (str(self._debuggerPort) , str(self._guiPort) , str(self._debuggerBreakPort))
979 path = DebuggerService.ExpandPath(DebuggerHarness.__file__)
980 self._executor = Executor(path, self, self._debuggerHost, \
981 self._debuggerPort, self._debuggerBreakPort, self._guiHost, self._guiPort, self._command, callbackOnExit=self.ExecutorFinished)
982
983 self._stopped = False
984
985 def LoadPythonFramesList(self, framesXML):
986 self.framesTab.LoadFramesList(framesXML)
987
988 def Execute(self, initialArgs, startIn, environment, onWebServer = False):
989 self._callback.Start()
990 self._executor.Execute(initialArgs, startIn, environment)
991 self._callback.WaitForRPC()
992
993
994 def StopExecution(self, event):
995 # This is a general comment on shutdown for the running and debugged processes. Basically, the
996 # current state of this is the result of trial and error coding. The common problems were memory
997 # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
998 # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
999 # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
1000 # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
1001 # it on to mfryer@activegrid.com.
1002 if not self._stopped:
1003 self._stopped = True
1004 try:
1005 self.DisableAfterStop()
1006 except wx._core.PyDeadObjectError:
1007 pass
1008 try:
1009 self._callback.ShutdownServer()
1010 except:
1011 tp,val,tb = sys.exc_info()
1012 traceback.print_exception(tp, val, tb)
1013
1014 try:
1015 self.DeleteCurrentLineMarkers()
1016 except:
1017 pass
1018 try:
1019 PythonDebuggerUI.ReturnPortToPool(self._debuggerPort)
1020 PythonDebuggerUI.ReturnPortToPool(self._guiPort)
1021 PythonDebuggerUI.ReturnPortToPool(self._debuggerBreakPort)
1022 except:
1023 pass
1024 try:
1025 if self._executor:
1026 self._executor.DoStopExecution()
1027 self._executor = None
1028 except:
1029 tp,val,tb = sys.exc_info()
1030 traceback.print_exception(tp, val, tb)
1031
1032
1033 def MakeFramesUI(self, parent, id, debugger):
1034 panel = PythonFramesUI(parent, id, self)
1035 return panel
1036
1037
1038 class BreakpointsUI(wx.Panel):
1039 def __init__(self, parent, id, ui):
1040 wx.Panel.__init__(self, parent, id)
1041 self._ui = ui
1042 self.currentItem = None
1043 self.clearBPID = wx.NewId()
1044 self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID)
1045 self.syncLineID = wx.NewId()
1046 self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID)
1047 sizer = wx.BoxSizer(wx.VERTICAL)
1048 p1 = self
1049 self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT)
1050 sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
1051 self._bpListCtrl.InsertColumn(0, "File")
1052 self._bpListCtrl.InsertColumn(1, "Line")
1053 self._bpListCtrl.InsertColumn(2, "Path")
1054 self._bpListCtrl.SetColumnWidth(0, 150)
1055 self._bpListCtrl.SetColumnWidth(1, 50)
1056 self._bpListCtrl.SetColumnWidth(2, 450)
1057 self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
1058 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl)
1059 self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl)
1060
1061 def OnLeftDoubleClick(event):
1062 self.SyncBPLine(event)
1063
1064 wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick)
1065
1066 self.PopulateBPList()
1067
1068 p1.SetSizer(sizer)
1069 sizer.Fit(p1)
1070 p1.Layout()
1071
1072 def PopulateBPList(self):
1073 list = self._bpListCtrl
1074 list.DeleteAllItems()
1075
1076 bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict()
1077 index = 0
1078 for fileName in bps.keys():
1079 shortFile = os.path.basename(fileName)
1080 lines = bps[fileName]
1081 if lines:
1082 for line in lines:
1083 list.InsertStringItem(index, shortFile)
1084 list.SetStringItem(index, 1, str(line))
1085 list.SetStringItem(index, 2, fileName)
1086
1087 def OnListRightClick(self, event):
1088 menu = wx.Menu()
1089 item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint")
1090 menu.AppendItem(item)
1091 item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line")
1092 menu.AppendItem(item)
1093 self.PopupMenu(menu, event.GetPosition())
1094 menu.Destroy()
1095
1096 def SyncBPLine(self, event):
1097 if self.currentItem != -1:
1098 list = self._bpListCtrl
1099 fileName = list.GetItem(self.currentItem, 2).GetText()
1100 lineNumber = list.GetItem(self.currentItem, 1).GetText()
1101 self._ui.SynchCurrentLine( fileName, int(lineNumber) , noArrow=True)
1102
1103 def ClearBreakPoint(self, event):
1104 if self.currentItem >= 0:
1105 list = self._bpListCtrl
1106 fileName = list.GetItem(self.currentItem, 2).GetText()
1107 lineNumber = list.GetItem(self.currentItem, 1).GetText()
1108 wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName )
1109
1110 def ListItemSelected(self, event):
1111 self.currentItem = event.m_itemIndex
1112
1113 def ListItemDeselected(self, event):
1114 self.currentItem = -1
1115
1116 class Watch:
1117 CODE_ALL_FRAMES = 1
1118 CODE_THIS_BLOCK = 2
1119 CODE_THIS_LINE = 4
1120 CODE_RUN_ONCE = 8
1121
1122 def __init__(self, name, command, show_code=CODE_ALL_FRAMES):
1123 self._name = name
1124 self._command = command
1125 self._show_code = show_code
1126
1127 class WatchDialog(wx.Dialog):
1128 WATCH_ALL_FRAMES = "Watch in all frames"
1129 WATCH_THIS_FRAME = "Watch in this frame only"
1130 WATCH_ONCE = "Watch once and delete"
1131 def __init__(self, parent, title, chain):
1132 wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE)
1133 self._chain = chain
1134 self.label_2 = wx.StaticText(self, -1, "Watch Name:")
1135 self._watchNameTextCtrl = wx.TextCtrl(self, -1, "")
1136 self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT)
1137 self._watchValueTextCtrl = wx.TextCtrl(self, -1, "")
1138 self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)")
1139 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)
1140
1141 self._okButton = wx.Button(self, wx.ID_OK, "OK")
1142 self._okButton.SetDefault()
1143 self._okButton.SetHelpText(_("The OK button completes the dialog"))
1144 def OnOkClick(event):
1145 if self._watchNameTextCtrl.GetValue() == "":
1146 wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
1147 return
1148 if self._watchValueTextCtrl.GetValue() == "":
1149 wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
1150 return
1151 self.EndModal(wx.ID_OK)
1152 self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton)
1153
1154 self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
1155 self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
1156
1157 self.__set_properties()
1158 self.__do_layout()
1159
1160 def GetSettings(self):
1161 return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce()
1162
1163 def GetSendFrame(self):
1164 return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection())
1165
1166 def GetRunOnce(self):
1167 return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection())
1168
1169 def __set_properties(self):
1170 self.SetTitle("Add a Watch")
1171 #self.SetSize((400, 250))
1172 self.radio_box_1.SetSelection(0)
1173
1174 def __do_layout(self):
1175 sizer_1 = wx.BoxSizer(wx.VERTICAL)
1176 grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5)
1177 grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5)
1178 grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
1179 grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0)
1180 grid_sizer_2.AddGrowableCol(1)
1181 sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
1182 grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
1183 grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0)
1184 grid_sizer_4.AddGrowableCol(1)
1185 grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
1186 sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0)
1187 sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0)
1188
1189 box = wx.BoxSizer(wx.HORIZONTAL)
1190 box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
1191 box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
1192 sizer_1.Add(box, 1, wx.EXPAND, 0)
1193 self.SetSizer(sizer_1)
1194 self.Layout()
1195
1196 class BaseFramesUI(wx.SplitterWindow):
1197 def __init__(self, parent, id, ui):
1198 wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
1199 self._ui = ui
1200 self._p1 = p1 = wx.ScrolledWindow(self, -1)
1201
1202 sizer = wx.BoxSizer(wx.HORIZONTAL)
1203 framesLabel = wx.StaticText(self, -1, "Stack Frame:")
1204 sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2)
1205
1206 self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "])
1207 sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
1208 self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
1209 self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl)
1210
1211 sizer2 = wx.BoxSizer(wx.VERTICAL)
1212 p1.SetSizer(sizer2)
1213 self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
1214 self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
1215 sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
1216 sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
1217 tree = self._treeCtrl
1218 tree.AddColumn("Thing")
1219 tree.AddColumn("Value")
1220 tree.SetMainColumn(0) # the one with the tree in it...
1221 tree.SetColumnWidth(0, 175)
1222 tree.SetColumnWidth(1, 355)
1223 self._root = tree.AddRoot("Frame")
1224 tree.SetPyData(self._root, "root")
1225 tree.SetItemText(self._root, "", 1)
1226 tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback)
1227 self._p2 = p2 = wx.Window(self, -1)
1228 sizer3 = wx.BoxSizer(wx.HORIZONTAL)
1229 p2.SetSizer(sizer3)
1230 p2.Bind(wx.EVT_SIZE, self.OnSize)
1231 self._notebook = wx.Notebook(p2, -1, size=(20,20))
1232 self._notebook.Hide()
1233 sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
1234 self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId())
1235 self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
1236 self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
1237 self._notebook.AddPage(self.consoleTab, "Output")
1238 self._notebook.AddPage(self.inspectConsoleTab, "Interact")
1239 self._notebook.AddPage(self.breakPointsTab, "Break Points")
1240 self.SetMinimumPaneSize(20)
1241 self.SplitVertically(p1, p2, 550)
1242 self.currentItem = None
1243 self._notebook.Show(True)
1244
1245 def PopulateBPList(self):
1246 self.breakPointsTab.PopulateBPList()
1247
1248 def OnSize(self, event):
1249 self._notebook.SetSize(self._p2.GetSize())
1250
1251 def OnDoubleClick(self, event):
1252 # Looking for a stack trace line.
1253 lineText, pos = self._textCtrl.GetCurLine()
1254 fileBegin = lineText.find("File \"")
1255 fileEnd = lineText.find("\", line ")
1256 lineEnd = lineText.find(", in ")
1257 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
1258 # Check the line before the one that was clicked on
1259 lineNumber = self._textCtrl.GetCurrentLine()
1260 if(lineNumber == 0):
1261 return
1262 lineText = self._textCtrl.GetLine(lineNumber - 1)
1263 fileBegin = lineText.find("File \"")
1264 fileEnd = lineText.find("\", line ")
1265 lineEnd = lineText.find(", in ")
1266 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
1267 return
1268
1269 filename = lineText[fileBegin + 6:fileEnd]
1270 lineNum = int(lineText[fileEnd + 8:lineEnd])
1271
1272 foundView = None
1273 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
1274 for openDoc in openDocs:
1275 if openDoc.GetFilename() == filename:
1276 foundView = openDoc.GetFirstView()
1277 break
1278
1279 if not foundView:
1280 doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
1281 foundView = doc.GetFirstView()
1282
1283 if foundView:
1284 foundView.GetFrame().SetFocus()
1285 foundView.Activate()
1286 foundView.GotoLine(lineNum)
1287 startPos = foundView.PositionFromLine(lineNum)
1288 lineText = foundView.GetCtrl().GetLine(lineNum - 1)
1289 foundView.SetSelection(startPos, startPos + len(lineText.rstrip("\n")))
1290 import OutlineService
1291 wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
1292
1293 def MakeConsoleTab(self, parent, id):
1294 panel = wx.Panel(parent, id)
1295 sizer = wx.BoxSizer(wx.HORIZONTAL)
1296 self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
1297 sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
1298 self._textCtrl.SetViewLineNumbers(False)
1299 self._textCtrl.SetReadOnly(True)
1300 if wx.Platform == '__WXMSW__':
1301 font = "Courier New"
1302 else:
1303 font = "Courier"
1304 self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
1305 self._textCtrl.SetFontColor(wx.BLACK)
1306 self._textCtrl.StyleClearAll()
1307 wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
1308
1309 panel.SetSizer(sizer)
1310 #sizer.Fit(panel)
1311
1312 return panel
1313 def ExecuteCommand(self, command):
1314 assert False, "ExecuteCommand not overridden"
1315
1316 def MakeInspectConsoleTab(self, parent, id):
1317 def handleCommand():
1318 cmdStr = self._cmdInput.GetValue()
1319 if cmdStr:
1320 self._cmdList.append(cmdStr)
1321 self._cmdIndex = len(self._cmdList)
1322 self._cmdInput.Clear()
1323 self._cmdOutput.SetDefaultStyle(style=self._cmdOutputTextStyle)
1324 self._cmdOutput.AppendText(">>> " + cmdStr + "\n")
1325 self._cmdOutput.SetDefaultStyle(style=self._defaultOutputTextStyle)
1326 self.ExecuteCommand(cmdStr)
1327 return
1328
1329 def OnCmdButtonPressed(event):
1330 handleCommand()
1331 return
1332
1333 def OnKeyPressed(event):
1334 key = event.KeyCode()
1335 if key == wx.WXK_RETURN:
1336 handleCommand()
1337 elif key == wx.WXK_UP:
1338 if len(self._cmdList) < 1 or self._cmdIndex < 1:
1339 return
1340
1341 self._cmdInput.Clear()
1342 self._cmdInput.AppendText(self._cmdList[self._cmdIndex - 1])
1343 self._cmdIndex = self._cmdIndex - 1
1344 elif key == wx.WXK_DOWN:
1345 if len(self._cmdList) < 1 or self._cmdIndex >= len(self._cmdList):
1346 return
1347
1348 self._cmdInput.Clear()
1349 self._cmdInput.AppendText(self._cmdList[self._cmdIndex - 1])
1350 self._cmdIndex = self._cmdIndex + 1
1351 else:
1352 event.Skip()
1353 return
1354
1355 def OnClrButtonPressed(event):
1356 self._cmdOutput.Clear()
1357
1358 panel = wx.Panel(parent, id)
1359
1360 cmdLabel = wx.StaticText(panel, -1, "Cmd: ")
1361 self._cmdInput = wx.TextCtrl(panel)
1362 cmdButton = wx.Button(panel, label="Execute")
1363 clrButton = wx.Button(panel, label="Clear")
1364 self._cmdOutput = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.HSCROLL | wx.TE_READONLY | wx.TE_RICH2)
1365
1366 hbox = wx.BoxSizer()
1367 hbox.Add(cmdLabel, proportion=0, flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
1368 hbox.Add(self._cmdInput, proportion=1, flag=wx.EXPAND)
1369 hbox.Add(cmdButton, proportion=0, flag=wx.RIGHT)
1370 hbox.Add(clrButton, proportion=0, flag=wx.RIGHT)
1371
1372 vbox = wx.BoxSizer(wx.VERTICAL)
1373 vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=2)
1374 vbox.Add(self._cmdOutput, proportion=1, flag=wx.EXPAND | wx.LEFT, border=2)
1375
1376 panel.SetSizer(vbox)
1377 cmdButton.Bind(wx.EVT_BUTTON, OnCmdButtonPressed)
1378 clrButton.Bind(wx.EVT_BUTTON, OnClrButtonPressed)
1379 wx.EVT_KEY_DOWN(self._cmdInput, OnKeyPressed)
1380
1381 fixedFont = wx.Font(self._cmdInput.GetFont().GetPointSize(), family=wx.TELETYPE, style=wx.NORMAL, weight=wx.NORMAL)
1382 self._defaultOutputTextStyle = wx.TextAttr("BLACK", wx.NullColour, fixedFont)
1383 self._cmdOutputTextStyle = wx.TextAttr("RED", wx.NullColour, fixedFont)
1384 self._cmdOutput.SetDefaultStyle(style=self._defaultOutputTextStyle)
1385 self._cmdList = []
1386 self._cmdIndex = 0
1387
1388 panel.Show()
1389 return panel
1390
1391 def MakeBreakPointsTab(self, parent, id):
1392 panel = BreakpointsUI(parent, id, self._ui)
1393 return panel
1394
1395 def OnRightClick(self, event):
1396 assert False, "OnRightClick not overridden"
1397
1398 def ClearWhileRunning(self):
1399 list = self._framesChoiceCtrl
1400 list.Clear()
1401 list.Enable(False)
1402 tree = self._treeCtrl
1403 root = self._root
1404 tree.DeleteChildren(root)
1405 self._cmdInput.Enable(False)
1406 self._cmdOutput.Enable(False)
1407
1408 def OnListRightClick(self, event):
1409 if not hasattr(self, "syncFrameID"):
1410 self.syncFrameID = wx.NewId()
1411 self.Bind(wx.EVT_MENU, self.OnSyncFrame, id=self.syncFrameID)
1412 menu = wx.Menu()
1413 item = wx.MenuItem(menu, self.syncFrameID, "Goto Source Line")
1414 menu.AppendItem(item)
1415 self.PopupMenu(menu, event.GetPosition())
1416 menu.Destroy()
1417
1418 def OnSyncFrame(self, event):
1419 assert False, "OnSyncFrame not overridden"
1420
1421 def LoadFramesList(self, framesXML):
1422 assert False, "LoadFramesList not overridden"
1423
1424 def ListItemSelected(self, event):
1425 assert False, "ListItemSelected not overridden"
1426
1427 def PopulateTreeFromFrameMessage(self, message):
1428 assert False, "PopulateTreeFromFrameMessage not overridden"
1429
1430 def IntrospectCallback(self, event):
1431 assert False, "IntrospectCallback not overridden"
1432
1433 def AppendText(self, text):
1434 self._textCtrl.SetReadOnly(False)
1435 self._textCtrl.AddText(text)
1436 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
1437 self._textCtrl.SetReadOnly(True)
1438
1439 def AppendErrorText(self, text):
1440 self._textCtrl.SetReadOnly(False)
1441 self._textCtrl.SetFontColor(wx.RED)
1442 self._textCtrl.StyleClearAll()
1443 self._textCtrl.AddText(text)
1444 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
1445 self._textCtrl.SetFontColor(wx.BLACK)
1446 self._textCtrl.StyleClearAll()
1447 self._textCtrl.SetReadOnly(True)
1448
1449 def ClearOutput(self, event):
1450 self._textCtrl.SetReadOnly(False)
1451 self._textCtrl.ClearAll()
1452 self._textCtrl.SetReadOnly(True)
1453
1454 def SwitchToOutputTab(self):
1455 self._notebook.SetSelection(0)
1456
1457 class PHPFramesUI(BaseFramesUI):
1458 def __init__(self, parent, id, ui):
1459 BaseFramesUI.__init__(self, parent, id, ui)
1460
1461 def LoadFramesList(self, stackList):
1462 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1463
1464 self._cmdInput.Enable(True)
1465 self._cmdOutput.Enable(True)
1466 index = 0
1467 self._stack = stackList
1468 list = self._framesChoiceCtrl
1469 list.Clear()
1470
1471 if len(stackList) > 0:
1472 self._displayVariableTreeRootNode()
1473
1474 for stackFrame in stackList:
1475 message = stackFrame.getDisplayStr(stackList)
1476 list.Append(message)
1477
1478 self.currentItem = index
1479 list.SetSelection(index)
1480 list.Enable(True)
1481 self.OnSyncFrame(None)
1482 self._p1.FitInside()
1483
1484 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
1485
1486 def PopulateTreeFromStackFrame(self, frameNode):
1487 vars = frameNode.getVariables()
1488 tree = self._treeCtrl
1489 rootTreeNode = self._root
1490
1491 #
1492 # Build a new sub variable tree from the root node.
1493 #
1494 tree.DeleteChildren(rootTreeNode)
1495 for var in vars:
1496 aTreeNode = self.AppendSubTreeFromAVariable(tree, var, rootTreeNode)
1497
1498 #
1499 # No need to expand the node here, as the IntrospectCallback() has
1500 # already called it.
1501 #
1502 self._p2.FitInside()
1503
1504 def AppendSubTreeFromAVariable(self, tree, var, parentTreeNode, previousOne = None):
1505 varName = var.getName()
1506 varValueStr = var.getValueString()
1507
1508 #
1509 # If previously we already have this item in the tree, replace it.
1510 # Otherwise, insert a new one.
1511 #
1512 if previousOne:
1513 newNode = tree.InsertItem(parentTreeNode, previousOne, varName)
1514 else:
1515 newNode = tree.AppendItem(parentTreeNode, varName)
1516
1517 #
1518 # Associate this variable object with this newNode.
1519 #
1520 tree.SetPyData(newNode, var)
1521
1522 #
1523 # Set this variable's value string (for displaying).
1524 #
1525 if varValueStr and len(varValueStr) > 0:
1526 tree.SetItemText(newNode, varValueStr, 1)
1527
1528 #
1529 # If this variable has child variables, recursively build the sub
1530 # variable tree.
1531 #
1532 if var.hasChildren():
1533 childrenVarList = var.getChildrenVariables()
1534 for childVar in childrenVarList:
1535 self.AppendSubTreeFromAVariable(tree, childVar, newNode)
1536
1537 #
1538 # If its child variables are sortable, sort it.
1539 #
1540 if var.childrenIsSortable():
1541 tree.SortChildren(newNode)
1542
1543 return newNode
1544
1545 def IntrospectCallback(self, event):
1546 tree = self._treeCtrl
1547 item = event.GetItem()
1548
1549 #
1550 # Only when the introspection happens to root, we get the whole
1551 # variable tree. For all the individual nodes, we have populated
1552 # the subtree already, so don't need to do anything.
1553 #
1554 if tree.GetPyData(item) == "root" and self._stack and self._stack[self.currentItem]:
1555 stackFrame = self._stack[self.currentItem]
1556 self.PopulateTreeFromStackFrame(stackFrame)
1557
1558 event.Skip()
1559
1560 def OnSyncFrame(self, event):
1561 stackFrame = self._stack[self.currentItem]
1562 fileName = stackFrame.getFileName()
1563 lineNo = stackFrame.getLineNo()
1564 if _VERBOSE:
1565 print "OnSyncFrame(): about to sync: fileName: %s, lineNo: %d" % (fileName, lineNo)
1566 self._ui.SynchCurrentLine(fileName, lineNo)
1567 if _VERBOSE:
1568 print "OnSyncFrame(): sync done"
1569
1570 def ListItemSelected(self, event):
1571 selectedStackFrameStr = event.GetString()
1572
1573 if not self._stack or len(self._stack) < 1:
1574 return
1575
1576 found = False
1577 for stackFrame in self._stack:
1578 if stackFrame.getDisplayStr() == selectedStackFrameStr:
1579 self.currentItem = stackFrame.getFrameIndex()
1580 found = True
1581 break
1582
1583 if found:
1584 self._displayVariableTreeRootNode()
1585 self.OnSyncFrame(None)
1586
1587 return
1588
1589 def _displayVariableTreeRootNode(self):
1590 #
1591 # Add a dummy item to rootTreeNode so that it will be shown as
1592 # expandable. Only do real tree population on the fly when the
1593 # rootTreeNode is expanded in OnIntrospection().
1594 #
1595 tree = self._treeCtrl
1596 rootTreeNode = self._root
1597 dummyNode = tree.AppendItem(rootTreeNode, "dummy")
1598 tree.Collapse(rootTreeNode)
1599
1600 return
1601
1602
1603 class PythonFramesUI(BaseFramesUI):
1604 def __init__(self, parent, id, ui):
1605 BaseFramesUI.__init__(self, parent, id, ui)
1606
1607 def ExecuteCommand(self, command):
1608 retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command)
1609 self._cmdOutput.AppendText(str(retval) + "\n")
1610 # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
1611 self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection())
1612
1613 def OnRightClick(self, event):
1614 #Refactor this...
1615 self._introspectItem = event.GetItem()
1616 self._parentChain = self.GetItemChain(event.GetItem())
1617 watchOnly = len(self._parentChain) < 1
1618 if not _WATCHES_ON and watchOnly:
1619 return
1620 menu = wx.Menu()
1621 if _WATCHES_ON:
1622 if not hasattr(self, "watchID"):
1623 self.watchID = wx.NewId()
1624 self.Bind(wx.EVT_MENU, self.OnWatch, id=self.watchID)
1625 item = wx.MenuItem(menu, self.watchID, "Create a Watch")
1626 menu.AppendItem(item)
1627 menu.AppendSeparator()
1628 if not watchOnly:
1629 if not hasattr(self, "viewID"):
1630 self.viewID = wx.NewId()
1631 self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID)
1632 item = wx.MenuItem(menu, self.viewID, "View in Dialog")
1633 menu.AppendItem(item)
1634 if not hasattr(self, "toInteractID"):
1635 self.toInteractID = wx.NewId()
1636 self.Bind(wx.EVT_MENU, self.OnSendToInteract, id=self.toInteractID)
1637 item = wx.MenuItem(menu, self.toInteractID, "Send to Interact")
1638 menu.AppendItem(item)
1639
1640 offset = wx.Point(x=0, y=20)
1641 menuSpot = event.GetPoint() + offset
1642 self._treeCtrl.PopupMenu(menu, menuSpot)
1643 menu.Destroy()
1644 self._parentChain = None
1645 self._introspectItem = None
1646
1647 def GetItemChain(self, item):
1648 parentChain = []
1649 if item:
1650 if _VERBOSE: print 'Exploding: %s' % self._treeCtrl.GetItemText(item, 0)
1651 while item != self._root:
1652 text = self._treeCtrl.GetItemText(item, 0)
1653 if _VERBOSE: print "Appending ", text
1654 parentChain.append(text)
1655 item = self._treeCtrl.GetItemParent(item)
1656 parentChain.reverse()
1657 return parentChain
1658
1659 def OnView(self, event):
1660 title = self._treeCtrl.GetItemText(self._introspectItem,0)
1661 value = self._treeCtrl.GetItemText(self._introspectItem,1)
1662 dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER)
1663 dlg.Show()
1664
1665 def OnSendToInteract(self, event):
1666 value = ""
1667 prevItem = ""
1668 for item in self._parentChain:
1669
1670 if item.find(prevItem + '[') != -1:
1671 value += item[item.find('['):]
1672 continue
1673 if value != "":
1674 value = value + '.'
1675 if item == 'globals':
1676 item = 'globals()'
1677 if item != 'locals':
1678 value += item
1679 prevItem = item
1680 print value
1681 self.ExecuteCommand(value)
1682
1683 def OnWatch(self, event):
1684 try:
1685 if hasattr(self, '_parentChain'):
1686 wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain)
1687 else:
1688 wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None)
1689 wd.CenterOnParent()
1690 if wd.ShowModal() == wx.ID_OK:
1691 name, text, send_frame, run_once = wd.GetSettings()
1692 if send_frame:
1693 frameNode = self._stack[int(self.currentItem)]
1694 message = frameNode.getAttribute("message")
1695 else:
1696 message = ""
1697 binType = self._ui._callback._debuggerServer.add_watch(name, text, message, run_once)
1698 xmldoc = bz2.decompress(binType.data)
1699 domDoc = parseString(xmldoc)
1700 nodeList = domDoc.getElementsByTagName('watch')
1701 if len(nodeList) == 1:
1702 watchValue = nodeList.item(0).getAttribute("message")
1703 wd.Destroy()
1704 except:
1705 tp, val, tb = sys.exc_info()
1706 traceback.print_exception(tp, val, tb)
1707
1708 def OnIntrospect(self, event):
1709 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1710
1711 try:
1712
1713 try:
1714 list = self._framesChoiceCtrl
1715 frameNode = self._stack[int(self.currentItem)]
1716 message = frameNode.getAttribute("message")
1717 binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain)
1718 xmldoc = bz2.decompress(binType.data)
1719 domDoc = parseString(xmldoc)
1720 nodeList = domDoc.getElementsByTagName('replacement')
1721 replacementNode = nodeList.item(0)
1722 if len(replacementNode.childNodes):
1723 thingToWalk = replacementNode.childNodes.item(0)
1724 tree = self._treeCtrl
1725 parent = tree.GetItemParent(self._introspectItem)
1726 treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem)
1727 if thingToWalk.getAttribute('name').find('[') == -1:
1728 self._treeCtrl.SortChildren(treeNode)
1729 self._treeCtrl.Expand(treeNode)
1730 tree.Delete(self._introspectItem)
1731 except:
1732 tp,val,tb = sys.exc_info()
1733 traceback.print_exception(tp, val, tb)
1734
1735 finally:
1736 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
1737
1738 def OnSyncFrame(self, event):
1739 list = self._framesChoiceCtrl
1740 frameNode = self._stack[int(self.currentItem)]
1741 file = frameNode.getAttribute("file")
1742 line = frameNode.getAttribute("line")
1743 self._ui.SynchCurrentLine( file, int(line) )
1744
1745 def LoadFramesList(self, framesXML):
1746 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1747 try:
1748 self._cmdInput.Enable(True)
1749 self._cmdOutput.Enable(True)
1750
1751 try:
1752 domDoc = parseString(framesXML)
1753 list = self._framesChoiceCtrl
1754 list.Clear()
1755 self._stack = []
1756 nodeList = domDoc.getElementsByTagName('frame')
1757 frame_count = -1
1758 for index in range(0, nodeList.length):
1759 frameNode = nodeList.item(index)
1760 message = frameNode.getAttribute("message")
1761 list.Append(message)
1762 self._stack.append(frameNode)
1763 frame_count += 1
1764 index = len(self._stack) - 1
1765 list.SetSelection(index)
1766
1767 node = self._stack[index]
1768 self.currentItem = index
1769 self.PopulateTreeFromFrameNode(node)
1770 self.OnSyncFrame(None)
1771
1772 self._p1.FitInside()
1773 frameNode = nodeList.item(index)
1774 file = frameNode.getAttribute("file")
1775 line = frameNode.getAttribute("line")
1776 self._ui.SynchCurrentLine( file, int(line) )
1777 except:
1778 tp,val,tb=sys.exc_info()
1779 traceback.print_exception(tp, val, tb)
1780
1781 finally:
1782 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
1783
1784
1785 def ListItemSelected(self, event):
1786 self.PopulateTreeFromFrameMessage(event.GetString())
1787 self.OnSyncFrame(None)
1788
1789 def PopulateTreeFromFrameMessage(self, message):
1790 index = 0
1791 for node in self._stack:
1792 if node.getAttribute("message") == message:
1793 binType = self._ui._callback._debuggerServer.request_frame_document(message)
1794 xmldoc = bz2.decompress(binType.data)
1795 domDoc = parseString(xmldoc)
1796 nodeList = domDoc.getElementsByTagName('frame')
1797 self.currentItem = index
1798 if len(nodeList):
1799 self.PopulateTreeFromFrameNode(nodeList[0])
1800 return
1801 index = index + 1
1802
1803 def PopulateTreeFromFrameNode(self, frameNode):
1804 list = self._framesChoiceCtrl
1805 list.Enable(True)
1806 tree = self._treeCtrl
1807 #tree.Show(True)
1808 root = self._root
1809 tree.DeleteChildren(root)
1810 children = frameNode.childNodes
1811 firstChild = None
1812 for index in range(0, children.length):
1813 subNode = children.item(index)
1814 treeNode = self.AppendSubTreeFromNode(subNode, subNode.getAttribute('name'), root)
1815 if not firstChild:
1816 firstChild = treeNode
1817 tree.Expand(root)
1818 if firstChild:
1819 tree.Expand(firstChild)
1820 self._p2.FitInside()
1821
1822 def IntrospectCallback(self, event):
1823 tree = self._treeCtrl
1824 item = event.GetItem()
1825 if _VERBOSE:
1826 print "In introspectCallback item is %s, pydata is %s" % (event.GetItem(), tree.GetPyData(item))
1827 if tree.GetPyData(item) != "Introspect":
1828 event.Skip()
1829 return
1830 self._introspectItem = item
1831 self._parentChain = self.GetItemChain(item)
1832 self.OnIntrospect(event)
1833 event.Skip()
1834
1835 def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None):
1836 tree = self._treeCtrl
1837 if insertBefore != None:
1838 treeNode = tree.InsertItem(parent, insertBefore, name)
1839 else:
1840 treeNode = tree.AppendItem(parent, name)
1841 children = node.childNodes
1842 intro = node.getAttribute('intro')
1843
1844 if intro == "True":
1845 tree.SetItemHasChildren(treeNode, True)
1846 tree.SetPyData(treeNode, "Introspect")
1847 if node.getAttribute("value"):
1848 tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1)
1849 for index in range(0, children.length):
1850 subNode = children.item(index)
1851 if self.HasChildren(subNode):
1852 self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode)
1853 else:
1854 name = subNode.getAttribute("name")
1855 value = self.StripOuterSingleQuotes(subNode.getAttribute("value"))
1856 n = tree.AppendItem(treeNode, name)
1857 tree.SetItemText(n, value, 1)
1858 intro = subNode.getAttribute('intro')
1859 if intro == "True":
1860 tree.SetItemHasChildren(n, True)
1861 tree.SetPyData(n, "Introspect")
1862 if name.find('[') == -1:
1863 self._treeCtrl.SortChildren(treeNode)
1864 return treeNode
1865
1866 def StripOuterSingleQuotes(self, string):
1867 if string.startswith("'") and string.endswith("'"):
1868 retval = string[1:-1]
1869 elif string.startswith("\"") and string.endswith("\""):
1870 retval = string[1:-1]
1871 else:
1872 retval = string
1873 if retval.startswith("u'") and retval.endswith("'"):
1874 retval = retval[1:]
1875 return retval
1876
1877 def HasChildren(self, node):
1878 try:
1879 return node.childNodes.length > 0
1880 except:
1881 tp,val,tb=sys.exc_info()
1882 return False
1883
1884
1885 class DebuggerView(Service.ServiceView):
1886
1887 #----------------------------------------------------------------------------
1888 # Overridden methods
1889 #----------------------------------------------------------------------------
1890
1891 def __init__(self, service):
1892 Service.ServiceView.__init__(self, service)
1893
1894 def _CreateControl(self, parent, id):
1895 return None
1896
1897 #------------------------------------------------------------------------------
1898 # Event handling
1899 #-----------------------------------------------------------------------------
1900
1901 def OnToolClicked(self, event):
1902 self.GetFrame().ProcessEvent(event)
1903
1904 #------------------------------------------------------------------------------
1905 # Class methods
1906 #-----------------------------------------------------------------------------
1907
1908 class Interaction:
1909 def __init__(self, message, framesXML, info=None, quit=False):
1910 self._framesXML = framesXML
1911 self._message = message
1912 self._info = info
1913 self._quit = quit
1914
1915 def getFramesXML(self):
1916 return self._framesXML
1917
1918 def getMessage(self):
1919 return self._message
1920
1921 def getInfo(self):
1922 return self._info
1923
1924 def getQuit(self):
1925 return self._quit
1926
1927 class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
1928 def __init__(self, address, logRequests=0):
1929 SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests)
1930
1931 class RequestHandlerThread(threading.Thread):
1932 def __init__(self, queue, address):
1933 threading.Thread.__init__(self)
1934 self._keepGoing = True
1935 self._queue = queue
1936 self._address = address
1937 self._server = AGXMLRPCServer(self._address,logRequests=0)
1938 self._server.register_function(self.interaction)
1939 self._server.register_function(self.quit)
1940 self._server.register_function(self.dummyOperation)
1941 if _VERBOSE: print "RequestHandlerThread on fileno %s" % str(self._server.fileno())
1942
1943 def run(self):
1944 while self._keepGoing:
1945 try:
1946 self._server.handle_request()
1947 except:
1948 tp, val, tb = sys.exc_info()
1949 traceback.print_exception(tp, val, tb)
1950 self._keepGoing = False
1951 if _VERBOSE: print "Exiting Request Handler Thread."
1952
1953 def interaction(self, message, frameXML, info):
1954 if _VERBOSE: print "In RequestHandlerThread.interaction -- adding to queue"
1955 interaction = Interaction(message, frameXML, info)
1956 self._queue.put(interaction)
1957 return ""
1958
1959 def quit(self):
1960 interaction = Interaction(None, None, info=None, quit=True)
1961 self._queue.put(interaction)
1962 return ""
1963
1964 def dummyOperation(self):
1965 return ""
1966
1967 def AskToStop(self):
1968 self._keepGoing = False
1969 if type(self._server) is not types.NoneType:
1970 try:
1971 # This is a really ugly way to make sure this thread isn't blocked in
1972 # handle_request.
1973 url = 'http://' + self._address[0] + ':' + str(self._address[1]) + '/'
1974 tempServer = xmlrpclib.ServerProxy(url, allow_none=1)
1975 tempServer.dummyOperation()
1976 except:
1977 tp, val, tb = sys.exc_info()
1978 traceback.print_exception(tp, val, tb)
1979 self._server.server_close()
1980
1981
1982 class RequestBreakThread(threading.Thread):
1983 def __init__(self, server, interrupt=False, pushBreakpoints=False, breakDict=None, kill=False):
1984 threading.Thread.__init__(self)
1985 self._server = server
1986
1987 self._interrupt = interrupt
1988 self._pushBreakpoints = pushBreakpoints
1989 self._breakDict = breakDict
1990 self._kill = kill
1991
1992 def run(self):
1993 try:
1994 if _VERBOSE: print "RequestBreakThread, before call"
1995 if self._interrupt:
1996 self._server.break_requested()
1997 if self._pushBreakpoints:
1998 self._server.update_breakpoints(xmlrpclib.Binary(pickle.dumps(self._breakDict)))
1999 if self._kill:
2000 try:
2001 self._server.die()
2002 except:
2003 pass
2004 if _VERBOSE: print "RequestBreakThread, after call"
2005 except:
2006 tp,val,tb = sys.exc_info()
2007 traceback.print_exception(tp, val, tb)
2008
2009 class DebuggerOperationThread(threading.Thread):
2010 def __init__(self, function):
2011 threading.Thread.__init__(self)
2012 self._function = function
2013
2014 def run(self):
2015 if _VERBOSE: print "In DOT, before call"
2016 try:
2017 self._function()
2018 except:
2019 tp,val,tb = sys.exc_info()
2020 traceback.print_exception(tp, val, tb)
2021 if _VERBOSE:
2022 print "In DOT, after call"
2023
2024 class BaseDebuggerCallback(object):
2025
2026 def Start(self):
2027 assert False, "Start not overridden"
2028
2029 def ShutdownServer(self):
2030 assert False, "ShutdownServer not overridden"
2031
2032 def BreakExecution(self):
2033 assert False, "BreakExecution not overridden"
2034
2035 def SingleStep(self):
2036 assert False, "SingleStep not overridden"
2037
2038 def Next(self):
2039 assert False, "Next not overridden"
2040
2041 def Continue(self):
2042 assert False, "Start not overridden"
2043
2044 def Return(self):
2045 assert False, "Return not overridden"
2046
2047 def PushBreakpoints(self):
2048 assert False, "PushBreakpoints not overridden"
2049
2050 class PythonDebuggerCallback(BaseDebuggerCallback):
2051
2052 def __init__(self, host, port, debugger_url, break_url, debuggerUI, autoContinue=False):
2053 if _VERBOSE: print "+++++++ Creating server on port, ", str(port)
2054 self._timer = None
2055 self._queue = Queue.Queue(50)
2056 self._host = host
2057 self._port = int(port)
2058 threading._VERBOSE = _VERBOSE
2059 self._serverHandlerThread = RequestHandlerThread(self._queue, (self._host, self._port))
2060
2061 self._debugger_url = debugger_url
2062 self._debuggerServer = None
2063 self._waiting = False
2064 self._service = wx.GetApp().GetService(DebuggerService)
2065 self._debuggerUI = debuggerUI
2066 self._break_url = break_url
2067 self._breakServer = None
2068 self._firstInteraction = True
2069 self._pendingBreak = False
2070 self._autoContinue = autoContinue
2071
2072 def Start(self):
2073 self._serverHandlerThread.start()
2074
2075 def ShutdownServer(self):
2076 #rbt = RequestBreakThread(self._breakServer, kill=True)
2077 #rbt.start()
2078 self._waiting = False
2079 if self._serverHandlerThread:
2080 self._serverHandlerThread.AskToStop()
2081 self._serverHandlerThread = None
2082
2083 def BreakExecution(self):
2084 rbt = RequestBreakThread(self._breakServer, interrupt=True)
2085 rbt.start()
2086
2087 def SingleStep(self):
2088 self._debuggerUI.DisableWhileDebuggerRunning()
2089 self._debuggerServer.set_step() # Figure out where to set allowNone
2090 self.WaitForRPC()
2091
2092 def Next(self):
2093 self._debuggerUI.DisableWhileDebuggerRunning()
2094 self._debuggerServer.set_next()
2095 self.WaitForRPC()
2096
2097 def Continue(self):
2098 self._debuggerUI.DisableWhileDebuggerRunning()
2099 self._debuggerServer.set_continue()
2100 self.WaitForRPC()
2101
2102 def Return(self):
2103 self._debuggerUI.DisableWhileDebuggerRunning()
2104 self._debuggerServer.set_return()
2105 self.WaitForRPC()
2106
2107 def ReadQueue(self):
2108 if self._queue.qsize():
2109 try:
2110 item = self._queue.get_nowait()
2111 if item.getQuit():
2112 self.interaction(None, None, None, True)
2113 else:
2114 data = bz2.decompress(item.getFramesXML().data)
2115 self.interaction(item.getMessage().data, data, item.getInfo(), False)
2116 except Queue.Empty:
2117 pass
2118
2119 def PushBreakpoints(self):
2120 rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict())
2121 rbt.start()
2122
2123
2124 def WaitForRPC(self):
2125 self._waiting = True
2126 while self._waiting:
2127 try:
2128 self.ReadQueue()
2129 import time
2130 time.sleep(0.02)
2131 except:
2132 tp, val, tb = sys.exc_info()
2133 traceback.print_exception(tp, val, tb)
2134 wx.GetApp().Yield(True)
2135 if _VERBOSE: print "Exiting WaitForRPC."
2136
2137 def interaction(self, message, frameXML, info, quit):
2138
2139 #This method should be hit as the debugger starts.
2140 if self._firstInteraction:
2141 self._firstInteraction = False
2142 self._debuggerServer = xmlrpclib.ServerProxy(self._debugger_url, allow_none=1)
2143 self._breakServer = xmlrpclib.ServerProxy(self._break_url, allow_none=1)
2144 self.PushBreakpoints()
2145 self._waiting = False
2146 if _VERBOSE: print "+"*40
2147 if(quit):
2148 self._debuggerUI.StopExecution(None)
2149 return ""
2150 if(info != ""):
2151 if _VERBOSE: print "Hit interaction with exception"
2152 #self._debuggerUI.StopExecution(None)
2153 #self._debuggerUI.SetStatusText("Got exception: " + str(info))
2154 self._debuggerUI.SwitchToOutputTab()
2155 else:
2156 if _VERBOSE: print "Hit interaction no exception"
2157 #if not self._autoContinue:
2158 self._debuggerUI.SetStatusText(message)
2159 if not self._autoContinue:
2160 self._debuggerUI.LoadPythonFramesList(frameXML)
2161 self._debuggerUI.EnableWhileDebuggerStopped()
2162
2163 if self._autoContinue:
2164 self._timer = wx.PyTimer(self.DoContinue)
2165 self._autoContinue = False
2166 self._timer.Start(250)
2167 if _VERBOSE: print "+"*40
2168
2169 def DoContinue(self):
2170 self._timer.Stop()
2171 dbgService = wx.GetApp().GetService(DebuggerService)
2172 evt = DebugInternalWebServer()
2173 evt.SetId(self._debuggerUI.CONTINUE_ID)
2174 wx.PostEvent(self._debuggerUI, evt)
2175 if _VERBOSE: print "Event Continue posted"
2176
2177 evt = DebugInternalWebServer()
2178 evt.SetId(DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID)
2179 wx.PostEvent(dbgService._frame, evt)
2180 if _VERBOSE: print "Event RunProject posted"
2181
2182 def SendRunEvent(self):
2183 class SendEventThread(threading.Thread):
2184 def __init__(self):
2185 threading.Thread.__init__(self)
2186
2187 def run(self):
2188 dbgService = wx.GetApp().GetService(DebuggerService)
2189 evt = DebugInternalWebServer()
2190 evt.SetId(DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID)
2191 wx.PostEvent(dbgService._frame, evt)
2192 print "Event posted"
2193 set = SendEventThread()
2194 set.start()
2195
2196 class DebuggerService(Service.Service):
2197
2198 #----------------------------------------------------------------------------
2199 # Constants
2200 #----------------------------------------------------------------------------
2201 TOGGLE_BREAKPOINT_ID = wx.NewId()
2202 CLEAR_ALL_BREAKPOINTS = wx.NewId()
2203 RUN_ID = wx.NewId()
2204 DEBUG_ID = wx.NewId()
2205 RUN_LAST_ID = wx.NewId()
2206 DEBUG_LAST_ID = wx.NewId()
2207 DEBUG_WEBSERVER_ID = wx.NewId()
2208 RUN_WEBSERVER_ID = wx.NewId()
2209 DEBUG_WEBSERVER_CONTINUE_ID = wx.NewId()
2210 DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID = wx.NewId()
2211 def ComparePaths(first, second):
2212 one = DebuggerService.ExpandPath(first)
2213 two = DebuggerService.ExpandPath(second)
2214 if _WINDOWS:
2215 return one.lower() == two.lower()
2216 else:
2217 return one == two
2218 ComparePaths = staticmethod(ComparePaths)
2219
2220 # Make sure we're using an expanded path on windows.
2221 def ExpandPath(path):
2222 if _WINDOWS:
2223 try:
2224 return win32api.GetLongPathName(path)
2225 except:
2226 if _VERBOSE:
2227 print "Cannot get long path for %s" % path
2228
2229 return path
2230
2231 ExpandPath = staticmethod(ExpandPath)
2232
2233 #----------------------------------------------------------------------------
2234 # Overridden methods
2235 #----------------------------------------------------------------------------
2236
2237 def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT):
2238 Service.Service.__init__(self, serviceName, embeddedWindowLocation)
2239 self.BREAKPOINT_DICT_STRING = "MasterBreakpointDict"
2240 config = wx.ConfigBase_Get()
2241 pickledbps = config.Read(self.BREAKPOINT_DICT_STRING)
2242 if pickledbps:
2243 try:
2244 self._masterBPDict = pickle.loads(pickledbps.encode('ascii'))
2245 except:
2246 tp, val, tb = sys.exc_info()
2247 traceback.print_exception(tp,val,tb)
2248 self._masterBPDict = {}
2249 else:
2250 self._masterBPDict = {}
2251 self._frame = None
2252 self.projectPath = None
2253 self.fileToDebug = None
2254 self.phpDbgParam = None
2255 self.dbgLanguage = projectmodel.LANGUAGE_DEFAULT
2256
2257 def OnCloseFrame(self, event):
2258 # IS THIS THE RIGHT PLACE?
2259 try:
2260 config = wx.ConfigBase_Get()
2261 config.Write(self.BREAKPOINT_DICT_STRING, pickle.dumps(self._masterBPDict))
2262 except:
2263 tp,val,tb = sys.exc_info()
2264 traceback.print_exception(tp, val, tb)
2265 return True
2266
2267 def _CreateView(self):
2268 return DebuggerView(self)
2269
2270
2271 #----------------------------------------------------------------------------
2272 # Service specific methods
2273 #----------------------------------------------------------------------------
2274
2275 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
2276 #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
2277 self._frame = frame
2278 config = wx.ConfigBase_Get()
2279
2280 debuggerMenu = wx.Menu()
2281 if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS):
2282
2283 debuggerMenu.Append(DebuggerService.RUN_ID, _("&Run...\tCtrl+R"), _("Runs a file"))
2284 wx.EVT_MENU(frame, DebuggerService.RUN_ID, frame.ProcessEvent)
2285 wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_ID, frame.ProcessUpdateUIEvent)
2286
2287 debuggerMenu.Append(DebuggerService.DEBUG_ID, _("&Debug...\tCtrl+D"), _("Debugs a file"))
2288 wx.EVT_MENU(frame, DebuggerService.DEBUG_ID, frame.ProcessEvent)
2289 wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_ID, frame.ProcessUpdateUIEvent)
2290
2291 debuggerMenu.Append(DebuggerService.RUN_LAST_ID, _("&Run Using Last Settings\tF5"), _("Runs a file using previous settings"))
2292 wx.EVT_MENU(frame, DebuggerService.RUN_LAST_ID, frame.ProcessEvent)
2293 wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_LAST_ID, frame.ProcessUpdateUIEvent)
2294
2295 debuggerMenu.Append(DebuggerService.DEBUG_LAST_ID, _("&Debug Using Last Settings\tF8"), _("Debugs a file using previous settings"))
2296 wx.EVT_MENU(frame, DebuggerService.DEBUG_LAST_ID, frame.ProcessEvent)
2297 wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_LAST_ID, frame.ProcessUpdateUIEvent)
2298
2299 if not ACTIVEGRID_BASE_IDE:
2300 debuggerMenu.AppendSeparator()
2301 debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier"))
2302 wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent)
2303 wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
2304 debuggerMenu.Append(DebuggerService.RUN_WEBSERVER_ID, _("Restart Internal Web Server"), _("Restarts the internal webservier"))
2305 wx.EVT_MENU(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessEvent)
2306 wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
2307
2308 frame.Bind(EVT_DEBUG_INTERNAL, frame.ProcessEvent)
2309 debuggerMenu.AppendSeparator()
2310
2311 debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint\tCtrl+B"), _("Toggle a breakpoint"))
2312 wx.EVT_MENU(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessEvent)
2313 wx.EVT_UPDATE_UI(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessUpdateUIEvent)
2314
2315 debuggerMenu.Append(DebuggerService.CLEAR_ALL_BREAKPOINTS, _("&Clear All Breakpoints"), _("Clear All Breakpoints"))
2316 wx.EVT_MENU(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessEvent)
2317 wx.EVT_UPDATE_UI(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessUpdateUIEvent)
2318
2319
2320 viewMenuIndex = menuBar.FindMenu(_("&Project"))
2321 menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run"))
2322
2323 toolBar.AddSeparator()
2324 toolBar.AddTool(DebuggerService.RUN_LAST_ID, getRunningManBitmap(), shortHelpString = _("Run Using Last Settings"), longHelpString = _("Run Using Last Settings"))
2325 toolBar.AddTool(DebuggerService.DEBUG_LAST_ID, getDebuggingManBitmap(), shortHelpString = _("Debug Using Last Settings"), longHelpString = _("Debug Using Last Settings"))
2326 toolBar.Realize()
2327
2328 return True
2329
2330
2331
2332 #----------------------------------------------------------------------------
2333 # Event Processing Methods
2334 #----------------------------------------------------------------------------
2335
2336 def ProcessEventBeforeWindows(self, event):
2337 return False
2338
2339
2340 def ProcessEvent(self, event):
2341 if Service.Service.ProcessEvent(self, event):
2342 return True
2343
2344 an_id = event.GetId()
2345 if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
2346 self.OnToggleBreakpoint(event)
2347 return True
2348 elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
2349 self.ClearAllBreakpoints()
2350 return True
2351 elif an_id == DebuggerService.RUN_ID:
2352 self.OnRunProject(event)
2353 return True
2354 elif an_id == DebuggerService.DEBUG_ID:
2355 self.OnDebugProject(event)
2356 return True
2357 elif an_id == DebuggerService.RUN_LAST_ID:
2358 self.OnRunProject(event, showDialog=False)
2359 return True
2360 elif an_id == DebuggerService.DEBUG_LAST_ID:
2361 self.OnDebugProject(event, showDialog=False)
2362 return True
2363 elif an_id == DebuggerService.DEBUG_WEBSERVER_ID:
2364 self.OnDebugWebServer(event)
2365 return True
2366 elif an_id == DebuggerService.DEBUG_WEBSERVER_CONTINUE_ID:
2367 self.OnDebugWebServerContinue(event)
2368 return True
2369 elif an_id == DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID:
2370 self.WaitDebuggerThenRunProject()
2371 return True
2372 elif an_id == DebuggerService.RUN_WEBSERVER_ID:
2373 self.OnRunWebServer(event)
2374 return True
2375 return False
2376
2377 def ProcessUpdateUIEvent(self, event):
2378 if Service.Service.ProcessUpdateUIEvent(self, event):
2379 return True
2380
2381 an_id = event.GetId()
2382 if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
2383 currentView = self.GetDocumentManager().GetCurrentView()
2384 event.Enable(isinstance(currentView, PythonEditor.PythonView))
2385 return True
2386 elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
2387 event.Enable(self.HasBreakpointsSet())
2388 return True
2389 elif (an_id == DebuggerService.RUN_ID
2390 or an_id == DebuggerService.RUN_LAST_ID
2391 or an_id == DebuggerService.DEBUG_ID
2392 or an_id == DebuggerService.DEBUG_LAST_ID):
2393 event.Enable(self.HasAnyFiles())
2394 return True
2395 else:
2396 return False
2397
2398 #----------------------------------------------------------------------------
2399 # Class Methods
2400 #----------------------------------------------------------------------------
2401
2402 def OnDebugProject(self, event, showDialog=True):
2403 if _WINDOWS and not _PYWIN32_INSTALLED:
2404 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."))
2405 return
2406 if not Executor.GetPythonExecutablePath():
2407 return
2408 if BaseDebuggerUI.DebuggerRunning():
2409 wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
2410 return
2411 config = wx.ConfigBase_Get()
2412 host = config.Read("DebuggerHostName", DEFAULT_HOST)
2413 if not host:
2414 wx.MessageBox(_("No debugger host set. Please go to Tools->Options->Debugger and set one."), _("No Debugger Host"))
2415 return
2416
2417 self.ShowWindow(True)
2418 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
2419 try:
2420 dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug File', projectService, None, okButtonName="Debug", debugging=True)
2421 except:
2422 return
2423 dlg.CenterOnParent()
2424 if not showDialog:
2425 showDialog = dlg.MustShowDialog()
2426 if showDialog and dlg.ShowModal() == wx.ID_OK:
2427 projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
2428 elif not showDialog:
2429 projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
2430 else:
2431 dlg.Destroy()
2432 return
2433 dlg.Destroy()
2434 self.PromptToSaveFiles()
2435 shortFile = os.path.basename(fileToDebug)
2436 fileToDebug = DebuggerService.ExpandPath(fileToDebug)
2437 if fileToDebug.endswith('.bpel'):
2438 self.projectPath = projectPath
2439 self.fileToDebug = fileToDebug
2440
2441 #
2442 # TODO: merge getting project stuff and save the results for
2443 # WaitDebuggerThenRunProject() which currently does it again.
2444 #
2445 projects = projectService.FindProjectByFile(projectPath)
2446 if not projects:
2447 return
2448 project = projects[0]
2449 lang = project.GetAppInfo().language
2450 if lang:
2451 self.dbgLanguage = lang
2452
2453 dbgService = wx.GetApp().GetService(DebuggerService)
2454
2455 evt = DebugInternalWebServer()
2456 evt.SetId(DebuggerService.DEBUG_WEBSERVER_CONTINUE_ID)
2457 wx.PostEvent(dbgService._frame, evt)
2458
2459 if lang == projectmodel.LANGUAGE_PHP:
2460 evt = DebugInternalWebServer()
2461 evt.SetId(DebuggerService.DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID)
2462 wx.PostEvent(dbgService._frame, evt)
2463
2464 return
2465
2466 elif fileToDebug.endswith('.php'):
2467 page = PHPDebuggerUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self)
2468 count = Service.ServiceView.bottomTab.GetPageCount()
2469 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile)
2470 Service.ServiceView.bottomTab.SetSelection(count)
2471
2472 fullPhpScriptPath = os.path.normpath(fileToDebug)
2473 environment["REDIRECT_STATUS"] = "200"
2474 environment["REDIRECT_URL"] = fullPhpScriptPath
2475 environment["SERVER_SOFTWARE"] = "AG PHP Debugger 1.7"
2476 environment["SERVER_NAME"] = "localhost"
2477 environment["SERVER_ADDR"] = "127.0.0.1"
2478 environment["SERVER_PORT"] = "80"
2479 environment["REMOTE_ADDR"] = "127.0.0.1"
2480 environment["SCRIPT_FILENAME"] = "php"
2481 environment["GATEWAY_INTERFACE"] = "CGI/1.1"
2482 environment["SERVER_PROTOCOL"] = "HTTP/1.1"
2483 environment["REQUEST_METHOD"] = "GET"
2484 environment["REQUEST_URI"] = fullPhpScriptPath
2485 environment["PATH_INFO"] = fullPhpScriptPath
2486 environment["PATH_TRANSLATED"] = fullPhpScriptPath
2487 environment["HTTP_COOKIE"] = "DBGSESSID=11439636363807700001@clienthost:10001"
2488
2489 page.Execute(initialArgs, startIn, environment)
2490 else:
2491 try:
2492 page = PythonDebuggerUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self)
2493 count = Service.ServiceView.bottomTab.GetPageCount()
2494 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile)
2495 Service.ServiceView.bottomTab.SetSelection(count)
2496 page.Execute(initialArgs, startIn, environment)
2497 except:
2498 pass
2499
2500 def WaitDebuggerThenRunProject(self):
2501 import time
2502 #while not BaseDebuggerUI.DebuggerPastAutoContinue():
2503 # time.sleep(0.2)
2504 # wx.GetApp().Yield(True)
2505 # print "After Yield"
2506 time.sleep(2.0)
2507 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
2508 projects = projectService.FindProjectByFile(self.projectPath)
2509 if not projects:
2510 return
2511 project = projects[0]
2512 try:
2513 deployFilePath = project.GenerateDeployment()
2514 except ProjectEditor.DataServiceExistenceException, e:
2515 dataSourceName = str(e)
2516 projectService.PromptForMissingDataSource(dataSourceName)
2517 return
2518 projectService.RunProcessModel(self.fileToDebug, project.GetAppInfo().language, deployFilePath)
2519
2520 def OnDebugWebServerContinue(self, event):
2521 self.OnDebugWebServer(event, autoContinue=True)
2522
2523 def OnDebugWebServer(self, event, autoContinue=False):
2524 #print "xxxxx debugging OnDebugWebServer"
2525 if _WINDOWS and not _PYWIN32_INSTALLED:
2526 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."))
2527 return
2528 if not Executor.GetPythonExecutablePath():
2529 return
2530 if BaseDebuggerUI.DebuggerRunning():
2531 wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
2532 return
2533 import WebServerService
2534 wsService = wx.GetApp().GetService(WebServerService.WebServerService)
2535 fileName, args = wsService.StopAndPrepareToDebug()
2536 #print "xxxxx OnDebugWebServer: fileName=%s, args=%s" % (repr(fileName), repr(args))
2537 config = wx.ConfigBase_Get()
2538 host = config.Read("DebuggerHostName", DEFAULT_HOST)
2539 if not host:
2540 wx.MessageBox(_("No debugger host set. Please go to Tools->Options->Debugger and set one."), _("No Debugger Host"))
2541 return
2542 try:
2543 if self.dbgLanguage == projectmodel.LANGUAGE_PHP:
2544 page = PHPDebuggerUI(Service.ServiceView.bottomTab, -1, fileName, self)
2545 else:
2546 page = PythonDebuggerUI(Service.ServiceView.bottomTab, -1, fileName, self, autoContinue)
2547
2548 count = Service.ServiceView.bottomTab.GetPageCount()
2549 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: Internal WebServer"))
2550 Service.ServiceView.bottomTab.SetSelection(count)
2551 page.Execute(args, startIn=sysutilslib.mainModuleDir, environment=os.environ, onWebServer = True)
2552 except:
2553 pass
2554
2555 def OnRunWebServer(self, event):
2556 if not Executor.GetPythonExecutablePath():
2557 return
2558 import WebServerService
2559 wsService = wx.GetApp().GetService(WebServerService.WebServerService)
2560 wsService.ShutDownAndRestart()
2561
2562 def HasAnyFiles(self):
2563 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2564 return len(docs) > 0
2565
2566 def PromptToSaveFiles(self, running=True):
2567 filesModified = False
2568 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2569 for doc in docs:
2570 if doc.IsModified():
2571 filesModified = True
2572 break
2573 if filesModified:
2574 frame = self.GetView().GetFrame()
2575 if running:
2576 yesNoMsg = wx.MessageDialog(frame,
2577 _("Files have been modified.\nWould you like to save all files before running?"),
2578 _("Run"),
2579 wx.YES_NO|wx.ICON_QUESTION
2580 )
2581 else:
2582 yesNoMsg = wx.MessageDialog(frame,
2583 _("Files have been modified.\nWould you like to save all files before debugging?"),
2584 _("Debug"),
2585 wx.YES_NO|wx.ICON_QUESTION
2586 )
2587 yesNoMsg.CenterOnParent()
2588 if yesNoMsg.ShowModal() == wx.ID_YES:
2589 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2590 for doc in docs:
2591 doc.Save()
2592 yesNoMsg.Destroy()
2593
2594 def OnExit(self):
2595 BaseDebuggerUI.ShutdownAllDebuggers()
2596 RunCommandUI.ShutdownAllRunners()
2597
2598 def OnRunProject(self, event, showDialog=True):
2599 if _WINDOWS and not _PYWIN32_INSTALLED:
2600 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."))
2601 return
2602 if not Executor.GetPythonExecutablePath():
2603 return
2604 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
2605 try:
2606 dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None)
2607 except:
2608 return
2609 dlg.CenterOnParent()
2610 if not showDialog:
2611 showDialog = dlg.MustShowDialog()
2612 if showDialog and dlg.ShowModal() == wx.ID_OK:
2613 projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
2614 elif not showDialog:
2615 projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
2616 else:
2617 dlg.Destroy()
2618 return
2619 dlg.Destroy()
2620 self.PromptToSaveFiles()
2621 if fileToRun.endswith('bpel'):
2622 projects = projectService.FindProjectByFile(projectPath)
2623 if not projects:
2624 return
2625 project = projects[0]
2626 try:
2627 deployFilePath = project.GenerateDeployment()
2628 except ProjectEditor.DataServiceExistenceException, e:
2629 dataSourceName = str(e)
2630 projectService.PromptForMissingDataSource(dataSourceName)
2631 return
2632 projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath)
2633 return
2634
2635 self.ShowWindow(True)
2636 shortFile = os.path.basename(fileToRun)
2637 page = RunCommandUI(Service.ServiceView.bottomTab, -1, str(fileToRun))
2638 count = Service.ServiceView.bottomTab.GetPageCount()
2639 Service.ServiceView.bottomTab.AddPage(page, "Running: " + shortFile)
2640 Service.ServiceView.bottomTab.SetSelection(count)
2641 page.Execute(initialArgs, startIn, environment, onWebServer = True)
2642
2643 def OnToggleBreakpoint(self, event, line=-1, fileName=None):
2644 if not fileName:
2645 view = wx.GetApp().GetDocumentManager().GetCurrentView()
2646 # Test to make sure we aren't the project view.
2647 if not hasattr(view, 'MarkerExists'):
2648 return
2649 fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
2650 if line < 0:
2651 line = view.GetCtrl().GetCurrentLine()
2652 else:
2653 view = None
2654 if self.BreakpointSet(fileName, line + 1):
2655 self.ClearBreak(fileName, line + 1)
2656 if view:
2657 view.GetCtrl().Refresh()
2658 else:
2659 self.SetBreak(fileName, line + 1)
2660 if view:
2661 view.GetCtrl().Refresh()
2662 # Now refresh all the markers icons in all the open views.
2663 self.ClearAllBreakpointMarkers()
2664 self.SetAllBreakpointMarkers()
2665
2666 def SilentToggleBreakpoint(self, fileName, line):
2667 found = False
2668 for lineNumber in self.GetBreakpointList(fileName):
2669 if int(lineNumber) == int(line):
2670 found = True
2671 break
2672 if found:
2673 self.SetBreak(fileName, line)
2674 else:
2675 self.ClearBreak(fileName, line)
2676
2677 def SetBreak(self, fileName, line):
2678 expandedName = DebuggerService.ExpandPath(fileName)
2679 if not self._masterBPDict.has_key(expandedName):
2680 self._masterBPDict[expandedName] = [line]
2681 else:
2682 self._masterBPDict[expandedName] += [line]
2683 # If we're already debugging, pass this bp off to the PythonDebuggerCallback
2684 self.NotifyDebuggersOfBreakpointChange()
2685
2686 def NotifyDebuggersOfBreakpointChange(self):
2687 BaseDebuggerUI.NotifyDebuggersOfBreakpointChange()
2688
2689 def GetBreakpointList(self, fileName):
2690 expandedName = DebuggerService.ExpandPath(fileName)
2691 if not self._masterBPDict.has_key(expandedName):
2692 return []
2693 else:
2694 return self._masterBPDict[expandedName]
2695
2696 def SetBreakpointList(self, fileName, bplist):
2697 expandedName = DebuggerService.ExpandPath(fileName)
2698 self._masterBPDict[expandedName] = bplist
2699
2700 def BreakpointSet(self, fileName, line):
2701 expandedName = DebuggerService.ExpandPath(fileName)
2702 if not self._masterBPDict.has_key(expandedName):
2703 return False
2704 else:
2705 newList = []
2706 for number in self._masterBPDict[expandedName]:
2707 if(int(number) == int(line)):
2708 return True
2709 return False
2710
2711 def ClearBreak(self, fileName, line):
2712 expandedName = DebuggerService.ExpandPath(fileName)
2713 if not self._masterBPDict.has_key(expandedName):
2714 print "In ClearBreak: no key"
2715 return
2716 else:
2717 newList = []
2718 for number in self._masterBPDict[expandedName]:
2719 if(int(number) != int(line)):
2720 newList.append(number)
2721 self._masterBPDict[expandedName] = newList
2722 self.NotifyDebuggersOfBreakpointChange()
2723
2724 def HasBreakpointsSet(self):
2725 for key, value in self._masterBPDict.items():
2726 if len(value) > 0:
2727 return True
2728 return False
2729
2730 def ClearAllBreakpoints(self):
2731 self._masterBPDict = {}
2732 self.NotifyDebuggersOfBreakpointChange()
2733 self.ClearAllBreakpointMarkers()
2734
2735 def ClearAllBreakpointMarkers(self):
2736 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
2737 for openDoc in openDocs:
2738 if isinstance(openDoc, CodeEditor.CodeDocument):
2739 openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2740
2741 def UpdateBreakpointsFromMarkers(self, view, fileName):
2742 newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2743 self.SetBreakpointList(fileName, newbpLines)
2744
2745 def GetMasterBreakpointDict(self):
2746 return self._masterBPDict
2747
2748 def SetAllBreakpointMarkers(self):
2749 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
2750 for openDoc in openDocs:
2751 if(isinstance(openDoc, CodeEditor.CodeDocument)):
2752 self.SetCurrentBreakpointMarkers(openDoc.GetFirstView())
2753
2754 def SetCurrentBreakpointMarkers(self, view):
2755 if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'):
2756 view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2757 for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()):
2758 view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2759
2760 def GetPhpDbgParam(self):
2761 return self.phpDbgParam
2762
2763 def SetPhpDbgParam(self, value = None):
2764 self.phpDbgParam = value
2765
2766 class DebuggerOptionsPanel(wx.Panel):
2767
2768
2769 def __init__(self, parent, id):
2770 wx.Panel.__init__(self, parent, id)
2771 SPACE = 10
2772 config = wx.ConfigBase_Get()
2773 localHostStaticText = wx.StaticText(self, -1, _("Local Host Name:"))
2774 self._LocalHostTextCtrl = wx.TextCtrl(self, -1, config.Read("DebuggerHostName", DEFAULT_HOST), size = (150, -1))
2775 portNumberStaticText = wx.StaticText(self, -1, _("Port Range:"))
2776 dashStaticText = wx.StaticText(self, -1, _("through to"))
2777 startingPort=config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
2778 self._PortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort, size = (50, -1))
2779 self._PortNumberTextCtrl.SetMin(1)#What are real values?
2780 self._PortNumberTextCtrl.SetMax(65514) #What are real values?
2781 self.Bind(wx.lib.intctrl.EVT_INT, self.MinPortChange, self._PortNumberTextCtrl)
2782
2783 self._EndPortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort + PORT_COUNT, size = (50, -1))
2784 self._EndPortNumberTextCtrl.SetMin(22)#What are real values?
2785 self._EndPortNumberTextCtrl.SetMax(65535)#What are real values?
2786 self._EndPortNumberTextCtrl.Enable( False )
2787 debuggerPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
2788 debuggerPanelSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
2789 debuggerPanelSizer.Add( localHostStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2790 debuggerPanelSizer.Add( self._LocalHostTextCtrl, (0,1), (1,3), flag=wx.EXPAND|wx.ALIGN_CENTER)
2791 debuggerPanelSizer.Add( portNumberStaticText, (1,0), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
2792 debuggerPanelSizer.Add( self._PortNumberTextCtrl, (1,1), flag=wx.ALIGN_CENTER)
2793 debuggerPanelSizer.Add( dashStaticText, (1,2), flag=wx.ALIGN_CENTER)
2794 debuggerPanelSizer.Add( self._EndPortNumberTextCtrl, (1,3), flag=wx.ALIGN_CENTER)
2795 FLUSH_PORTS_ID = wx.NewId()
2796 self._flushPortsButton = wx.Button(self, FLUSH_PORTS_ID, "Reset Port List")
2797 wx.EVT_BUTTON(parent, FLUSH_PORTS_ID, self.FlushPorts)
2798 debuggerPanelSizer.Add(self._flushPortsButton, (2,2), (1,2), flag=wx.ALIGN_RIGHT)
2799
2800 debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE)
2801 self.SetSizer(debuggerPanelBorderSizer)
2802 self.Layout()
2803 parent.AddPage(self, _("Debugger"))
2804
2805 def FlushPorts(self, event):
2806 if self._PortNumberTextCtrl.IsInBounds():
2807 config = wx.ConfigBase_Get()
2808 config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
2809 PythonDebuggerUI.NewPortRange()
2810 else:
2811 wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
2812
2813 def MinPortChange(self, event):
2814 self._EndPortNumberTextCtrl.Enable( True )
2815 self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT)
2816 self._EndPortNumberTextCtrl.Enable( False )
2817
2818 def OnOK(self, optionsDialog):
2819 config = wx.ConfigBase_Get()
2820 config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue())
2821 if self._PortNumberTextCtrl.IsInBounds():
2822 config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
2823
2824
2825 def GetIcon(self):
2826 return getContinueIcon()
2827
2828
2829 class CommandPropertiesDialog(wx.Dialog):
2830 def __init__(self, parent, title, projectService, currentProjectDocument, okButtonName="Run", debugging=False):
2831 self._projService = projectService
2832 self._pmext = None
2833 self._pyext = '.py'
2834 self._phpext = '.php'
2835 for template in self._projService.GetDocumentManager().GetTemplates():
2836 if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
2837 self._pmext = template.GetDefaultExtension()
2838 break
2839 self._currentProj = projectService.GetCurrentProject()
2840 self._projectNameList, self._projectDocumentList, selectedIndex = self.GetProjectList()
2841 if not self._projectNameList:
2842 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"))
2843 raise Exception("Nothing to Run or Debug.")
2844
2845 wx.Dialog.__init__(self, parent, -1, title)
2846
2847 projStaticText = wx.StaticText(self, -1, _("Project:"))
2848 fileStaticText = wx.StaticText(self, -1, _("File:"))
2849 argsStaticText = wx.StaticText(self, -1, _("Arguments:"))
2850 startInStaticText = wx.StaticText(self, -1, _("Start in:"))
2851 pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:"))
2852 postpendStaticText = _("Postpend win32api path")
2853 cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
2854 self._projList = wx.Choice(self, -1, choices=self._projectNameList)
2855 self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList)
2856 HALF_SPACE = 5
2857 GAP = HALF_SPACE
2858 if wx.Platform == "__WXMAC__":
2859 GAP = 10
2860 flexGridSizer = wx.GridBagSizer(GAP, GAP)
2861
2862 flexGridSizer.Add(projStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2863 flexGridSizer.Add(self._projList, (0,1), (1,2), flag=wx.EXPAND)
2864
2865 flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2866 self._fileList = wx.Choice(self, -1)
2867 self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList)
2868 flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND)
2869
2870 config = wx.ConfigBase_Get()
2871 self._lastArguments = config.Read(self.GetKey("LastRunArguments"))
2872 self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments))
2873 self._argsEntry.SetToolTipString(str(self._lastArguments))
2874
2875 flexGridSizer.Add(argsStaticText, (2,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2876 flexGridSizer.Add(self._argsEntry, (2,1), (1,2), flag=wx.EXPAND)
2877
2878 flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2879 self._lastStartIn = config.Read(self.GetKey("LastRunStartIn"))
2880 if not self._lastStartIn:
2881 self._lastStartIn = str(os.getcwd())
2882 self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn)
2883 self._startEntry.SetToolTipString(self._lastStartIn)
2884
2885 flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND)
2886 self._findDir = wx.Button(self, -1, _("Browse..."))
2887 self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir)
2888 flexGridSizer.Add(self._findDir, (3,2))
2889
2890 flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2891 if os.environ.has_key('PYTHONPATH'):
2892 startval = os.environ['PYTHONPATH']
2893 else:
2894 startval = ""
2895 self._lastPythonPath = config.Read(self.GetKey("LastPythonPath"), startval)
2896 self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath)
2897 self._pythonPathEntry.SetToolTipString(self._lastPythonPath)
2898 flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND)
2899
2900 if debugging and _WINDOWS:
2901 self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText)
2902 checked = bool(config.ReadInt(self.GetKey("PythonPathPostpend"), 1))
2903 self._postpendCheckBox.SetValue(checked)
2904 flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND)
2905 cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10)
2906
2907 box = wx.StdDialogButtonSizer()
2908 self._okButton = wx.Button(self, wx.ID_OK, okButtonName)
2909 self._okButton.SetDefault()
2910 self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog"))
2911 box.AddButton(self._okButton)
2912 self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton)
2913 btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
2914 btn.SetHelpText(_("The Cancel button cancels the dialog."))
2915 box.AddButton(btn)
2916 box.Realize()
2917 cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5)
2918
2919 self.SetSizer(cpPanelBorderSizer)
2920
2921 # Set up selections based on last values used.
2922 self._fileNameList = None
2923 self._selectedFileIndex = -1
2924 lastProject = config.Read(self.GetKey("LastRunProject"))
2925 lastFile = config.Read(self.GetKey("LastRunFile"))
2926 self._mustShow = not lastFile
2927
2928 if lastProject in self._projectNameList:
2929 selectedIndex = self._projectNameList.index(lastProject)
2930 elif selectedIndex < 0:
2931 selectedIndex = 0
2932 self._projList.Select(selectedIndex)
2933 self._selectedProjectIndex = selectedIndex
2934 self._selectedProjectDocument = self._projectDocumentList[selectedIndex]
2935 self.PopulateFileList(self._selectedProjectDocument, lastFile)
2936
2937 cpPanelBorderSizer.Fit(self)
2938
2939 def MustShowDialog(self):
2940 return self._mustShow
2941
2942 def GetKey(self, lastPart):
2943 if self._currentProj:
2944 return "%s/%s/%s" % (ProjectEditor.PROJECT_KEY, self._currentProj.GetFilename().replace(os.sep, '|'), lastPart)
2945
2946
2947 def OnOKClick(self, event):
2948 startIn = self._startEntry.GetValue()
2949 fileToRun = self._fileList.GetStringSelection()
2950 if not fileToRun:
2951 wx.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged."))
2952 return
2953 isPython = fileToRun.endswith(self._pyext)
2954 if isPython and not os.path.exists(startIn):
2955 wx.MessageBox(_("Starting directory does not exist. Please change this value."))
2956 return
2957 config = wx.ConfigBase_Get()
2958 config.Write(self.GetKey("LastRunProject"), self._projectNameList[self._selectedProjectIndex])
2959 config.Write(self.GetKey("LastRunFile"), fileToRun)
2960 # Don't update the arguments or starting directory unless we're runing python.
2961 if isPython:
2962 config.Write(self.GetKey("LastRunArguments"), self._argsEntry.GetValue())
2963 config.Write(self.GetKey("LastRunStartIn"), self._startEntry.GetValue())
2964 config.Write(self.GetKey("LastPythonPath"),self._pythonPathEntry.GetValue())
2965 if hasattr(self, "_postpendCheckBox"):
2966 config.WriteInt(self.GetKey("PythonPathPostpend"), int(self._postpendCheckBox.GetValue()))
2967
2968 self.EndModal(wx.ID_OK)
2969
2970 def GetSettings(self):
2971 projectPath = self._selectedProjectDocument.GetFilename()
2972 filename = self._fileNameList[self._selectedFileIndex]
2973 args = self._argsEntry.GetValue()
2974 startIn = self._startEntry.GetValue()
2975 isPython = filename.endswith(self._pyext)
2976 env = os.environ
2977 if hasattr(self, "_postpendCheckBox"):
2978 postpend = self._postpendCheckBox.GetValue()
2979 else:
2980 postpend = False
2981 if postpend:
2982 env['PYTHONPATH'] = self._pythonPathEntry.GetValue() + os.pathsep + os.path.join(os.getcwd(), "3rdparty", "pywin32")
2983 else:
2984 env['PYTHONPATH'] = self._pythonPathEntry.GetValue()
2985
2986 return projectPath, filename, args, startIn, isPython, env
2987
2988 def OnFileSelected(self, event):
2989 self._selectedFileIndex = self._fileList.GetSelection()
2990 self.EnableForFileType(event.GetString())
2991
2992 def EnableForFileType(self, fileName):
2993 show = fileName.endswith(self._pyext) or fileName.endswith(self._phpext)
2994 self._startEntry.Enable(show)
2995 self._findDir.Enable(show)
2996 self._argsEntry.Enable(show)
2997
2998 if not show:
2999 self._lastStartIn = self._startEntry.GetValue()
3000 self._startEntry.SetValue("")
3001 self._lastArguments = self._argsEntry.GetValue()
3002 self._argsEntry.SetValue("")
3003 else:
3004 if fileName.endswith(self._phpext):
3005 self._startEntry.SetValue(os.path.dirname(fileName))
3006 else:
3007 self._startEntry.SetValue(self._lastStartIn)
3008 self._argsEntry.SetValue(self._lastArguments)
3009
3010
3011
3012 def OnFindDirClick(self, event):
3013 dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(),
3014 style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
3015
3016 dlg.CenterOnParent()
3017 if dlg.ShowModal() == wx.ID_OK:
3018 self._startEntry.SetValue(dlg.GetPath())
3019
3020 dlg.Destroy()
3021
3022
3023 def EvtListBox(self, event):
3024 if event.GetString():
3025 index = self._projectNameList.index(event.GetString())
3026 self._selectedProjectDocument = self._projectDocumentList[index]
3027 self._selectedProjectIndex = index
3028 self.PopulateFileList(self._selectedProjectDocument)
3029
3030 def FilterFileList(self, list):
3031 files = filter(lambda f: (self._phpext and f.endswith(self._phpext)) or (self._pmext and f.endswith(self._pmext)) or f.endswith(self._pyext), list)
3032 return files
3033
3034 def PopulateFileList(self, project, shortNameToSelect=None):
3035 self._fileNameList = self.FilterFileList(project.GetFiles()[:])
3036 self._fileList.Clear()
3037 if not self._fileNameList:
3038 return
3039 self._fileNameList.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower()))
3040 strings = map(lambda file: os.path.basename(file), self._fileNameList)
3041 for index in range(0, len(strings)):
3042 if shortNameToSelect == strings[index]:
3043 self._selectedFileIndex = index
3044 break
3045 self._fileList.Hide()
3046 self._fileList.AppendItems(strings)
3047 self._fileList.Show()
3048 if self._selectedFileIndex not in range(0, len(strings)):
3049 # Pick first bpel file if there is one.
3050 for index in range(0, len(strings)):
3051 if strings[index].endswith('.bpel'):
3052 self._selectedFileIndex = index
3053 break
3054 # Still no selected file, use first file.
3055 if self._selectedFileIndex not in range(0, len(strings)):
3056 self._selectedFileIndex = 0
3057 self._fileList.SetSelection(self._selectedFileIndex)
3058 self.EnableForFileType(strings[self._selectedFileIndex])
3059
3060 def GetProjectList(self):
3061 docList = []
3062 nameList = []
3063 found = False
3064 index = -1
3065 count = 0
3066 for document in self._projService.GetDocumentManager().GetDocuments():
3067 if document.GetDocumentTemplate().GetDocumentType() == ProjectEditor.ProjectDocument and len(document.GetFiles()):
3068 docList.append(document)
3069 nameList.append(os.path.basename(document.GetFilename()))
3070 if document == self._currentProj:
3071 found = True
3072 index = count
3073 count += 1
3074 #Check for open files not in any of these projects and add them to a default project
3075 def AlreadyInProject(fileName):
3076 for projectDocument in docList:
3077 if projectDocument.IsFileInProject(fileName):
3078 return True
3079 return False
3080
3081 unprojectedFiles = []
3082 for document in self._projService.GetDocumentManager().GetDocuments():
3083 if not ACTIVEGRID_BASE_IDE and type(document) == ProcessModelEditor.ProcessModelDocument:
3084 if not AlreadyInProject(document.GetFilename()):
3085 unprojectedFiles.append(document.GetFilename())
3086 if type(document) == PythonEditor.PythonDocument or type(document) == PHPEditor.PHPDocument:
3087 if not AlreadyInProject(document.GetFilename()):
3088 unprojectedFiles.append(document.GetFilename())
3089
3090 if unprojectedFiles:
3091 unprojProj = ProjectEditor.ProjectDocument()
3092 unprojProj.SetFilename(_("Not in any Project"))
3093 unprojProj.AddFiles(unprojectedFiles)
3094 docList.append(unprojProj)
3095 nameList.append(_("Not in any Project"))
3096
3097 return nameList, docList, index
3098
3099
3100 #----------------------------------------------------------------------
3101 from wx import ImageFromStream, BitmapFromImage
3102 import cStringIO
3103
3104 #----------------------------------------------------------------------
3105 def getBreakData():
3106 return \
3107 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
3108 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
3109 \x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\
3110 \x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\
3111 \xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\
3112 \x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\
3113 5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\
3114 \x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\
3115 \xaeB`\x82'
3116
3117 def getBreakBitmap():
3118 return BitmapFromImage(getBreakImage())
3119
3120 def getBreakImage():
3121 stream = cStringIO.StringIO(getBreakData())
3122 return ImageFromStream(stream)
3123
3124 def getBreakIcon():
3125 return wx.IconFromBitmap(getBreakBitmap())
3126
3127 #----------------------------------------------------------------------
3128
3129 def getClearOutputData():
3130 return \
3131 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3132 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3133 \x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\
3134 \xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\
3135 \x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\
3136 \x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\
3137 \x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\
3138 \xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\
3139 \xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\
3140 \x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\
3141 \x00IEND\xaeB`\x82'
3142
3143 def getClearOutputBitmap():
3144 return BitmapFromImage(getClearOutputImage())
3145
3146 def getClearOutputImage():
3147 stream = cStringIO.StringIO(getClearOutputData())
3148 return ImageFromStream(stream)
3149
3150 def getClearOutputIcon():
3151 return wx.IconFromBitmap(getClearOutputBitmap())
3152
3153 #----------------------------------------------------------------------
3154 def getCloseData():
3155 return \
3156 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
3157 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
3158 \x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\
3159 \x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\
3160 \xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\
3161 \xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\
3162 \x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\
3163 \xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\
3164 \x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\
3165 \xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\
3166 \xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\
3167 \xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82'
3168
3169 def getCloseBitmap():
3170 return BitmapFromImage(getCloseImage())
3171
3172 def getCloseImage():
3173 stream = cStringIO.StringIO(getCloseData())
3174 return ImageFromStream(stream)
3175
3176 def getCloseIcon():
3177 return wx.IconFromBitmap(getCloseBitmap())
3178
3179 #----------------------------------------------------------------------
3180 def getContinueData():
3181 return \
3182 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3183 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3184 \x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\
3185 \x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\
3186 !P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\
3187 \xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\
3188 \x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\
3189 \x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\
3190 \xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\
3191 \x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\
3192 \x00\x00\x00\x00IEND\xaeB`\x82'
3193
3194 def getContinueBitmap():
3195 return BitmapFromImage(getContinueImage())
3196
3197 def getContinueImage():
3198 stream = cStringIO.StringIO(getContinueData())
3199 return ImageFromStream(stream)
3200
3201 def getContinueIcon():
3202 return wx.IconFromBitmap(getContinueBitmap())
3203
3204 #----------------------------------------------------------------------
3205 def getNextData():
3206 return \
3207 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3208 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3209 \x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\
3210 \x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\
3211 gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\
3212 \x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\
3213 \xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\
3214 )\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\
3215 `\x82'
3216
3217 def getNextBitmap():
3218 return BitmapFromImage(getNextImage())
3219
3220 def getNextImage():
3221 stream = cStringIO.StringIO(getNextData())
3222 return ImageFromStream(stream)
3223
3224 def getNextIcon():
3225 return wx.IconFromBitmap(getNextBitmap())
3226
3227 #----------------------------------------------------------------------
3228 def getStepInData():
3229 return \
3230 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3231 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3232 \x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\
3233 \x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\
3234 \x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\
3235 ]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\
3236 \x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\
3237 \x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
3238
3239 def getStepInBitmap():
3240 return BitmapFromImage(getStepInImage())
3241
3242 def getStepInImage():
3243 stream = cStringIO.StringIO(getStepInData())
3244 return ImageFromStream(stream)
3245
3246 def getStepInIcon():
3247 return wx.IconFromBitmap(getStepInBitmap())
3248
3249 #----------------------------------------------------------------------
3250 def getStopData():
3251 return \
3252 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3253 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3254 \x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\
3255 \xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\
3256 \x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\
3257 \x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
3258
3259 def getStopBitmap():
3260 return BitmapFromImage(getStopImage())
3261
3262 def getStopImage():
3263 stream = cStringIO.StringIO(getStopData())
3264 return ImageFromStream(stream)
3265
3266 def getStopIcon():
3267 return wx.IconFromBitmap(getStopBitmap())
3268
3269 #----------------------------------------------------------------------
3270 def getStepReturnData():
3271 return \
3272 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3273 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3274 \x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\
3275 \xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\
3276 \x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\
3277 \x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\
3278 \x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\
3279 \xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\
3280 \xaeB`\x82"
3281
3282 def getStepReturnBitmap():
3283 return BitmapFromImage(getStepReturnImage())
3284
3285 def getStepReturnImage():
3286 stream = cStringIO.StringIO(getStepReturnData())
3287 return ImageFromStream(stream)
3288
3289 def getStepReturnIcon():
3290 return wx.IconFromBitmap(getStepReturnBitmap())
3291
3292 #----------------------------------------------------------------------
3293 def getAddWatchData():
3294 return \
3295 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3296 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3297 \x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\
3298 \x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\
3299 \xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\
3300 \xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\
3301 \xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\
3302 \x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
3303
3304 def getAddWatchBitmap():
3305 return BitmapFromImage(getAddWatchImage())
3306
3307 def getAddWatchImage():
3308 stream = cStringIO.StringIO(getAddWatchData())
3309 return ImageFromStream(stream)
3310
3311 def getAddWatchIcon():
3312 return wx.IconFromBitmap(getAddWatchBitmap())
3313
3314 #----------------------------------------------------------------------
3315 def getRunningManData():
3316 return \
3317 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3318 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3319 \x00\x01\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\
3320 \x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\
3321 %\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\
3322 \x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \
3323 \\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\
3324 \xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\
3325 CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\
3326 \x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\
3327 \x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\
3328 \x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\
3329 \x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\
3330 \r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\
3331 \x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\
3332 \xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\
3333 \xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\
3334 \xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82'
3335
3336 def getRunningManBitmap():
3337 return BitmapFromImage(getRunningManImage())
3338
3339 def getRunningManImage():
3340 stream = cStringIO.StringIO(getRunningManData())
3341 return ImageFromStream(stream)
3342
3343 def getRunningManIcon():
3344 icon = EmptyIcon()
3345 icon.CopyFromBitmap(getRunningManBitmap())
3346 return icon
3347
3348 #----------------------------------------------------------------------
3349 def getDebuggingManData():
3350 return \
3351 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3352 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3353 \x00\x01\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\
3354 \xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\
3355 \xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\
3356 \xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\
3357 \xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\
3358 ++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\
3359 f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\
3360 \x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\
3361 \xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\
3362 \xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\
3363 \x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\
3364 \x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\
3365 \xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\
3366 \xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\
3367 \x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\
3368 \x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\
3369 \x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\
3370 \xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82'
3371
3372 def getDebuggingManBitmap():
3373 return BitmapFromImage(getDebuggingManImage())
3374
3375 def getDebuggingManImage():
3376 stream = cStringIO.StringIO(getDebuggingManData())
3377 return ImageFromStream(stream)
3378
3379 def getDebuggingManIcon():
3380 icon = EmptyIcon()
3381 icon.CopyFromBitmap(getDebuggingManBitmap())
3382 return icon
3383
3384 #----------------------------------------------------------------------
3385