]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/ide/activegrid/tool/DebuggerService.py
DocView and ActiveGrid IDE updates from Morgan Hua:
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / DebuggerService.py
CommitLineData
1f780e48
RD
1#----------------------------------------------------------------------------
2# Name: DebuggerService.py
aca310e5 3# Purpose: Debugger Service for Python and PHP
1f780e48
RD
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
13import wx
14import wx.lib.intctrl
15import wx.lib.docview
16import wx.lib.dialogs
17import wx.gizmos
18import wx._core
19import wx.lib.pydocview
20import Service
21import STCTextEditor
22import CodeEditor
23import PythonEditor
aca310e5
RD
24import PHPEditor
25import PHPDebugger
26import activegrid.model.projectmodel as projectmodel
1f780e48
RD
27from IDE import ACTIVEGRID_BASE_IDE
28if not ACTIVEGRID_BASE_IDE:
29 import ProcessModelEditor
30import wx.lib.scrolledpanel as scrolled
31import sys
32import time
33import SimpleXMLRPCServer
34import xmlrpclib
35import os
36import threading
1f780e48
RD
37import Queue
38import SocketServer
39import ProjectEditor
40import types
41from xml.dom.minidom import parse, parseString
42import bz2
43import pickle
44import DebuggerHarness
45import traceback
46import StringIO
2eeaec19 47import UICommon
aca310e5
RD
48import activegrid.util.sysutils as sysutilslib
49import subprocess
50import shutil
51
1f780e48 52if wx.Platform == '__WXMSW__':
b792147d
RD
53 try:
54 import win32api
55 _PYWIN32_INSTALLED = True
56 except ImportError:
57 _PYWIN32_INSTALLED = False
1f780e48
RD
58 _WINDOWS = True
59else:
60 _WINDOWS = False
b792147d
RD
61
62if not _WINDOWS or _PYWIN32_INSTALLED:
63 import process
64
1f780e48
RD
65_ = wx.GetTranslation
66
67_VERBOSE = False
68_WATCHES_ON = False
69
aca310e5
RD
70import 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
1f780e48
RD
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.
79class 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
26ee3a06 88 self.setDaemon(True)
aca310e5 89
26ee3a06 90 def __del__(self):
aca310e5 91 # See comment on PythonDebuggerUI.StopExecution
26ee3a06 92 self._keepGoing = False
aca310e5 93
1f780e48
RD
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
26ee3a06 104 elif not self._accumulate and self._keepGoing:
1f780e48
RD
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
aca310e5 110 # sure that at least some of the exception gets printed, always
1f780e48 111 # send the first hundred lines back as they come in.
aca310e5 112 if self._lineCount < 100 and self._keepGoing:
1f780e48
RD
113 self._callback_function(output)
114 self._lineCount += 1
aca310e5 115 output = ""
26ee3a06 116 elif time.time() - start > 0.25 and self._keepGoing:
1f780e48 117 try:
aca310e5 118 self._callback_function(output)
1f780e48
RD
119 except wx._core.PyDeadObjectError:
120 # GUI was killed while we were blocked.
121 self._keepGoing = False
122 start = time.time()
aca310e5 123 output = ""
26ee3a06
RD
124 #except TypeError:
125 # pass
1f780e48
RD
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"
aca310e5 136
1f780e48
RD
137 def AskToStop(self):
138 self._keepGoing = False
aca310e5
RD
139
140
1f780e48 141class Executor:
aca310e5
RD
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
1f780e48 149 def GetPythonExecutablePath():
2eeaec19 150 path = UICommon.GetPythonExecPath()
1f780e48
RD
151 if path:
152 return path
aca310e5 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"))
1f780e48 154 return None
aca310e5
RD
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
1f780e48
RD
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
aca310e5
RD
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 + '"'
1f780e48 191 #Better way to do this? Quotes needed for windows file paths.
2eeaec19
RD
192 def spaceAndQuote(text):
193 if text.startswith("\"") and text.endswith("\""):
194 return ' ' + text
195 else:
196 return ' \"' + text + '\"'
1f780e48 197 if(arg1 != None):
2eeaec19 198 self._cmd += spaceAndQuote(arg1)
1f780e48 199 if(arg2 != None):
2eeaec19 200 self._cmd += spaceAndQuote(arg2)
1f780e48 201 if(arg3 != None):
2eeaec19 202 self._cmd += spaceAndQuote(arg3)
1f780e48 203 if(arg4 != None):
2eeaec19 204 self._cmd += spaceAndQuote(arg4)
1f780e48 205 if(arg5 != None):
2eeaec19 206 self._cmd += spaceAndQuote(arg5)
1f780e48 207 if(arg6 != None):
2eeaec19 208 self._cmd += spaceAndQuote(arg6)
1f780e48 209 if(arg7 != None):
2eeaec19 210 self._cmd += spaceAndQuote(arg7)
1f780e48 211 if(arg8 != None):
2eeaec19 212 self._cmd += spaceAndQuote(arg8)
1f780e48 213 if(arg9 != None):
2eeaec19 214 self._cmd += spaceAndQuote(arg9)
aca310e5 215
1f780e48
RD
216 self._stdOutReader = None
217 self._stdErrReader = None
218 self._process = None
aca310e5 219
1f780e48
RD
220 def OutCall(self, text):
221 evt = UpdateTextEvent(value = text)
222 wx.PostEvent(self._wxComponent, evt)
aca310e5 223
1f780e48
RD
224 def ErrCall(self, text):
225 evt = UpdateErrorEvent(value = text)
226 wx.PostEvent(self._wxComponent, evt)
aca310e5 227
1f780e48
RD
228 def Execute(self, arguments, startIn=None, environment=None):
229 if not startIn:
230 startIn = str(os.getcwd())
231 startIn = os.path.abspath(startIn)
aca310e5
RD
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"
1f780e48
RD
239 self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment)
240 # Kick off threads to read stdout and stderr and write them
aca310e5 241 # to our text control.
1f780e48
RD
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()
aca310e5 246
1f780e48 247 def DoStopExecution(self):
aca310e5 248 # See comment on PythonDebuggerUI.StopExecution
1f780e48 249 if(self._process != None):
1f780e48 250 self._stdOutReader.AskToStop()
1f780e48 251 self._stdErrReader.AskToStop()
26ee3a06
RD
252 try:
253 self._process.kill(gracePeriod=2.0)
254 except:
255 pass
256 self._process = None
aca310e5
RD
257
258 def GetExecPath(self):
259 return self._path
260
1f780e48 261class RunCommandUI(wx.Panel):
26ee3a06 262 runners = []
aca310e5 263
26ee3a06 264 def ShutdownAllRunners():
aca310e5 265 # See comment on PythonDebuggerUI.StopExecution
26ee3a06
RD
266 for runner in RunCommandUI.runners:
267 try:
268 runner.StopExecution(None)
269 except wx._core.PyDeadObjectError:
270 pass
aca310e5 271 RunCommandUI.runners = []
26ee3a06 272 ShutdownAllRunners = staticmethod(ShutdownAllRunners)
aca310e5 273
1f780e48
RD
274 def __init__(self, parent, id, fileName):
275 wx.Panel.__init__(self, parent, id)
276 self._noteBook = parent
aca310e5 277
26ee3a06 278 threading._VERBOSE = _VERBOSE
aca310e5 279
1f780e48
RD
280 self.KILL_PROCESS_ID = wx.NewId()
281 self.CLOSE_TAB_ID = wx.NewId()
aca310e5
RD
282
283
1f780e48
RD
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))
26ee3a06 288 sizer.Add(tb, 0, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL, 1)
1f780e48
RD
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)
aca310e5 293
1f780e48
RD
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)
aca310e5 297
1f780e48
RD
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()
aca310e5
RD
310
311 wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
1f780e48
RD
312
313 self.SetSizer(sizer)
314 sizer.Fit(self)
aca310e5 315
26ee3a06 316 self._stopped = False
1f780e48
RD
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)
aca310e5 321
26ee3a06 322 RunCommandUI.runners.append(self)
aca310e5 323
1f780e48 324 def __del__(self):
aca310e5 325 # See comment on PythonDebuggerUI.StopExecution
1f780e48 326 self._executor.DoStopExecution()
aca310e5
RD
327
328 def Execute(self, initialArgs, startIn, environment, onWebServer = False):
1f780e48 329 self._executor.Execute(initialArgs, startIn, environment)
aca310e5 330
1f780e48
RD
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
aca310e5 340
1f780e48 341 def StopExecution(self):
26ee3a06
RD
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()
aca310e5 347
1f780e48
RD
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)
aca310e5 353
1f780e48
RD
354 def AppendErrorText(self, event):
355 self._textCtrl.SetReadOnly(False)
aca310e5 356 self._textCtrl.SetFontColor(wx.RED)
1f780e48
RD
357 self._textCtrl.StyleClearAll()
358 self._textCtrl.AddText(event.value)
359 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
aca310e5 360 self._textCtrl.SetFontColor(wx.BLACK)
1f780e48
RD
361 self._textCtrl.StyleClearAll()
362 self._textCtrl.SetReadOnly(True)
02b800ce
RD
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)
aca310e5 370
1f780e48
RD
371 #------------------------------------------------------------------------------
372 # Event handling
373 #-----------------------------------------------------------------------------
aca310e5 374
1f780e48
RD
375 def OnToolClicked(self, event):
376 id = event.GetId()
aca310e5 377
1f780e48 378 if id == self.KILL_PROCESS_ID:
26ee3a06 379 self.StopExecution()
aca310e5 380
1f780e48 381 elif id == self.CLOSE_TAB_ID:
02b800ce 382 self.StopAndRemoveUI(event)
aca310e5 383
1f780e48
RD
384 def OnDoubleClick(self, event):
385 # Looking for a stack trace line.
386 lineText, pos = self._textCtrl.GetCurLine()
387 fileBegin = lineText.find("File \"")
aca310e5
RD
388 fileEnd = lineText.find("\", line ")
389 lineEnd = lineText.find(", in ")
1f780e48
RD
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 \"")
aca310e5
RD
397 fileEnd = lineText.find("\", line ")
398 lineEnd = lineText.find(", in ")
1f780e48
RD
399 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
400 return
aca310e5 401
1f780e48
RD
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)
aca310e5
RD
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)
1f780e48 425
1f780e48
RD
426
427DEFAULT_PORT = 32032
aca310e5
RD
428DEFAULT_HOST = 'localhost'
429PORT_COUNT = 21
1f780e48 430
aca310e5 431class BaseDebuggerUI(wx.Panel):
1f780e48 432 debuggers = []
aca310e5 433
1f780e48 434 def NotifyDebuggersOfBreakpointChange():
aca310e5 435 for debugger in BaseDebuggerUI.debuggers:
1f780e48 436 debugger.BreakPointChange()
aca310e5 437
1f780e48 438 NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange)
aca310e5 439
1f780e48 440 def DebuggerRunning():
aca310e5 441 for debugger in BaseDebuggerUI.debuggers:
1f780e48
RD
442 if debugger._executor:
443 return True
444 return False
445 DebuggerRunning = staticmethod(DebuggerRunning)
aca310e5
RD
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
1f780e48 463 def ShutdownAllDebuggers():
aca310e5 464 for debugger in BaseDebuggerUI.debuggers:
26ee3a06
RD
465 try:
466 debugger.StopExecution(None)
467 except wx._core.PyDeadObjectError:
468 pass
aca310e5 469 BaseDebuggerUI.debuggers = []
1f780e48 470 ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
1f780e48 471
aca310e5 472 def __init__(self, parent, id):
1f780e48 473 wx.Panel.__init__(self, parent, id)
1f780e48 474 self._parentNoteBook = parent
aca310e5
RD
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)
1f780e48 485 self._executor = None
aca310e5 486
1f780e48
RD
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))
aca310e5 500
1f780e48
RD
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)
aca310e5 504
1f780e48
RD
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)
aca310e5 508
1f780e48 509 tb.AddSeparator()
aca310e5 510
1f780e48
RD
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)
aca310e5 514
1f780e48 515 tb.AddSeparator()
aca310e5 516
1f780e48
RD
517 continue_bmp = getContinueBitmap()
518 tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution"))
519 wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue)
aca310e5
RD
520 self.Bind(EVT_DEBUG_INTERNAL, self.OnContinue)
521
1f780e48 522 tb.AddSeparator()
1f780e48
RD
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)
aca310e5 526
1f780e48
RD
527 step_bmp = getStepInBitmap()
528 tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in"))
529 wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep)
aca310e5 530
1f780e48
RD
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()
aca310e5 541
1f780e48
RD
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)
aca310e5
RD
545
546 self._toolEnabled = True
1f780e48
RD
547 self.framesTab = None
548 self.DisableWhileDebuggerRunning()
6f1a3f9c
RD
549 self.framesTab = self.MakeFramesUI(self, wx.NewId(), None)
550 sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
1f780e48
RD
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)
1f780e48 554 self.SetStatusText("Starting debug...")
1f780e48 555 self.SetSizer(sizer)
6f1a3f9c 556 tb.Realize()
1f780e48 557 sizer.Fit(self)
aca310e5 558
1f780e48
RD
559 def OnSingleStep(self, event):
560 self._callback.SingleStep()
561
562 def OnContinue(self, event):
563 self._callback.Continue()
aca310e5 564
1f780e48
RD
565 def OnStepOut(self, event):
566 self._callback.Return()
aca310e5 567
1f780e48
RD
568 def OnNext(self, event):
569 self._callback.Next()
570
571 def BreakPointChange(self):
572 if not self._stopped:
aca310e5 573 self._callback.PushBreakpoints()
6f1a3f9c 574 self.framesTab.PopulateBPList()
aca310e5 575
1f780e48 576 def __del__(self):
aca310e5
RD
577 # See comment on PythonDebuggerUI.StopExecution
578 self.StopExecution(None)
579
1f780e48 580 def DisableWhileDebuggerRunning(self):
aca310e5
RD
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
1f780e48
RD
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)
aca310e5
RD
603 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
604 self._tb.EnableTool(self.KILL_PROCESS_ID, True)
605
1f780e48
RD
606 if _WATCHES_ON:
607 self._tb.EnableTool(self.ADD_WATCH_ID, True)
aca310e5
RD
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):
1f780e48 618 if _VERBOSE: print "In ExectorFinished"
aca310e5 619 try:
1f780e48
RD
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
aca310e5
RD
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"
1f780e48 646
2eeaec19 647 def SynchCurrentLine(self, filename, lineNum, noArrow=False):
1f780e48 648 self.DeleteCurrentLineMarkers()
aca310e5 649
1f780e48
RD
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
aca310e5 664
1f780e48
RD
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)
aca310e5
RD
676
677 if not noArrow:
2eeaec19 678 foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
1f780e48
RD
679
680 def DeleteCurrentLineMarkers(self):
681 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
aca310e5
RD
682 for openDoc in openDocs:
683 if(isinstance(openDoc, CodeEditor.CodeDocument)):
684 openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
1f780e48
RD
685
686 def StopAndRemoveUI(self, event):
687 self.StopExecution(None)
aca310e5
RD
688 if self in BaseDebuggerUI.debuggers:
689 BaseDebuggerUI.debuggers.remove(self)
1f780e48
RD
690 index = self._parentNoteBook.GetSelection()
691 self._parentNoteBook.GetPage(index).Show(False)
aca310e5 692 self._parentNoteBook.RemovePage(index)
1f780e48
RD
693
694 def OnAddWatch(self, event):
695 if self.framesTab:
696 self.framesTab.OnWatch(event)
aca310e5 697
6f1a3f9c 698 def MakeFramesUI(self, parent, id, debugger):
aca310e5
RD
699 assert False, "MakeFramesUI not overridden"
700
1f780e48 701 def AppendText(self, event):
6f1a3f9c 702 self.framesTab.AppendText(event.value)
aca310e5 703
1f780e48 704 def AppendErrorText(self, event):
6f1a3f9c 705 self.framesTab.AppendErrorText(event.value)
aca310e5 706
6f1a3f9c 707 def OnClearOutput(self, event):
26ee3a06 708 self.framesTab.ClearOutput(None)
6f1a3f9c
RD
709
710 def SwitchToOutputTab(self):
711 self.framesTab.SwitchToOutputTab()
aca310e5
RD
712
713
714class 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
907class 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
1f780e48
RD
1038class 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)
1f780e48
RD
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)
aca310e5
RD
1051 self._bpListCtrl.InsertColumn(0, "File")
1052 self._bpListCtrl.InsertColumn(1, "Line")
1053 self._bpListCtrl.InsertColumn(2, "Path")
1f780e48
RD
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)
aca310e5 1060
6f1a3f9c
RD
1061 def OnLeftDoubleClick(event):
1062 self.SyncBPLine(event)
aca310e5 1063
6f1a3f9c 1064 wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick)
1f780e48
RD
1065
1066 self.PopulateBPList()
1067
1068 p1.SetSizer(sizer)
1069 sizer.Fit(p1)
1070 p1.Layout()
aca310e5 1071
1f780e48
RD
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)
aca310e5 1086
1f780e48
RD
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()
aca310e5 1101 self._ui.SynchCurrentLine( fileName, int(lineNumber) , noArrow=True)
1f780e48
RD
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()
aca310e5
RD
1108 wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName )
1109
1f780e48
RD
1110 def ListItemSelected(self, event):
1111 self.currentItem = event.m_itemIndex
1112
1113 def ListItemDeselected(self, event):
1114 self.currentItem = -1
aca310e5 1115
1f780e48
RD
1116class Watch:
1117 CODE_ALL_FRAMES = 1
1118 CODE_THIS_BLOCK = 2
1119 CODE_THIS_LINE = 4
1120 CODE_RUN_ONCE = 8
aca310e5 1121
1f780e48
RD
1122 def __init__(self, name, command, show_code=CODE_ALL_FRAMES):
1123 self._name = name
aca310e5 1124 self._command = command
1f780e48 1125 self._show_code = show_code
aca310e5 1126
1f780e48
RD
1127class 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
02b800ce 1141 self._okButton = wx.Button(self, wx.ID_OK, "OK")
1f780e48
RD
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)
aca310e5 1153
02b800ce 1154 self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
1f780e48 1155 self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
aca310e5 1156
1f780e48
RD
1157 self.__set_properties()
1158 self.__do_layout()
aca310e5 1159
1f780e48
RD
1160 def GetSettings(self):
1161 return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce()
aca310e5 1162
1f780e48
RD
1163 def GetSendFrame(self):
1164 return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection())
aca310e5 1165
1f780e48
RD
1166 def GetRunOnce(self):
1167 return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection())
aca310e5 1168
1f780e48
RD
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)
aca310e5 1188
1f780e48
RD
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)
1f780e48
RD
1193 self.SetSizer(sizer_1)
1194 self.Layout()
aca310e5
RD
1195
1196class BaseFramesUI(wx.SplitterWindow):
1f780e48
RD
1197 def __init__(self, parent, id, ui):
1198 wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
1199 self._ui = ui
1f780e48 1200 self._p1 = p1 = wx.ScrolledWindow(self, -1)
1f780e48 1201
6f1a3f9c
RD
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)
aca310e5 1205
6f1a3f9c
RD
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)
1f780e48
RD
1210
1211 sizer2 = wx.BoxSizer(wx.VERTICAL)
6f1a3f9c 1212 p1.SetSizer(sizer2)
6f1a3f9c 1213 self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
1f780e48 1214 self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
6f1a3f9c
RD
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)
aca310e5 1217 tree = self._treeCtrl
1f780e48
RD
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")
aca310e5 1224 tree.SetPyData(self._root, "root")
1f780e48 1225 tree.SetItemText(self._root, "", 1)
6f1a3f9c 1226 tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback)
6f1a3f9c
RD
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())
26ee3a06 1235 self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
6f1a3f9c
RD
1236 self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
1237 self._notebook.AddPage(self.consoleTab, "Output")
26ee3a06 1238 self._notebook.AddPage(self.inspectConsoleTab, "Interact")
6f1a3f9c 1239 self._notebook.AddPage(self.breakPointsTab, "Break Points")
1f780e48 1240 self.SetMinimumPaneSize(20)
6f1a3f9c 1241 self.SplitVertically(p1, p2, 550)
1f780e48 1242 self.currentItem = None
6f1a3f9c 1243 self._notebook.Show(True)
aca310e5 1244
6f1a3f9c
RD
1245 def PopulateBPList(self):
1246 self.breakPointsTab.PopulateBPList()
aca310e5 1247
6f1a3f9c
RD
1248 def OnSize(self, event):
1249 self._notebook.SetSize(self._p2.GetSize())
aca310e5
RD
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
6f1a3f9c
RD
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()
aca310e5
RD
1307 wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
1308
6f1a3f9c
RD
1309 panel.SetSizer(sizer)
1310 #sizer.Fit(panel)
1311
1312 return panel
02b800ce 1313 def ExecuteCommand(self, command):
aca310e5
RD
1314 assert False, "ExecuteCommand not overridden"
1315
6f1a3f9c 1316 def MakeInspectConsoleTab(self, parent, id):
aca310e5
RD
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
26ee3a06
RD
1333 def OnKeyPressed(event):
1334 key = event.KeyCode()
aca310e5
RD
1335 if key == wx.WXK_RETURN:
1336 handleCommand()
26ee3a06 1337 elif key == wx.WXK_UP:
aca310e5 1338 if len(self._cmdList) < 1 or self._cmdIndex < 1:
26ee3a06 1339 return
aca310e5
RD
1340
1341 self._cmdInput.Clear()
1342 self._cmdInput.AppendText(self._cmdList[self._cmdIndex - 1])
1343 self._cmdIndex = self._cmdIndex - 1
26ee3a06 1344 elif key == wx.WXK_DOWN:
aca310e5 1345 if len(self._cmdList) < 1 or self._cmdIndex >= len(self._cmdList):
26ee3a06 1346 return
26ee3a06 1347
aca310e5
RD
1348 self._cmdInput.Clear()
1349 self._cmdInput.AppendText(self._cmdList[self._cmdIndex - 1])
1350 self._cmdIndex = self._cmdIndex + 1
6f1a3f9c 1351 else:
aca310e5
RD
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
6f1a3f9c
RD
1391 def MakeBreakPointsTab(self, parent, id):
1392 panel = BreakpointsUI(parent, id, self._ui)
1393 return panel
aca310e5
RD
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
1457class 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
1603class 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
1f780e48
RD
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()
1f780e48
RD
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)
02b800ce
RD
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
1f780e48
RD
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
aca310e5 1646
1f780e48
RD
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
aca310e5 1658
1f780e48
RD
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()
aca310e5 1664
02b800ce
RD
1665 def OnSendToInteract(self, event):
1666 value = ""
1667 prevItem = ""
1668 for item in self._parentChain:
aca310e5 1669
02b800ce
RD
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
02b800ce 1681 self.ExecuteCommand(value)
aca310e5 1682
1f780e48
RD
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)
02b800ce 1689 wd.CenterOnParent()
1f780e48
RD
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)]
aca310e5 1694 message = frameNode.getAttribute("message")
1f780e48
RD
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")
02b800ce 1703 wd.Destroy()
1f780e48
RD
1704 except:
1705 tp, val, tb = sys.exc_info()
aca310e5
RD
1706 traceback.print_exception(tp, val, tb)
1707
1f780e48
RD
1708 def OnIntrospect(self, event):
1709 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1710
1711 try:
aca310e5
RD
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))
1f780e48
RD
1737
1738 def OnSyncFrame(self, event):
6f1a3f9c 1739 list = self._framesChoiceCtrl
1f780e48
RD
1740 frameNode = self._stack[int(self.currentItem)]
1741 file = frameNode.getAttribute("file")
1742 line = frameNode.getAttribute("line")
aca310e5 1743 self._ui.SynchCurrentLine( file, int(line) )
26ee3a06 1744
aca310e5
RD
1745 def LoadFramesList(self, framesXML):
1746 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1f780e48 1747 try:
aca310e5
RD
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()
1f780e48 1773 frameNode = nodeList.item(index)
aca310e5
RD
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)
26ee3a06 1780
aca310e5
RD
1781 finally:
1782 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
6f1a3f9c 1783
1f780e48 1784
1f780e48 1785 def ListItemSelected(self, event):
26ee3a06
RD
1786 self.PopulateTreeFromFrameMessage(event.GetString())
1787 self.OnSyncFrame(None)
aca310e5
RD
1788
1789 def PopulateTreeFromFrameMessage(self, message):
6f1a3f9c
RD
1790 index = 0
1791 for node in self._stack:
1792 if node.getAttribute("message") == message:
26ee3a06
RD
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')
6f1a3f9c 1797 self.currentItem = index
26ee3a06
RD
1798 if len(nodeList):
1799 self.PopulateTreeFromFrameNode(nodeList[0])
6f1a3f9c
RD
1800 return
1801 index = index + 1
aca310e5 1802
1f780e48 1803 def PopulateTreeFromFrameNode(self, frameNode):
6f1a3f9c
RD
1804 list = self._framesChoiceCtrl
1805 list.Enable(True)
aca310e5 1806 tree = self._treeCtrl
6f1a3f9c 1807 #tree.Show(True)
aca310e5 1808 root = self._root
1f780e48
RD
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)
26ee3a06
RD
1818 if firstChild:
1819 tree.Expand(firstChild)
1f780e48 1820 self._p2.FitInside()
aca310e5 1821
6f1a3f9c 1822 def IntrospectCallback(self, event):
aca310e5 1823 tree = self._treeCtrl
6f1a3f9c
RD
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()
aca310e5 1834
1f780e48 1835 def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None):
aca310e5 1836 tree = self._treeCtrl
1f780e48
RD
1837 if insertBefore != None:
1838 treeNode = tree.InsertItem(parent, insertBefore, name)
aca310e5 1839 else:
1f780e48
RD
1840 treeNode = tree.AppendItem(parent, name)
1841 children = node.childNodes
6f1a3f9c 1842 intro = node.getAttribute('intro')
aca310e5 1843
6f1a3f9c
RD
1844 if intro == "True":
1845 tree.SetItemHasChildren(treeNode, True)
1846 tree.SetPyData(treeNode, "Introspect")
1847 if node.getAttribute("value"):
1f780e48
RD
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):
aca310e5 1852 self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode)
1f780e48
RD
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)
6f1a3f9c
RD
1858 intro = subNode.getAttribute('intro')
1859 if intro == "True":
1860 tree.SetItemHasChildren(n, True)
1861 tree.SetPyData(n, "Introspect")
02b800ce
RD
1862 if name.find('[') == -1:
1863 self._treeCtrl.SortChildren(treeNode)
1f780e48 1864 return treeNode
aca310e5 1865
1f780e48
RD
1866 def StripOuterSingleQuotes(self, string):
1867 if string.startswith("'") and string.endswith("'"):
6f1a3f9c
RD
1868 retval = string[1:-1]
1869 elif string.startswith("\"") and string.endswith("\""):
1870 retval = string[1:-1]
1f780e48 1871 else:
aca310e5
RD
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
6f1a3f9c 1884
1f780e48 1885class DebuggerView(Service.ServiceView):
aca310e5 1886
1f780e48
RD
1887 #----------------------------------------------------------------------------
1888 # Overridden methods
1889 #----------------------------------------------------------------------------
1890
1891 def __init__(self, service):
1892 Service.ServiceView.__init__(self, service)
aca310e5 1893
1f780e48
RD
1894 def _CreateControl(self, parent, id):
1895 return None
aca310e5 1896
1f780e48
RD
1897 #------------------------------------------------------------------------------
1898 # Event handling
1899 #-----------------------------------------------------------------------------
aca310e5 1900
1f780e48
RD
1901 def OnToolClicked(self, event):
1902 self.GetFrame().ProcessEvent(event)
26ee3a06 1903
1f780e48
RD
1904 #------------------------------------------------------------------------------
1905 # Class methods
1906 #-----------------------------------------------------------------------------
1907
1908class 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
aca310e5 1914
1f780e48
RD
1915 def getFramesXML(self):
1916 return self._framesXML
aca310e5 1917
1f780e48
RD
1918 def getMessage(self):
1919 return self._message
aca310e5 1920
1f780e48
RD
1921 def getInfo(self):
1922 return self._info
aca310e5 1923
1f780e48 1924 def getQuit(self):
aca310e5
RD
1925 return self._quit
1926
1f780e48
RD
1927class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
1928 def __init__(self, address, logRequests=0):
aca310e5
RD
1929 SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests)
1930
1f780e48
RD
1931class 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())
aca310e5 1942
1f780e48
RD
1943 def run(self):
1944 while self._keepGoing:
1945 try:
aca310e5 1946 self._server.handle_request()
1f780e48
RD
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."
aca310e5 1952
1f780e48
RD
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 ""
aca310e5 1958
1f780e48
RD
1959 def quit(self):
1960 interaction = Interaction(None, None, info=None, quit=True)
1961 self._queue.put(interaction)
1962 return ""
aca310e5 1963
1f780e48
RD
1964 def dummyOperation(self):
1965 return ""
aca310e5 1966
1f780e48
RD
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
1982class 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
aca310e5 1991
1f780e48
RD
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
2009class DebuggerOperationThread(threading.Thread):
2010 def __init__(self, function):
2011 threading.Thread.__init__(self)
2012 self._function = function
aca310e5 2013
1f780e48
RD
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)
aca310e5
RD
2021 if _VERBOSE:
2022 print "In DOT, after call"
2023
2024class 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"
1f780e48 2049
aca310e5
RD
2050class PythonDebuggerCallback(BaseDebuggerCallback):
2051
2052 def __init__(self, host, port, debugger_url, break_url, debuggerUI, autoContinue=False):
1f780e48 2053 if _VERBOSE: print "+++++++ Creating server on port, ", str(port)
aca310e5 2054 self._timer = None
1f780e48
RD
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))
aca310e5 2060
1f780e48
RD
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
aca310e5
RD
2070 self._autoContinue = autoContinue
2071
2072 def Start(self):
1f780e48 2073 self._serverHandlerThread.start()
aca310e5 2074
26ee3a06
RD
2075 def ShutdownServer(self):
2076 #rbt = RequestBreakThread(self._breakServer, kill=True)
2077 #rbt.start()
aca310e5 2078 self._waiting = False
1f780e48
RD
2079 if self._serverHandlerThread:
2080 self._serverHandlerThread.AskToStop()
2081 self._serverHandlerThread = None
aca310e5 2082
1f780e48
RD
2083 def BreakExecution(self):
2084 rbt = RequestBreakThread(self._breakServer, interrupt=True)
2085 rbt.start()
aca310e5 2086
1f780e48
RD
2087 def SingleStep(self):
2088 self._debuggerUI.DisableWhileDebuggerRunning()
1f780e48 2089 self._debuggerServer.set_step() # Figure out where to set allowNone
aca310e5 2090 self.WaitForRPC()
1f780e48
RD
2091
2092 def Next(self):
2093 self._debuggerUI.DisableWhileDebuggerRunning()
1f780e48 2094 self._debuggerServer.set_next()
aca310e5
RD
2095 self.WaitForRPC()
2096
1f780e48
RD
2097 def Continue(self):
2098 self._debuggerUI.DisableWhileDebuggerRunning()
1f780e48 2099 self._debuggerServer.set_continue()
aca310e5
RD
2100 self.WaitForRPC()
2101
1f780e48
RD
2102 def Return(self):
2103 self._debuggerUI.DisableWhileDebuggerRunning()
1f780e48 2104 self._debuggerServer.set_return()
aca310e5
RD
2105 self.WaitForRPC()
2106
2107 def ReadQueue(self):
1f780e48
RD
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)
aca310e5 2115 self.interaction(item.getMessage().data, data, item.getInfo(), False)
1f780e48
RD
2116 except Queue.Empty:
2117 pass
aca310e5
RD
2118
2119 def PushBreakpoints(self):
1f780e48
RD
2120 rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict())
2121 rbt.start()
2122
aca310e5
RD
2123
2124 def WaitForRPC(self):
2125 self._waiting = True
2126 while self._waiting:
1f780e48 2127 try:
aca310e5 2128 self.ReadQueue()
1f780e48
RD
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)
aca310e5
RD
2135 if _VERBOSE: print "Exiting WaitForRPC."
2136
1f780e48 2137 def interaction(self, message, frameXML, info, quit):
aca310e5 2138
1f780e48
RD
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)
aca310e5
RD
2144 self.PushBreakpoints()
2145 self._waiting = False
1f780e48
RD
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"
aca310e5 2157 #if not self._autoContinue:
1f780e48 2158 self._debuggerUI.SetStatusText(message)
aca310e5
RD
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)
1f780e48 2167 if _VERBOSE: print "+"*40
aca310e5
RD
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
1f780e48
RD
2196class 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()
aca310e5
RD
2205 RUN_LAST_ID = wx.NewId()
2206 DEBUG_LAST_ID = wx.NewId()
bbf7159c 2207 DEBUG_WEBSERVER_ID = wx.NewId()
02b800ce 2208 RUN_WEBSERVER_ID = wx.NewId()
aca310e5
RD
2209 DEBUG_WEBSERVER_CONTINUE_ID = wx.NewId()
2210 DEBUG_WEBSERVER_NOW_RUN_PROJECT_ID = wx.NewId()
1f780e48
RD
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)
aca310e5 2219
1f780e48
RD
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:
26ee3a06
RD
2226 if _VERBOSE:
2227 print "Cannot get long path for %s" % path
aca310e5 2228
1f780e48 2229 return path
aca310e5 2230
1f780e48 2231 ExpandPath = staticmethod(ExpandPath)
aca310e5 2232
1f780e48
RD
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 = {}
aca310e5
RD
2251 self._frame = None
2252 self.projectPath = None
2253 self.fileToDebug = None
2254 self.phpDbgParam = None
2255 self.dbgLanguage = projectmodel.LANGUAGE_DEFAULT
2256
1f780e48
RD
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
aca310e5 2266
1f780e48
RD
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)
aca310e5 2277 self._frame = frame
1f780e48
RD
2278 config = wx.ConfigBase_Get()
2279
2280 debuggerMenu = wx.Menu()
2281 if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS):
aca310e5 2282
1f780e48
RD
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)
aca310e5 2286
1f780e48
RD
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)
aca310e5
RD
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
bbf7159c
RD
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)
02b800ce
RD
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)
aca310e5
RD
2307
2308 frame.Bind(EVT_DEBUG_INTERNAL, frame.ProcessEvent)
1f780e48 2309 debuggerMenu.AppendSeparator()
aca310e5
RD
2310
2311 debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint\tCtrl+B"), _("Toggle a breakpoint"))
1f780e48
RD
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)
aca310e5
RD
2318
2319
1f780e48
RD
2320 viewMenuIndex = menuBar.FindMenu(_("&Project"))
2321 menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run"))
aca310e5 2322
02b800ce 2323 toolBar.AddSeparator()
aca310e5
RD
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"))
02b800ce 2326 toolBar.Realize()
1f780e48
RD
2327
2328 return True
2329
2330
aca310e5 2331
1f780e48
RD
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
aca310e5
RD
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
bbf7159c
RD
2363 elif an_id == DebuggerService.DEBUG_WEBSERVER_ID:
2364 self.OnDebugWebServer(event)
2365 return True
aca310e5
RD
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
02b800ce
RD
2372 elif an_id == DebuggerService.RUN_WEBSERVER_ID:
2373 self.OnRunWebServer(event)
2374 return True
1f780e48 2375 return False
aca310e5 2376
1f780e48
RD
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
b792147d 2389 elif (an_id == DebuggerService.RUN_ID
aca310e5
RD
2390 or an_id == DebuggerService.RUN_LAST_ID
2391 or an_id == DebuggerService.DEBUG_ID
2392 or an_id == DebuggerService.DEBUG_LAST_ID):
1f780e48
RD
2393 event.Enable(self.HasAnyFiles())
2394 return True
2395 else:
2396 return False
2397
2398 #----------------------------------------------------------------------------
2399 # Class Methods
aca310e5
RD
2400 #----------------------------------------------------------------------------
2401
2402 def OnDebugProject(self, event, showDialog=True):
b792147d
RD
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
1f780e48
RD
2406 if not Executor.GetPythonExecutablePath():
2407 return
aca310e5 2408 if BaseDebuggerUI.DebuggerRunning():
1f780e48
RD
2409 wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
2410 return
aca310e5
RD
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
1f780e48
RD
2417 self.ShowWindow(True)
2418 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
bbf7159c 2419 try:
aca310e5 2420 dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug File', projectService, None, okButtonName="Debug", debugging=True)
bbf7159c
RD
2421 except:
2422 return
02b800ce 2423 dlg.CenterOnParent()
aca310e5
RD
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:
02b800ce 2429 projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
1f780e48
RD
2430 else:
2431 dlg.Destroy()
2432 return
aca310e5 2433 dlg.Destroy()
1f780e48 2434 self.PromptToSaveFiles()
1f780e48
RD
2435 shortFile = os.path.basename(fileToDebug)
2436 fileToDebug = DebuggerService.ExpandPath(fileToDebug)
aca310e5
RD
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)
1f780e48 2468 count = Service.ServiceView.bottomTab.GetPageCount()
bbf7159c 2469 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile)
1f780e48 2470 Service.ServiceView.bottomTab.SetSelection(count)
aca310e5
RD
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
1f780e48 2489 page.Execute(initialArgs, startIn, environment)
aca310e5
RD
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"
6f1a3f9c
RD
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
aca310e5 2530 if BaseDebuggerUI.DebuggerRunning():
6f1a3f9c
RD
2531 wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
2532 return
bbf7159c
RD
2533 import WebServerService
2534 wsService = wx.GetApp().GetService(WebServerService.WebServerService)
2535 fileName, args = wsService.StopAndPrepareToDebug()
aca310e5
RD
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
bbf7159c 2542 try:
aca310e5
RD
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
bbf7159c
RD
2548 count = Service.ServiceView.bottomTab.GetPageCount()
2549 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: Internal WebServer"))
2550 Service.ServiceView.bottomTab.SetSelection(count)
aca310e5 2551 page.Execute(args, startIn=sysutilslib.mainModuleDir, environment=os.environ, onWebServer = True)
bbf7159c
RD
2552 except:
2553 pass
aca310e5 2554
02b800ce
RD
2555 def OnRunWebServer(self, event):
2556 if not Executor.GetPythonExecutablePath():
2557 return
2558 import WebServerService
2559 wsService = wx.GetApp().GetService(WebServerService.WebServerService)
aca310e5
RD
2560 wsService.ShutDownAndRestart()
2561
1f780e48
RD
2562 def HasAnyFiles(self):
2563 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2564 return len(docs) > 0
aca310e5 2565
1f780e48
RD
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:
aca310e5
RD
2574 frame = self.GetView().GetFrame()
2575 if running:
1f780e48
RD
2576 yesNoMsg = wx.MessageDialog(frame,
2577 _("Files have been modified.\nWould you like to save all files before running?"),
2578 _("Run"),
b792147d 2579 wx.YES_NO|wx.ICON_QUESTION
1f780e48 2580 )
aca310e5 2581 else:
1f780e48
RD
2582 yesNoMsg = wx.MessageDialog(frame,
2583 _("Files have been modified.\nWould you like to save all files before debugging?"),
2584 _("Debug"),
b792147d 2585 wx.YES_NO|wx.ICON_QUESTION
1f780e48 2586 )
02b800ce 2587 yesNoMsg.CenterOnParent()
1f780e48
RD
2588 if yesNoMsg.ShowModal() == wx.ID_YES:
2589 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2590 for doc in docs:
2591 doc.Save()
02b800ce 2592 yesNoMsg.Destroy()
1f780e48
RD
2593
2594 def OnExit(self):
aca310e5 2595 BaseDebuggerUI.ShutdownAllDebuggers()
26ee3a06 2596 RunCommandUI.ShutdownAllRunners()
aca310e5
RD
2597
2598 def OnRunProject(self, event, showDialog=True):
b792147d
RD
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
1f780e48
RD
2602 if not Executor.GetPythonExecutablePath():
2603 return
2604 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
bbf7159c
RD
2605 try:
2606 dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None)
2607 except:
2608 return
02b800ce 2609 dlg.CenterOnParent()
aca310e5
RD
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:
02b800ce 2615 projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
1f780e48
RD
2616 else:
2617 dlg.Destroy()
2618 return
aca310e5 2619 dlg.Destroy()
1f780e48 2620 self.PromptToSaveFiles()
aca310e5 2621 if fileToRun.endswith('bpel'):
02b800ce
RD
2622 projects = projectService.FindProjectByFile(projectPath)
2623 if not projects:
2624 return
2625 project = projects[0]
aca310e5
RD
2626 try:
2627 deployFilePath = project.GenerateDeployment()
2628 except ProjectEditor.DataServiceExistenceException, e:
2629 dataSourceName = str(e)
2630 projectService.PromptForMissingDataSource(dataSourceName)
2631 return
02b800ce 2632 projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath)
1f780e48 2633 return
aca310e5 2634
1f780e48
RD
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)
aca310e5 2641 page.Execute(initialArgs, startIn, environment, onWebServer = True)
1f780e48
RD
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()
02b800ce
RD
2652 else:
2653 view = None
1f780e48
RD
2654 if self.BreakpointSet(fileName, line + 1):
2655 self.ClearBreak(fileName, line + 1)
02b800ce
RD
2656 if view:
2657 view.GetCtrl().Refresh()
1f780e48
RD
2658 else:
2659 self.SetBreak(fileName, line + 1)
02b800ce
RD
2660 if view:
2661 view.GetCtrl().Refresh()
1f780e48
RD
2662 # Now refresh all the markers icons in all the open views.
2663 self.ClearAllBreakpointMarkers()
aca310e5
RD
2664 self.SetAllBreakpointMarkers()
2665
1f780e48
RD
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)
aca310e5 2676
1f780e48
RD
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]
aca310e5 2683 # If we're already debugging, pass this bp off to the PythonDebuggerCallback
1f780e48 2684 self.NotifyDebuggersOfBreakpointChange()
aca310e5 2685
1f780e48 2686 def NotifyDebuggersOfBreakpointChange(self):
aca310e5
RD
2687 BaseDebuggerUI.NotifyDebuggersOfBreakpointChange()
2688
1f780e48
RD
2689 def GetBreakpointList(self, fileName):
2690 expandedName = DebuggerService.ExpandPath(fileName)
2691 if not self._masterBPDict.has_key(expandedName):
2692 return []
2693 else:
aca310e5 2694 return self._masterBPDict[expandedName]
1f780e48 2695
02b800ce
RD
2696 def SetBreakpointList(self, fileName, bplist):
2697 expandedName = DebuggerService.ExpandPath(fileName)
2698 self._masterBPDict[expandedName] = bplist
aca310e5 2699
1f780e48
RD
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
aca310e5 2710
1f780e48
RD
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()
aca310e5 2723
1f780e48
RD
2724 def HasBreakpointsSet(self):
2725 for key, value in self._masterBPDict.items():
2726 if len(value) > 0:
2727 return True
2728 return False
aca310e5 2729
1f780e48
RD
2730 def ClearAllBreakpoints(self):
2731 self._masterBPDict = {}
2732 self.NotifyDebuggersOfBreakpointChange()
2733 self.ClearAllBreakpointMarkers()
aca310e5 2734
1f780e48
RD
2735 def ClearAllBreakpointMarkers(self):
2736 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
aca310e5
RD
2737 for openDoc in openDocs:
2738 if isinstance(openDoc, CodeEditor.CodeDocument):
2739 openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2740
02b800ce
RD
2741 def UpdateBreakpointsFromMarkers(self, view, fileName):
2742 newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2743 self.SetBreakpointList(fileName, newbpLines)
aca310e5 2744
1f780e48
RD
2745 def GetMasterBreakpointDict(self):
2746 return self._masterBPDict
aca310e5 2747
1f780e48
RD
2748 def SetAllBreakpointMarkers(self):
2749 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
aca310e5
RD
2750 for openDoc in openDocs:
2751 if(isinstance(openDoc, CodeEditor.CodeDocument)):
1f780e48 2752 self.SetCurrentBreakpointMarkers(openDoc.GetFirstView())
aca310e5 2753
1f780e48
RD
2754 def SetCurrentBreakpointMarkers(self, view):
2755 if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'):
2756 view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
aca310e5 2757 for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()):
1f780e48
RD
2758 view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2759
aca310e5
RD
2760 def GetPhpDbgParam(self):
2761 return self.phpDbgParam
2762
2763 def SetPhpDbgParam(self, value = None):
2764 self.phpDbgParam = value
2765
1f780e48
RD
2766class 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:"))
aca310e5 2776 dashStaticText = wx.StaticText(self, -1, _("through to"))
1f780e48
RD
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)
aca310e5 2799
1f780e48
RD
2800 debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE)
2801 self.SetSizer(debuggerPanelBorderSizer)
2802 self.Layout()
2803 parent.AddPage(self, _("Debugger"))
aca310e5 2804
1f780e48
RD
2805 def FlushPorts(self, event):
2806 if self._PortNumberTextCtrl.IsInBounds():
2807 config = wx.ConfigBase_Get()
2808 config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
aca310e5 2809 PythonDebuggerUI.NewPortRange()
1f780e48
RD
2810 else:
2811 wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
aca310e5 2812
1f780e48
RD
2813 def MinPortChange(self, event):
2814 self._EndPortNumberTextCtrl.Enable( True )
2815 self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT)
2816 self._EndPortNumberTextCtrl.Enable( False )
aca310e5 2817
1f780e48
RD
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())
aca310e5 2823
02b800ce
RD
2824
2825 def GetIcon(self):
2826 return getContinueIcon()
2827
1f780e48
RD
2828
2829class CommandPropertiesDialog(wx.Dialog):
aca310e5 2830 def __init__(self, parent, title, projectService, currentProjectDocument, okButtonName="Run", debugging=False):
1f780e48
RD
2831 self._projService = projectService
2832 self._pmext = None
aca310e5
RD
2833 self._pyext = '.py'
2834 self._phpext = '.php'
1f780e48
RD
2835 for template in self._projService.GetDocumentManager().GetTemplates():
2836 if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
2837 self._pmext = template.GetDefaultExtension()
aca310e5
RD
2838 break
2839 self._currentProj = projectService.GetCurrentProject()
bbf7159c
RD
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"))
aca310e5 2843 raise Exception("Nothing to Run or Debug.")
02b800ce
RD
2844
2845 wx.Dialog.__init__(self, parent, -1, title)
aca310e5
RD
2846
2847 projStaticText = wx.StaticText(self, -1, _("Project:"))
2848 fileStaticText = wx.StaticText(self, -1, _("File:"))
2849 argsStaticText = wx.StaticText(self, -1, _("Arguments:"))
1f780e48
RD
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)
02b800ce 2854 self._projList = wx.Choice(self, -1, choices=self._projectNameList)
1f780e48
RD
2855 self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList)
2856 HALF_SPACE = 5
02b800ce
RD
2857 GAP = HALF_SPACE
2858 if wx.Platform == "__WXMAC__":
2859 GAP = 10
2860 flexGridSizer = wx.GridBagSizer(GAP, GAP)
aca310e5 2861
02b800ce
RD
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)
aca310e5 2864
02b800ce
RD
2865 flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2866 self._fileList = wx.Choice(self, -1)
1f780e48 2867 self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList)
02b800ce 2868 flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND)
aca310e5 2869
1f780e48 2870 config = wx.ConfigBase_Get()
aca310e5 2871 self._lastArguments = config.Read(self.GetKey("LastRunArguments"))
1f780e48
RD
2872 self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments))
2873 self._argsEntry.SetToolTipString(str(self._lastArguments))
1f780e48 2874
02b800ce
RD
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)
aca310e5 2877
02b800ce 2878 flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
aca310e5 2879 self._lastStartIn = config.Read(self.GetKey("LastRunStartIn"))
1f780e48
RD
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)
1f780e48 2884
02b800ce 2885 flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND)
b792147d 2886 self._findDir = wx.Button(self, -1, _("Browse..."))
1f780e48 2887 self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir)
02b800ce 2888 flexGridSizer.Add(self._findDir, (3,2))
aca310e5 2889
02b800ce 2890 flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
1f780e48
RD
2891 if os.environ.has_key('PYTHONPATH'):
2892 startval = os.environ['PYTHONPATH']
2893 else:
2894 startval = ""
aca310e5 2895 self._lastPythonPath = config.Read(self.GetKey("LastPythonPath"), startval)
1f780e48
RD
2896 self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath)
2897 self._pythonPathEntry.SetToolTipString(self._lastPythonPath)
02b800ce 2898 flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND)
aca310e5 2899
2eeaec19 2900 if debugging and _WINDOWS:
1f780e48 2901 self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText)
aca310e5 2902 checked = bool(config.ReadInt(self.GetKey("PythonPathPostpend"), 1))
1f780e48 2903 self._postpendCheckBox.SetValue(checked)
02b800ce
RD
2904 flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND)
2905 cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10)
aca310e5 2906
02b800ce 2907 box = wx.StdDialogButtonSizer()
b792147d 2908 self._okButton = wx.Button(self, wx.ID_OK, okButtonName)
1f780e48
RD
2909 self._okButton.SetDefault()
2910 self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog"))
02b800ce 2911 box.AddButton(self._okButton)
1f780e48 2912 self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton)
b792147d 2913 btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
1f780e48 2914 btn.SetHelpText(_("The Cancel button cancels the dialog."))
02b800ce
RD
2915 box.AddButton(btn)
2916 box.Realize()
2917 cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5)
aca310e5 2918
1f780e48 2919 self.SetSizer(cpPanelBorderSizer)
aca310e5 2920
1f780e48
RD
2921 # Set up selections based on last values used.
2922 self._fileNameList = None
aca310e5
RD
2923 self._selectedFileIndex = -1
2924 lastProject = config.Read(self.GetKey("LastRunProject"))
2925 lastFile = config.Read(self.GetKey("LastRunFile"))
2926 self._mustShow = not lastFile
1f780e48
RD
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)
02b800ce
RD
2936
2937 cpPanelBorderSizer.Fit(self)
2938
aca310e5
RD
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
1f780e48
RD
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()
aca310e5
RD
2958 config.Write(self.GetKey("LastRunProject"), self._projectNameList[self._selectedProjectIndex])
2959 config.Write(self.GetKey("LastRunFile"), fileToRun)
1f780e48
RD
2960 # Don't update the arguments or starting directory unless we're runing python.
2961 if isPython:
aca310e5
RD
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())
1f780e48 2965 if hasattr(self, "_postpendCheckBox"):
aca310e5 2966 config.WriteInt(self.GetKey("PythonPathPostpend"), int(self._postpendCheckBox.GetValue()))
1f780e48
RD
2967
2968 self.EndModal(wx.ID_OK)
aca310e5
RD
2969
2970 def GetSettings(self):
02b800ce 2971 projectPath = self._selectedProjectDocument.GetFilename()
1f780e48 2972 filename = self._fileNameList[self._selectedFileIndex]
aca310e5 2973 args = self._argsEntry.GetValue()
1f780e48
RD
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()
aca310e5 2985
02b800ce 2986 return projectPath, filename, args, startIn, isPython, env
aca310e5 2987
1f780e48
RD
2988 def OnFileSelected(self, event):
2989 self._selectedFileIndex = self._fileList.GetSelection()
2990 self.EnableForFileType(event.GetString())
aca310e5 2991
1f780e48 2992 def EnableForFileType(self, fileName):
aca310e5 2993 show = fileName.endswith(self._pyext) or fileName.endswith(self._phpext)
1f780e48
RD
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()
aca310e5 3002 self._argsEntry.SetValue("")
1f780e48 3003 else:
aca310e5
RD
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
1f780e48
RD
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
02b800ce 3016 dlg.CenterOnParent()
1f780e48
RD
3017 if dlg.ShowModal() == wx.ID_OK:
3018 self._startEntry.SetValue(dlg.GetPath())
aca310e5
RD
3019
3020 dlg.Destroy()
3021
02b800ce 3022
1f780e48
RD
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)
aca310e5 3029
1f780e48 3030 def FilterFileList(self, list):
aca310e5 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)
1f780e48 3032 return files
aca310e5 3033
1f780e48
RD
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]:
aca310e5
RD
3043 self._selectedFileIndex = index
3044 break
1f780e48
RD
3045 self._fileList.Hide()
3046 self._fileList.AppendItems(strings)
3047 self._fileList.Show()
aca310e5
RD
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
1f780e48
RD
3057 self._fileList.SetSelection(self._selectedFileIndex)
3058 self.EnableForFileType(strings[self._selectedFileIndex])
aca310e5 3059
1f780e48
RD
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
bbf7159c
RD
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
aca310e5 3080
bbf7159c
RD
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())
aca310e5 3086 if type(document) == PythonEditor.PythonDocument or type(document) == PHPEditor.PHPDocument:
bbf7159c
RD
3087 if not AlreadyInProject(document.GetFilename()):
3088 unprojectedFiles.append(document.GetFilename())
aca310e5 3089
bbf7159c
RD
3090 if unprojectedFiles:
3091 unprojProj = ProjectEditor.ProjectDocument()
aca310e5 3092 unprojProj.SetFilename(_("Not in any Project"))
bbf7159c
RD
3093 unprojProj.AddFiles(unprojectedFiles)
3094 docList.append(unprojProj)
aca310e5
RD
3095 nameList.append(_("Not in any Project"))
3096
1f780e48 3097 return nameList, docList, index
aca310e5 3098
bbf7159c 3099
1f780e48
RD
3100#----------------------------------------------------------------------
3101from wx import ImageFromStream, BitmapFromImage
1f780e48 3102import cStringIO
bbf7159c 3103
1f780e48
RD
3104#----------------------------------------------------------------------
3105def getBreakData():
3106 return \
b792147d
RD
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\
31135a\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\
aca310e5 3115\xaeB`\x82'
1f780e48
RD
3116
3117def getBreakBitmap():
3118 return BitmapFromImage(getBreakImage())
3119
3120def getBreakImage():
3121 stream = cStringIO.StringIO(getBreakData())
3122 return ImageFromStream(stream)
3123
3124def getBreakIcon():
bbf7159c 3125 return wx.IconFromBitmap(getBreakBitmap())
1f780e48
RD
3126
3127#----------------------------------------------------------------------
26ee3a06 3128
1f780e48
RD
3129def 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\
26ee3a06
RD
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\
aca310e5 3141\x00IEND\xaeB`\x82'
1f780e48
RD
3142
3143def getClearOutputBitmap():
3144 return BitmapFromImage(getClearOutputImage())
3145
3146def getClearOutputImage():
3147 stream = cStringIO.StringIO(getClearOutputData())
3148 return ImageFromStream(stream)
3149
3150def getClearOutputIcon():
bbf7159c 3151 return wx.IconFromBitmap(getClearOutputBitmap())
1f780e48
RD
3152
3153#----------------------------------------------------------------------
3154def getCloseData():
3155 return \
b792147d
RD
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\
aca310e5 3167\xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82'
1f780e48
RD
3168
3169def getCloseBitmap():
3170 return BitmapFromImage(getCloseImage())
3171
3172def getCloseImage():
3173 stream = cStringIO.StringIO(getCloseData())
3174 return ImageFromStream(stream)
3175
3176def getCloseIcon():
bbf7159c 3177 return wx.IconFromBitmap(getCloseBitmap())
1f780e48
RD
3178
3179#----------------------------------------------------------------------
3180def 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\
26ee3a06
RD
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\
aca310e5 3192\x00\x00\x00\x00IEND\xaeB`\x82'
1f780e48
RD
3193
3194def getContinueBitmap():
3195 return BitmapFromImage(getContinueImage())
3196
3197def getContinueImage():
3198 stream = cStringIO.StringIO(getContinueData())
3199 return ImageFromStream(stream)
3200
3201def getContinueIcon():
bbf7159c 3202 return wx.IconFromBitmap(getContinueBitmap())
1f780e48
RD
3203
3204#----------------------------------------------------------------------
3205def 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\
3211gK\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\
aca310e5 3215`\x82'
1f780e48
RD
3216
3217def getNextBitmap():
3218 return BitmapFromImage(getNextImage())
3219
3220def getNextImage():
3221 stream = cStringIO.StringIO(getNextData())
3222 return ImageFromStream(stream)
3223
3224def getNextIcon():
bbf7159c 3225 return wx.IconFromBitmap(getNextBitmap())
1f780e48
RD
3226
3227#----------------------------------------------------------------------
3228def 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\
aca310e5 3237\x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
1f780e48
RD
3238
3239def getStepInBitmap():
3240 return BitmapFromImage(getStepInImage())
3241
3242def getStepInImage():
3243 stream = cStringIO.StringIO(getStepInData())
3244 return ImageFromStream(stream)
3245
3246def getStepInIcon():
bbf7159c 3247 return wx.IconFromBitmap(getStepInBitmap())
1f780e48
RD
3248
3249#----------------------------------------------------------------------
3250def getStopData():
3251 return \
26ee3a06 3252'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1f780e48 3253\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
26ee3a06
RD
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\
aca310e5 3257\x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
1f780e48
RD
3258
3259def getStopBitmap():
3260 return BitmapFromImage(getStopImage())
3261
3262def getStopImage():
3263 stream = cStringIO.StringIO(getStopData())
3264 return ImageFromStream(stream)
3265
3266def getStopIcon():
bbf7159c 3267 return wx.IconFromBitmap(getStopBitmap())
1f780e48
RD
3268
3269#----------------------------------------------------------------------
3270def 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\
aca310e5 3280\xaeB`\x82"
1f780e48
RD
3281
3282def getStepReturnBitmap():
3283 return BitmapFromImage(getStepReturnImage())
3284
3285def getStepReturnImage():
3286 stream = cStringIO.StringIO(getStepReturnData())
3287 return ImageFromStream(stream)
3288
3289def getStepReturnIcon():
bbf7159c 3290 return wx.IconFromBitmap(getStepReturnBitmap())
aca310e5 3291
bbf7159c 3292#----------------------------------------------------------------------
1f780e48
RD
3293def 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\
aca310e5 3302\x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
1f780e48
RD
3303
3304def getAddWatchBitmap():
3305 return BitmapFromImage(getAddWatchImage())
3306
3307def getAddWatchImage():
3308 stream = cStringIO.StringIO(getAddWatchData())
3309 return ImageFromStream(stream)
3310
3311def getAddWatchIcon():
bbf7159c 3312 return wx.IconFromBitmap(getAddWatchBitmap())
aca310e5 3313
02b800ce
RD
3314#----------------------------------------------------------------------
3315def 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\
3325CF\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\
aca310e5 3334\xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82'
02b800ce
RD
3335
3336def getRunningManBitmap():
3337 return BitmapFromImage(getRunningManImage())
3338
3339def getRunningManImage():
3340 stream = cStringIO.StringIO(getRunningManData())
3341 return ImageFromStream(stream)
3342
3343def getRunningManIcon():
3344 icon = EmptyIcon()
3345 icon.CopyFromBitmap(getRunningManBitmap())
3346 return icon
3347
3348#----------------------------------------------------------------------
3349def 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\
3359f?*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\
aca310e5 3370\xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82'
02b800ce
RD
3371
3372def getDebuggingManBitmap():
3373 return BitmapFromImage(getDebuggingManImage())
3374
3375def getDebuggingManImage():
3376 stream = cStringIO.StringIO(getDebuggingManData())
3377 return ImageFromStream(stream)
3378
3379def getDebuggingManIcon():
3380 icon = EmptyIcon()
3381 icon.CopyFromBitmap(getDebuggingManBitmap())
3382 return icon
3383
3384#----------------------------------------------------------------------
3385