--- /dev/null
+#----------------------------------------------------------------------------
+# Name: DebuggerService.py
+# Purpose: Debugger Service for Python.
+#
+# Author: Matt Fryer
+#
+# Created: 12/9/04
+# CVS-ID: $Id$
+# Copyright: (c) 2004-2005 ActiveGrid, Inc.
+# License: wxWindows License
+#----------------------------------------------------------------------------
+
+import wx
+import wx.lib.intctrl
+import wx.lib.docview
+import wx.lib.dialogs
+import wx.gizmos
+import wx._core
+import wx.lib.pydocview
+import Service
+import STCTextEditor
+import CodeEditor
+import PythonEditor
+from IDE import ACTIVEGRID_BASE_IDE
+if not ACTIVEGRID_BASE_IDE:
+ import ProcessModelEditor
+import wx.lib.scrolledpanel as scrolled
+import sys
+import time
+import SimpleXMLRPCServer
+import xmlrpclib
+import os
+import threading
+import process
+import Queue
+import SocketServer
+import ProjectEditor
+import types
+from xml.dom.minidom import parse, parseString
+import bz2
+import pickle
+import DebuggerHarness
+import traceback
+import StringIO
+if wx.Platform == '__WXMSW__':
+ import win32api
+ _WINDOWS = True
+else:
+ _WINDOWS = False
+_ = wx.GetTranslation
+
+_VERBOSE = False
+_WATCHES_ON = False
+
+# Class to read from stdout or stderr and write the result to a text control.
+# Args: file=file-like object
+# callback_function= function that takes a single argument, the line of text
+# read.
+class OutputReaderThread(threading.Thread):
+ def __init__(self, file, callback_function, callbackOnExit=None, accumulate=True):
+ threading.Thread.__init__(self)
+ self._file = file
+ self._callback_function = callback_function
+ self._keepGoing = True
+ self._lineCount = 0
+ self._accumulate = accumulate
+ self._callbackOnExit = callbackOnExit
+
+ def run(self):
+ file = self._file
+ start = time.time()
+ output = ""
+ while self._keepGoing:
+ try:
+ # This could block--how to handle that?
+ text = file.readline()
+ if text == '' or text == None:
+ self._keepGoing = False
+ elif not self._accumulate:
+ self._callback_function(text)
+ else:
+ # Should use a buffer? StringIO?
+ output += text
+ # Seems as though the read blocks if we got an error, so, to be
+ # sure that at least some of the exception gets printed, always
+ # send the first hundred lines back as they come in.
+ if self._lineCount < 100:
+ self._callback_function(output)
+ self._lineCount += 1
+ output = ""
+ elif time.time() - start > 0.25:
+ try:
+ self._callback_function(output)
+ except wx._core.PyDeadObjectError:
+ # GUI was killed while we were blocked.
+ self._keepGoing = False
+ start = time.time()
+ output = ""
+ except:
+ tp, val, tb = sys.exc_info()
+ print "Exception in OutputReaderThread.run():", tp, val
+ self._keepGoing = False
+ if self._callbackOnExit:
+ try:
+ self._callbackOnExit()
+ except wx._core.PyDeadObjectError:
+ pass
+ if _VERBOSE: print "Exiting OutputReaderThread"
+
+ def AskToStop(self):
+ self._keepGoing = False
+
+import wx.lib.newevent
+(UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent()
+(UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent()
+
+class Executor:
+
+ def GetPythonExecutablePath():
+ config = wx.ConfigBase_Get()
+ path = config.Read("ActiveGridPythonLocation")
+ if path:
+ return path
+ wx.MessageBox(_("To proceed I need to know the location of the python.exe you would like to use.\nTo set this, go to Tools-->Options and use the 'Python' tab to enter a value.\n"), _("Python Executable Location Unknown"))
+ return None
+ GetPythonExecutablePath = staticmethod(GetPythonExecutablePath)
+
+ 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):
+ self._fileName = fileName
+ self._stdOutCallback = self.OutCall
+ self._stdErrCallback = self.ErrCall
+ self._callbackOnExit = callbackOnExit
+ self._wxComponent = wxComponent
+ path = Executor.GetPythonExecutablePath()
+ self._cmd = '"' + path + '" -u \"' + fileName + '\"'
+ #Better way to do this? Quotes needed for windows file paths.
+ if(arg1 != None):
+ self._cmd += ' \"' + arg1 + '\"'
+ if(arg2 != None):
+ self._cmd += ' \"' + arg2 + '\"'
+ if(arg3 != None):
+ self._cmd += ' \"' + arg3 + '\"'
+ if(arg4 != None):
+ self._cmd += ' \"' + arg4 + '\"'
+ if(arg5 != None):
+ self._cmd += ' \"' + arg5 + '\"'
+ if(arg6 != None):
+ self._cmd += ' \"' + arg6 + '\"'
+ if(arg7 != None):
+ self._cmd += ' \"' + arg7 + '\"'
+ if(arg8 != None):
+ self._cmd += ' \"' + arg8 + '\"'
+ if(arg9 != None):
+ self._cmd += ' \"' + arg9 + '\"'
+
+ self._stdOutReader = None
+ self._stdErrReader = None
+ self._process = None
+
+ def OutCall(self, text):
+ evt = UpdateTextEvent(value = text)
+ wx.PostEvent(self._wxComponent, evt)
+
+ def ErrCall(self, text):
+ evt = UpdateErrorEvent(value = text)
+ wx.PostEvent(self._wxComponent, evt)
+
+ def Execute(self, arguments, startIn=None, environment=None):
+ if not startIn:
+ startIn = str(os.getcwd())
+ startIn = os.path.abspath(startIn)
+ command = self._cmd + ' ' + arguments
+ #stdinput = process.IOBuffer()
+ #self._process = process.ProcessProxy(command, mode='b', cwd=startIn, stdin=stdinput)
+ self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment)
+ # Kick off threads to read stdout and stderr and write them
+ # to our text control.
+ self._stdOutReader = OutputReaderThread(self._process.stdout, self._stdOutCallback, callbackOnExit=self._callbackOnExit)
+ self._stdOutReader.start()
+ self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False)
+ self._stdErrReader.start()
+
+
+ def DoStopExecution(self):
+ if(self._process != None):
+ self._process.kill()
+ self._process.close()
+ self._process = None
+ if(self._stdOutReader != None):
+ self._stdOutReader.AskToStop()
+ if(self._stdErrReader != None):
+ self._stdErrReader.AskToStop()
+
+class RunCommandUI(wx.Panel):
+
+ def __init__(self, parent, id, fileName):
+ wx.Panel.__init__(self, parent, id)
+ self._noteBook = parent
+
+ self.KILL_PROCESS_ID = wx.NewId()
+ self.CLOSE_TAB_ID = wx.NewId()
+
+ self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded)
+
+ # GUI Initialization follows
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" )
+ tb.SetToolBitmapSize((16,16))
+ sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
+
+ close_bmp = getCloseBitmap()
+ tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window'))
+ wx.EVT_TOOL(self, self.CLOSE_TAB_ID, self.OnToolClicked)
+
+ stop_bmp = getStopBitmap()
+ tb.AddSimpleTool(self.KILL_PROCESS_ID, stop_bmp, _("Stop the Run."))
+ wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.OnToolClicked)
+
+ tb.Realize()
+ self._textCtrl = STCTextEditor.TextCtrl(self, wx.NewId()) #id)
+ sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
+ self._textCtrl.SetViewLineNumbers(False)
+ self._textCtrl.SetReadOnly(True)
+ if wx.Platform == '__WXMSW__':
+ font = "Courier New"
+ else:
+ font = "Courier"
+ self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
+ self._textCtrl.SetFontColor(wx.BLACK)
+ self._textCtrl.StyleClearAll()
+
+ #Disabling for now...may interfere with file open. wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+
+ # Executor initialization
+ self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished)
+ self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
+ self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
+
+ def __del__(self):
+ self._executor.DoStopExecution()
+
+ def Execute(self, initialArgs, startIn, environment):
+ self._executor.Execute(initialArgs, startIn, environment)
+
+ def ExecutorFinished(self):
+ self._tb.EnableTool(self.KILL_PROCESS_ID, False)
+ nb = self.GetParent()
+ for i in range(0,nb.GetPageCount()):
+ if self == nb.GetPage(i):
+ text = nb.GetPageText(i)
+ newText = text.replace("Running", "Finished")
+ nb.SetPageText(i, newText)
+ break
+
+ def StopExecution(self):
+ self.Unbind(EVT_UPDATE_STDTEXT)
+ self.Unbind(EVT_UPDATE_ERRTEXT)
+ self._executor.DoStopExecution()
+
+ def AppendText(self, event):
+ self._textCtrl.SetReadOnly(False)
+ self._textCtrl.AddText(event.value)
+ self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
+ self._textCtrl.SetReadOnly(True)
+
+ def AppendErrorText(self, event):
+ self._textCtrl.SetReadOnly(False)
+ self._textCtrl.SetFontColor(wx.RED)
+ self._textCtrl.StyleClearAll()
+ self._textCtrl.AddText(event.value)
+ self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
+ self._textCtrl.SetFontColor(wx.BLACK)
+ self._textCtrl.StyleClearAll()
+ self._textCtrl.SetReadOnly(True)
+
+ #------------------------------------------------------------------------------
+ # Event handling
+ #-----------------------------------------------------------------------------
+
+ def OnToolClicked(self, event):
+ id = event.GetId()
+
+ if id == self.KILL_PROCESS_ID:
+ self._executor.DoStopExecution()
+
+ elif id == self.CLOSE_TAB_ID:
+ self._executor.DoStopExecution()
+ index = self._noteBook.GetSelection()
+ self._noteBook.GetPage(index).Show(False)
+ self._noteBook.RemovePage(index)
+
+ def OnDoubleClick(self, event):
+ # Looking for a stack trace line.
+ lineText, pos = self._textCtrl.GetCurLine()
+ fileBegin = lineText.find("File \"")
+ fileEnd = lineText.find("\", line ")
+ lineEnd = lineText.find(", in ")
+ if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
+ # Check the line before the one that was clicked on
+ lineNumber = self._textCtrl.GetCurrentLine()
+ if(lineNumber == 0):
+ return
+ lineText = self._textCtrl.GetLine(lineNumber - 1)
+ fileBegin = lineText.find("File \"")
+ fileEnd = lineText.find("\", line ")
+ lineEnd = lineText.find(", in ")
+ if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
+ return
+
+ filename = lineText[fileBegin + 6:fileEnd]
+ lineNum = int(lineText[fileEnd + 8:lineEnd])
+
+ foundView = None
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ if openDoc.GetFilename() == filename:
+ foundView = openDoc.GetFirstView()
+ break
+
+ if not foundView:
+ doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
+ foundView = doc.GetFirstView()
+
+ if foundView:
+ foundView.GetFrame().SetFocus()
+ foundView.Activate()
+ foundView.GotoLine(lineNum)
+ startPos = foundView.PositionFromLine(lineNum)
+
+ # FACTOR THIS INTO DocManager
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
+ openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
+
+ foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
+
+ def OnProcessEnded(self, evt):
+ self._executor.DoStopExecution()
+
+DEFAULT_PORT = 32032
+DEFAULT_HOST = 'localhost'
+PORT_COUNT = 21
+
+class DebugCommandUI(wx.Panel):
+ debuggerPortList = None
+ debuggers = []
+
+ def NotifyDebuggersOfBreakpointChange():
+ for debugger in DebugCommandUI.debuggers:
+ debugger.BreakPointChange()
+
+ NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange)
+
+ def DebuggerRunning():
+ for debugger in DebugCommandUI.debuggers:
+ if debugger._executor:
+ return True
+ return False
+ DebuggerRunning = staticmethod(DebuggerRunning)
+
+ def ShutdownAllDebuggers():
+ for debugger in DebugCommandUI.debuggers:
+ debugger.StopExecution()
+
+ ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
+
+ def GetAvailablePort():
+ for index in range( 0, len(DebugCommandUI.debuggerPortList)):
+ port = DebugCommandUI.debuggerPortList[index]
+ if DebugCommandUI.PortAvailable(port):
+ DebugCommandUI.debuggerPortList.pop(index)
+ return port
+ 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"))
+ assert False, "Out of ports for debugger."
+
+ GetAvailablePort = staticmethod(GetAvailablePort)
+
+ def ReturnPortToPool(port):
+ config = wx.ConfigBase_Get()
+ startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
+ if port in range(startingPort, startingPort + PORT_COUNT):
+ DebugCommandUI.debuggerPortList.append(port)
+
+ ReturnPortToPool = staticmethod(ReturnPortToPool)
+
+ def PortAvailable(port):
+ config = wx.ConfigBase_Get()
+ hostname = config.Read("DebuggerHostName", DEFAULT_HOST)
+ try:
+ server = AGXMLRPCServer((hostname, port))
+ server.server_close()
+ if _VERBOSE: print "Port ", str(port), " available."
+ return True
+ except:
+ tp,val,tb = sys.exc_info()
+ if _VERBOSE: traceback.print_exception(tp, val, tb)
+ if _VERBOSE: print "Port ", str(port), " unavailable."
+ return False
+
+ PortAvailable = staticmethod(PortAvailable)
+
+ def NewPortRange():
+ config = wx.ConfigBase_Get()
+ startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
+ DebugCommandUI.debuggerPortList = range(startingPort, startingPort + PORT_COUNT)
+ NewPortRange = staticmethod(NewPortRange)
+
+ def __init__(self, parent, id, command, service):
+ # Check for ports before creating the panel.
+ if not DebugCommandUI.debuggerPortList:
+ DebugCommandUI.NewPortRange()
+ self._debuggerPort = str(DebugCommandUI.GetAvailablePort())
+ self._guiPort = str(DebugCommandUI.GetAvailablePort())
+ self._debuggerBreakPort = str(DebugCommandUI.GetAvailablePort())
+
+ wx.Panel.__init__(self, parent, id)
+
+ self._parentNoteBook = parent
+ self._command = command
+ self._textCtrl = None
+ self._service = service
+ self._executor = None
+ self.STEP_ID = wx.NewId()
+ self.CONTINUE_ID = wx.NewId()
+ self.STEP_OUT_ID = wx.NewId()
+ self.NEXT_ID = wx.NewId()
+ self.KILL_PROCESS_ID = wx.NewId()
+ self.CLOSE_WINDOW_ID = wx.NewId()
+ self.BREAK_INTO_DEBUGGER_ID = wx.NewId()
+ self.CLEAR_ID = wx.NewId()
+ self.ADD_WATCH_ID = wx.NewId()
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (1000,30), wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT| wx.TB_TEXT, "Debugger" )
+ sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
+ tb.SetToolBitmapSize((16,16))
+
+ close_bmp = getCloseBitmap()
+ tb.AddSimpleTool( self.CLOSE_WINDOW_ID, close_bmp, _('Close Window'))
+ wx.EVT_TOOL(self, self.CLOSE_WINDOW_ID, self.StopAndRemoveUI)
+
+ stop_bmp = getStopBitmap()
+ tb.AddSimpleTool( self.KILL_PROCESS_ID, stop_bmp, _("Stop Debugging"))
+ wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.StopExecution)
+
+ tb.AddSeparator()
+
+ break_bmp = getBreakBitmap()
+ tb.AddSimpleTool( self.BREAK_INTO_DEBUGGER_ID, break_bmp, _("Break into Debugger"))
+ wx.EVT_TOOL(self, self.BREAK_INTO_DEBUGGER_ID, self.BreakExecution)
+
+ tb.AddSeparator()
+
+ continue_bmp = getContinueBitmap()
+ tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution"))
+ wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue)
+
+ tb.AddSeparator()
+
+ next_bmp = getNextBitmap()
+ tb.AddSimpleTool( self.NEXT_ID, next_bmp, _("Step to next line"))
+ wx.EVT_TOOL(self, self.NEXT_ID, self.OnNext)
+
+ step_bmp = getStepInBitmap()
+ tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in"))
+ wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep)
+
+ stepOut_bmp = getStepReturnBitmap()
+ tb.AddSimpleTool(self.STEP_OUT_ID, stepOut_bmp, _("Stop at function return"))
+ wx.EVT_TOOL(self, self.STEP_OUT_ID, self.OnStepOut)
+
+ tb.AddSeparator()
+ if _WATCHES_ON:
+ watch_bmp = getAddWatchBitmap()
+ tb.AddSimpleTool(self.ADD_WATCH_ID, watch_bmp, _("Add a watch"))
+ wx.EVT_TOOL(self, self.ADD_WATCH_ID, self.OnAddWatch)
+ tb.AddSeparator()
+
+ clear_bmp = getClearOutputBitmap()
+ tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane"))
+ wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput)
+
+ tb.Realize()
+ self.framesTab = None
+ self.DisableWhileDebuggerRunning()
+ self._notebook = wx.Notebook(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.LB_DEFAULT, "Debugger")
+ sizer.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
+ self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId(), None)
+ self.framesTab = self.MakeFramesTab(self._notebook, wx.NewId(), None)
+ self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId(), None)
+ self._notebook.AddPage(self.consoleTab, "Output")
+ self._notebook.AddPage(self.framesTab, "Frames")
+ self._notebook.AddPage(self.breakPointsTab, "Break Points")
+
+ self._statusBar = wx.StatusBar( self, -1)
+ self._statusBar.SetFieldsCount(1)
+ sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
+
+ self.SetStatusText("Starting debug...")
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+ config = wx.ConfigBase_Get()
+ self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST)
+ url = 'http://' + self._debuggerHost + ':' + self._debuggerPort + '/'
+ self._breakURL = 'http://' + self._debuggerHost + ':' + self._debuggerBreakPort + '/'
+ self._callback = DebuggerCallback(self._guiHost, self._guiPort, url, self._breakURL, self)
+ if DebuggerHarness.__file__.find('library.zip') > 0:
+ try:
+ fname = DebuggerHarness.__file__
+ parts = fname.split('library.zip')
+ path = os.path.join(parts[0],'activegrid', 'tool', 'DebuggerHarness.py')
+ except:
+ tp, val, tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+
+ else:
+ print "Starting debugger on these ports: %s, %s, %s" % (str(self._debuggerPort) , str(self._guiPort) , str(self._debuggerBreakPort))
+ path = DebuggerService.ExpandPath(DebuggerHarness.__file__)
+ self._executor = Executor(path, self, self._debuggerHost, \
+ self._debuggerPort, self._debuggerBreakPort, self._guiHost, self._guiPort, self._command, callbackOnExit=self.ExecutorFinished)
+
+ self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
+ self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
+ DebugCommandUI.debuggers.append(self)
+ self._stopped = False
+
+ def OnSingleStep(self, event):
+ self._callback.SingleStep()
+
+ def OnContinue(self, event):
+ self._callback.Continue()
+
+ def OnStepOut(self, event):
+ self._callback.Return()
+
+ def OnNext(self, event):
+ self._callback.Next()
+
+ def BreakPointChange(self):
+ if not self._stopped:
+ self._callback.pushBreakpoints()
+ self.breakPointsTab.PopulateBPList()
+
+ def __del__(self):
+ if self in DebugCommandUI.debuggers:
+ DebugCommandUI.debuggers.remove(self)
+
+ def SwitchToOutputTab(self):
+ self._notebook.SetSelection(0)
+
+ def DisableWhileDebuggerRunning(self):
+ self._tb.EnableTool(self.STEP_ID, False)
+ self._tb.EnableTool(self.CONTINUE_ID, False)
+ self._tb.EnableTool(self.STEP_OUT_ID, False)
+ self._tb.EnableTool(self.NEXT_ID, False)
+ self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, True)
+ if _WATCHES_ON:
+ self._tb.EnableTool(self.ADD_WATCH_ID, False)
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
+ openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
+ if self.framesTab:
+ self.framesTab.ClearWhileRunning()
+ #wx.GetApp().ProcessPendingEvents() #Yield(True)
+
+ def EnableWhileDebuggerStopped(self):
+ self._tb.EnableTool(self.STEP_ID, True)
+ self._tb.EnableTool(self.CONTINUE_ID, True)
+ self._tb.EnableTool(self.STEP_OUT_ID, True)
+ self._tb.EnableTool(self.NEXT_ID, True)
+ if _WATCHES_ON:
+ self._tb.EnableTool(self.ADD_WATCH_ID, True)
+ self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
+ #if _WINDOWS:
+ # wx.GetApp().GetTopWindow().RequestUserAttention()
+
+ def ExecutorFinished(self):
+ if _VERBOSE: print "In ExectorFinished"
+ try:
+ self.DisableAfterStop()
+ except wx._core.PyDeadObjectError:
+ pass
+ try:
+ nb = self.GetParent()
+ for i in range(0, nb.GetPageCount()):
+ if self == nb.GetPage(i):
+ text = nb.GetPageText(i)
+ newText = text.replace("Debugging", "Finished")
+ nb.SetPageText(i, newText)
+ if _VERBOSE: print "In ExectorFinished, changed tab title."
+ break
+ except:
+ if _VERBOSE: print "In ExectorFinished, got exception"
+
+ def DisableAfterStop(self):
+ self.DisableWhileDebuggerRunning()
+ self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
+ self._tb.EnableTool(self.KILL_PROCESS_ID, False)
+
+ def SynchCurrentLine(self, filename, lineNum):
+ # FACTOR THIS INTO DocManager
+ self.DeleteCurrentLineMarkers()
+
+ # Filename will be <string> if we're in a bit of code that was executed from
+ # a string (rather than a file). I haven't been able to get the original string
+ # for display.
+ if filename == '<string>':
+ return
+ foundView = None
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ # This ugliness to prevent comparison failing because the drive letter
+ # gets lowercased occasionally. Don't know why that happens or why it
+ # only happens occasionally.
+ if DebuggerService.ComparePaths(openDoc.GetFilename(),filename):
+ foundView = openDoc.GetFirstView()
+ break
+
+ if not foundView:
+ if _VERBOSE:
+ print "filename=", filename
+ doc = wx.GetApp().GetDocumentManager().CreateDocument(DebuggerService.ExpandPath(filename), wx.lib.docview.DOC_SILENT)
+ foundView = doc.GetFirstView()
+
+ if foundView:
+ foundView.GetFrame().SetFocus()
+ foundView.Activate()
+ foundView.GotoLine(lineNum)
+ startPos = foundView.PositionFromLine(lineNum)
+
+ foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
+
+ def DeleteCurrentLineMarkers(self):
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
+ openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
+
+ def LoadFramesListXML(self, framesXML):
+ self.framesTab.LoadFramesListXML(framesXML)
+
+ def SetStatusText(self, text):
+ self._statusBar.SetStatusText(text,0)
+
+ def Execute(self, initialArgs, startIn, environment):
+ self._callback.start()
+ self._executor.Execute(initialArgs, startIn, environment)
+ self._callback.waitForRPC()
+
+ def BreakExecution(self, event):
+ self._callback.BreakExecution()
+
+
+ def StopExecution(self, event):
+ self._stopped = True
+ self.DisableAfterStop()
+ try:
+ self._callback.ServerClose()
+ except:
+ pass
+ try:
+ if self._executor:
+ self._executor.DoStopExecution()
+ self._executor = None
+ except:
+ pass
+ self.DeleteCurrentLineMarkers()
+ DebugCommandUI.ReturnPortToPool(self._debuggerPort)
+ DebugCommandUI.ReturnPortToPool(self._guiPort)
+ DebugCommandUI.ReturnPortToPool(self._debuggerBreakPort)
+
+ def StopAndRemoveUI(self, event):
+ self.StopExecution(None)
+ if self in DebugCommandUI.debuggers:
+ DebugCommandUI.debuggers.remove(self)
+ index = self._parentNoteBook.GetSelection()
+ self._parentNoteBook.GetPage(index).Show(False)
+ self._parentNoteBook.RemovePage(index)
+
+ def GetConsoleTextControl(self):
+ return self._textCtrl
+
+ def OnClearOutput(self, event):
+ self._textCtrl.SetReadOnly(False)
+ self._textCtrl.ClearAll()
+ self._textCtrl.SetReadOnly(True)
+
+ def OnAddWatch(self, event):
+ if self.framesTab:
+ self.framesTab.OnWatch(event)
+
+ def MakeConsoleTab(self, parent, id, debugger):
+ panel = wx.Panel(parent, id)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
+ sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
+ self._textCtrl.SetViewLineNumbers(False)
+ self._textCtrl.SetReadOnly(True)
+ if wx.Platform == '__WXMSW__':
+ font = "Courier New"
+ else:
+ font = "Courier"
+ self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
+ self._textCtrl.SetFontColor(wx.BLACK)
+ self._textCtrl.StyleClearAll()
+ panel.SetSizer(sizer)
+ sizer.Fit(panel)
+
+ return panel
+
+ def MakeFramesTab(self, parent, id, debugger):
+ panel = FramesUI(parent, id, self)
+ return panel
+
+ def MakeBreakPointsTab(self, parent, id, debugger):
+ panel = BreakpointsUI(parent, id, self)
+ return panel
+
+ def AppendText(self, event):
+ self._textCtrl.SetReadOnly(False)
+ self._textCtrl.AddText(event.value)
+ self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
+ self._textCtrl.SetReadOnly(True)
+
+ def AppendErrorText(self, event):
+ self._textCtrl.SetReadOnly(False)
+ self._textCtrl.SetFontColor(wx.RED)
+ self._textCtrl.StyleClearAll()
+ self._textCtrl.AddText(event.value)
+ self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
+ self._textCtrl.SetFontColor(wx.BLACK)
+ self._textCtrl.StyleClearAll()
+ self._textCtrl.SetReadOnly(True)
+
+class BreakpointsUI(wx.Panel):
+ def __init__(self, parent, id, ui):
+ wx.Panel.__init__(self, parent, id)
+ self._ui = ui
+ self.currentItem = None
+ self.clearBPID = wx.NewId()
+ self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID)
+ self.syncLineID = wx.NewId()
+ self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ p1 = self
+ self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT)
+ sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
+ self._bpListCtrl.InsertColumn(0, "File")
+ self._bpListCtrl.InsertColumn(1, "Line")
+ self._bpListCtrl.InsertColumn(2, "Path")
+ self._bpListCtrl.SetColumnWidth(0, 150)
+ self._bpListCtrl.SetColumnWidth(1, 50)
+ self._bpListCtrl.SetColumnWidth(2, 450)
+ self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl)
+ self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl)
+
+ self.PopulateBPList()
+
+ p1.SetSizer(sizer)
+ sizer.Fit(p1)
+ p1.Layout()
+
+ def PopulateBPList(self):
+ list = self._bpListCtrl
+ list.DeleteAllItems()
+
+ bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict()
+ index = 0
+ for fileName in bps.keys():
+ shortFile = os.path.basename(fileName)
+ lines = bps[fileName]
+ if lines:
+ for line in lines:
+ list.InsertStringItem(index, shortFile)
+ list.SetStringItem(index, 1, str(line))
+ list.SetStringItem(index, 2, fileName)
+
+ def OnListRightClick(self, event):
+ menu = wx.Menu()
+ item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint")
+ menu.AppendItem(item)
+ item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line")
+ menu.AppendItem(item)
+ self.PopupMenu(menu, event.GetPosition())
+ menu.Destroy()
+
+ def SyncBPLine(self, event):
+ if self.currentItem != -1:
+ list = self._bpListCtrl
+ fileName = list.GetItem(self.currentItem, 2).GetText()
+ lineNumber = list.GetItem(self.currentItem, 1).GetText()
+ self._ui.SynchCurrentLine( fileName, int(lineNumber) )
+
+ def ClearBreakPoint(self, event):
+ if self.currentItem >= 0:
+ list = self._bpListCtrl
+ fileName = list.GetItem(self.currentItem, 2).GetText()
+ lineNumber = list.GetItem(self.currentItem, 1).GetText()
+ wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName )
+
+ def ListItemSelected(self, event):
+ self.currentItem = event.m_itemIndex
+
+ def ListItemDeselected(self, event):
+ self.currentItem = -1
+
+class Watch:
+ CODE_ALL_FRAMES = 1
+ CODE_THIS_BLOCK = 2
+ CODE_THIS_LINE = 4
+ CODE_RUN_ONCE = 8
+
+ def __init__(self, name, command, show_code=CODE_ALL_FRAMES):
+ self._name = name
+ self._command = command
+ self._show_code = show_code
+
+class WatchDialog(wx.Dialog):
+ WATCH_ALL_FRAMES = "Watch in all frames"
+ WATCH_THIS_FRAME = "Watch in this frame only"
+ WATCH_ONCE = "Watch once and delete"
+ def __init__(self, parent, title, chain):
+ wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE)
+ self._chain = chain
+ self.label_2 = wx.StaticText(self, -1, "Watch Name:")
+ self._watchNameTextCtrl = wx.TextCtrl(self, -1, "")
+ self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT)
+ self._watchValueTextCtrl = wx.TextCtrl(self, -1, "")
+ self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)")
+ 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)
+
+ self._okButton = wx.Button(self, wx.ID_OK, "OK", size=(75,-1))
+ self._okButton.SetDefault()
+ self._okButton.SetHelpText(_("The OK button completes the dialog"))
+ def OnOkClick(event):
+ if self._watchNameTextCtrl.GetValue() == "":
+ wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
+ return
+ if self._watchValueTextCtrl.GetValue() == "":
+ wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
+ return
+ self.EndModal(wx.ID_OK)
+ self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton)
+
+ self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"), size=(75,-1))
+ self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
+
+ self.__set_properties()
+ self.__do_layout()
+
+ def GetSettings(self):
+ return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce()
+
+ def GetSendFrame(self):
+ return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection())
+
+ def GetRunOnce(self):
+ return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection())
+
+ def __set_properties(self):
+ self.SetTitle("Add a Watch")
+ #self.SetSize((400, 250))
+ self.radio_box_1.SetSelection(0)
+
+ def __do_layout(self):
+ sizer_1 = wx.BoxSizer(wx.VERTICAL)
+ grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5)
+ grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5)
+ grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
+ grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0)
+ grid_sizer_2.AddGrowableCol(1)
+ sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
+ grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
+ grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0)
+ grid_sizer_4.AddGrowableCol(1)
+ grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
+ sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0)
+ sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0)
+
+ box = wx.BoxSizer(wx.HORIZONTAL)
+ box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
+ box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
+ sizer_1.Add(box, 1, wx.EXPAND, 0)
+ self.SetAutoLayout(True)
+ self.SetSizer(sizer_1)
+ self.Layout()
+
+class FramesUI(wx.SplitterWindow):
+ def __init__(self, parent, id, ui):
+ wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
+ self._ui = ui
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ self._p1 = p1 = wx.ScrolledWindow(self, -1)
+ p1.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self._framesListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(250,150), style=wx.LC_REPORT)
+ sizer.Add(self._framesListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
+ self._framesListCtrl.InsertColumn(0, "Frame")
+ self._framesListCtrl.SetColumnWidth(0, 250)
+ self._framesListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._framesListCtrl)
+ self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._framesListCtrl)
+
+ sizer2 = wx.BoxSizer(wx.VERTICAL)
+ self._p2 = p2 = wx.ScrolledWindow(self, -1)
+ p2.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self._treeCtrl = wx.gizmos.TreeListCtrl(p2, -1, size=(530,250), style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
+ self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
+ sizer2.Add(self._framesListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
+ tree = self._treeCtrl
+ tree.AddColumn("Thing")
+ tree.AddColumn("Value")
+ tree.SetMainColumn(0) # the one with the tree in it...
+ tree.SetColumnWidth(0, 175)
+ tree.SetColumnWidth(1, 355)
+ self._root = tree.AddRoot("Frame")
+ tree.SetItemText(self._root, "", 1)
+
+ self.SetMinimumPaneSize(20)
+ self.SplitVertically(p1, p2, 250)
+ self.currentItem = None
+ self.Layout()
+
+ def OnRightClick(self, event):
+ #Refactor this...
+ self._introspectItem = event.GetItem()
+ self._parentChain = self.GetItemChain(event.GetItem())
+ watchOnly = len(self._parentChain) < 1
+ if not _WATCHES_ON and watchOnly:
+ return
+ menu = wx.Menu()
+ if not watchOnly:
+ if not hasattr(self, "introspectID"):
+ self.introspectID = wx.NewId()
+ self.Bind(wx.EVT_MENU, self.OnIntrospect, id=self.introspectID)
+ item = wx.MenuItem(menu, self.introspectID, "Attempt Introspection")
+ menu.AppendItem(item)
+ menu.AppendSeparator()
+ if _WATCHES_ON:
+ if not hasattr(self, "watchID"):
+ self.watchID = wx.NewId()
+ self.Bind(wx.EVT_MENU, self.OnWatch, id=self.watchID)
+ item = wx.MenuItem(menu, self.watchID, "Create a Watch")
+ menu.AppendItem(item)
+ menu.AppendSeparator()
+ if not watchOnly:
+ if not hasattr(self, "viewID"):
+ self.viewID = wx.NewId()
+ self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID)
+ item = wx.MenuItem(menu, self.viewID, "View in Dialog")
+ menu.AppendItem(item)
+ offset = wx.Point(x=0, y=20)
+ menuSpot = event.GetPoint() + offset
+ self._treeCtrl.PopupMenu(menu, menuSpot)
+ menu.Destroy()
+ self._parentChain = None
+ self._introspectItem = None
+
+ def GetItemChain(self, item):
+ parentChain = []
+ if item:
+ if _VERBOSE: print 'Exploding: %s' % self._treeCtrl.GetItemText(item, 0)
+ while item != self._root:
+ text = self._treeCtrl.GetItemText(item, 0)
+ if _VERBOSE: print "Appending ", text
+ parentChain.append(text)
+ item = self._treeCtrl.GetItemParent(item)
+ parentChain.reverse()
+ return parentChain
+
+ def OnView(self, event):
+ title = self._treeCtrl.GetItemText(self._introspectItem,0)
+ value = self._treeCtrl.GetItemText(self._introspectItem,1)
+ dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER)
+ dlg.Show()
+
+ def OnWatch(self, event):
+ try:
+ if hasattr(self, '_parentChain'):
+ wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain)
+ else:
+ wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None)
+ if wd.ShowModal() == wx.ID_OK:
+ name, text, send_frame, run_once = wd.GetSettings()
+ if send_frame:
+ frameNode = self._stack[int(self.currentItem)]
+ message = frameNode.getAttribute("message")
+ else:
+ message = ""
+ binType = self._ui._callback._debuggerServer.add_watch(name, text, message, run_once)
+ xmldoc = bz2.decompress(binType.data)
+ domDoc = parseString(xmldoc)
+ nodeList = domDoc.getElementsByTagName('watch')
+ if len(nodeList) == 1:
+ watchValue = nodeList.item(0).getAttribute("message")
+ except:
+ tp, val, tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+
+ def OnIntrospect(self, event):
+ wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
+
+ try:
+ list = self._framesListCtrl
+ frameNode = self._stack[int(self.currentItem)]
+ message = frameNode.getAttribute("message")
+ binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain)
+ xmldoc = bz2.decompress(binType.data)
+
+ domDoc = parseString(xmldoc)
+ nodeList = domDoc.getElementsByTagName('replacement')
+ replacementNode = nodeList.item(0)
+ if len(replacementNode.childNodes):
+ thingToWalk = replacementNode.childNodes.item(0)
+ tree = self._treeCtrl
+ parent = tree.GetItemParent(self._introspectItem)
+ treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem)
+ tree.Delete(self._introspectItem)
+ except:
+ tp,val,tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+
+ wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
+
+ def OnSize(self, event):
+ self._treeCtrl.SetSize(self._p2.GetSize())
+ w,h = self._p1.GetClientSizeTuple()
+ self._framesListCtrl.SetDimensions(0, 0, w, h)
+
+ def ClearWhileRunning(self):
+ list = self._framesListCtrl
+ list.DeleteAllItems()
+ tree = self._treeCtrl
+ tree.Hide()
+
+ def OnListRightClick(self, event):
+ if not hasattr(self, "syncFrameID"):
+ self.syncFrameID = wx.NewId()
+ self.Bind(wx.EVT_MENU, self.OnSyncFrame, id=self.syncFrameID)
+ menu = wx.Menu()
+ item = wx.MenuItem(menu, self.syncFrameID, "Goto Source Line")
+ menu.AppendItem(item)
+ self.PopupMenu(menu, event.GetPosition())
+ menu.Destroy()
+
+ def OnSyncFrame(self, event):
+ list = self._framesListCtrl
+ frameNode = self._stack[int(self.currentItem)]
+ file = frameNode.getAttribute("file")
+ line = frameNode.getAttribute("line")
+ self._ui.SynchCurrentLine( file, int(line) )
+
+ def LoadFramesListXML(self, framesXML):
+ wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
+ try:
+ domDoc = parseString(framesXML)
+ list = self._framesListCtrl
+ list.DeleteAllItems()
+ self._stack = []
+ nodeList = domDoc.getElementsByTagName('frame')
+ frame_count = -1
+ for index in range(0, nodeList.length):
+ frameNode = nodeList.item(index)
+ message = frameNode.getAttribute("message")
+ list.InsertStringItem(index, message)
+ self._stack.append(frameNode)
+ frame_count += 1
+ list.Select(frame_count)
+ self._p1.FitInside()
+ frameNode = nodeList.item(index)
+ file = frameNode.getAttribute("file")
+ line = frameNode.getAttribute("line")
+ self._ui.SynchCurrentLine( file, int(line) )
+ except:
+ tp,val,tb=sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+
+ wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
+
+ def ListItemDeselected(self, event):
+ pass
+
+ def ListItemSelected(self, event):
+ self.currentItem = event.m_itemIndex
+ frameNode = self._stack[int(self.currentItem)]
+ self.PopulateTreeFromFrameNode(frameNode)
+ # Temporarily doing this to test out automatically swicting to source line.
+ self.OnSyncFrame(None)
+
+ def PopulateTreeFromFrameNode(self, frameNode):
+ tree = self._treeCtrl
+ tree.Show(True)
+ root = self._root
+ tree.DeleteChildren(root)
+ children = frameNode.childNodes
+ firstChild = None
+ for index in range(0, children.length):
+ subNode = children.item(index)
+ treeNode = self.AppendSubTreeFromNode(subNode, subNode.getAttribute('name'), root)
+ if not firstChild:
+ firstChild = treeNode
+ tree.Expand(root)
+ tree.Expand(firstChild)
+ self._p2.FitInside()
+
+ def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None):
+ tree = self._treeCtrl
+ if insertBefore != None:
+ treeNode = tree.InsertItem(parent, insertBefore, name)
+ else:
+ treeNode = tree.AppendItem(parent, name)
+ children = node.childNodes
+ if children.length == 0:
+ tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1)
+ for index in range(0, children.length):
+ subNode = children.item(index)
+ if self.HasChildren(subNode):
+ self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode)
+ else:
+ name = subNode.getAttribute("name")
+ value = self.StripOuterSingleQuotes(subNode.getAttribute("value"))
+ n = tree.AppendItem(treeNode, name)
+ tree.SetItemText(n, value, 1)
+ return treeNode
+
+ def StripOuterSingleQuotes(self, string):
+ if string.startswith("'") and string.endswith("'"):
+ return string[1:-1]
+ elif type(string) == types.UnicodeType:
+ return string[1:-1]
+ else:
+ return string
+
+ def HasChildren(self, node):
+ try:
+ return node.childNodes.length > 0
+ except:
+ tp,val,tb=sys.exc_info()
+ return False
+
+class DebuggerView(Service.ServiceView):
+
+ #----------------------------------------------------------------------------
+ # Overridden methods
+ #----------------------------------------------------------------------------
+
+ def __init__(self, service):
+ Service.ServiceView.__init__(self, service)
+
+ def _CreateControl(self, parent, id):
+ return None
+
+ #------------------------------------------------------------------------------
+ # Event handling
+ #-----------------------------------------------------------------------------
+
+ def OnToolClicked(self, event):
+ self.GetFrame().ProcessEvent(event)
+
+ #------------------------------------------------------------------------------
+ # Class methods
+ #-----------------------------------------------------------------------------
+
+class Interaction:
+ def __init__(self, message, framesXML, info=None, quit=False):
+ self._framesXML = framesXML
+ self._message = message
+ self._info = info
+ self._quit = quit
+
+ def getFramesXML(self):
+ return self._framesXML
+
+ def getMessage(self):
+ return self._message
+
+ def getInfo(self):
+ return self._info
+
+ def getQuit(self):
+ return self._quit
+
+class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
+ def __init__(self, address, logRequests=0):
+ SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests)
+
+class RequestHandlerThread(threading.Thread):
+ def __init__(self, queue, address):
+ threading.Thread.__init__(self)
+ self._keepGoing = True
+ self._queue = queue
+ self._address = address
+ self._server = AGXMLRPCServer(self._address,logRequests=0)
+ self._server.register_function(self.interaction)
+ self._server.register_function(self.quit)
+ self._server.register_function(self.dummyOperation)
+ if _VERBOSE: print "RequestHandlerThread on fileno %s" % str(self._server.fileno())
+
+ def run(self):
+ while self._keepGoing:
+ try:
+ self._server.handle_request()
+ except:
+ tp, val, tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+ self._keepGoing = False
+ if _VERBOSE: print "Exiting Request Handler Thread."
+
+ def interaction(self, message, frameXML, info):
+ if _VERBOSE: print "In RequestHandlerThread.interaction -- adding to queue"
+ interaction = Interaction(message, frameXML, info)
+ self._queue.put(interaction)
+ return ""
+
+ def quit(self):
+ interaction = Interaction(None, None, info=None, quit=True)
+ self._queue.put(interaction)
+ return ""
+
+ def dummyOperation(self):
+ return ""
+
+ def AskToStop(self):
+ self._keepGoing = False
+ if type(self._server) is not types.NoneType:
+ try:
+ # This is a really ugly way to make sure this thread isn't blocked in
+ # handle_request.
+ url = 'http://' + self._address[0] + ':' + str(self._address[1]) + '/'
+ tempServer = xmlrpclib.ServerProxy(url, allow_none=1)
+ tempServer.dummyOperation()
+ except:
+ tp, val, tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+ self._server.server_close()
+
+
+class RequestBreakThread(threading.Thread):
+ def __init__(self, server, interrupt=False, pushBreakpoints=False, breakDict=None, kill=False):
+ threading.Thread.__init__(self)
+ self._server = server
+
+ self._interrupt = interrupt
+ self._pushBreakpoints = pushBreakpoints
+ self._breakDict = breakDict
+ self._kill = kill
+
+ def run(self):
+ try:
+ if _VERBOSE: print "RequestBreakThread, before call"
+ if self._interrupt:
+ self._server.break_requested()
+ if self._pushBreakpoints:
+ self._server.update_breakpoints(xmlrpclib.Binary(pickle.dumps(self._breakDict)))
+ if self._kill:
+ try:
+ self._server.die()
+ except:
+ pass
+ if _VERBOSE: print "RequestBreakThread, after call"
+ except:
+ tp,val,tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+
+class DebuggerOperationThread(threading.Thread):
+ def __init__(self, function):
+ threading.Thread.__init__(self)
+ self._function = function
+
+ def run(self):
+ if _VERBOSE: print "In DOT, before call"
+ try:
+ self._function()
+ except:
+ tp,val,tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+ if _VERBOSE: print "In DOT, after call"
+
+class DebuggerCallback:
+
+ def __init__(self, host, port, debugger_url, break_url, debuggerUI):
+ if _VERBOSE: print "+++++++ Creating server on port, ", str(port)
+
+ self._queue = Queue.Queue(50)
+ self._host = host
+ self._port = int(port)
+ threading._VERBOSE = _VERBOSE
+ self._serverHandlerThread = RequestHandlerThread(self._queue, (self._host, self._port))
+
+ self._debugger_url = debugger_url
+ self._debuggerServer = None
+ self._waiting = False
+ self._service = wx.GetApp().GetService(DebuggerService)
+ self._debuggerUI = debuggerUI
+ self._break_url = break_url
+ self._breakServer = None
+ self._firstInteraction = True
+ self._pendingBreak = False
+
+ def start(self):
+ self._serverHandlerThread.start()
+
+ def ServerClose(self):
+ rbt = RequestBreakThread(self._breakServer, kill=True)
+ rbt.start()
+ self.setWaiting(False)
+ if self._serverHandlerThread:
+ self._serverHandlerThread.AskToStop()
+ self._serverHandlerThread = None
+
+ def BreakExecution(self):
+ rbt = RequestBreakThread(self._breakServer, interrupt=True)
+ rbt.start()
+
+ def SingleStep(self):
+ self._debuggerUI.DisableWhileDebuggerRunning()
+ #dot = DebuggerOperationThread(self._debuggerServer.set_step)
+ #dot.start()
+ self._debuggerServer.set_step() # Figure out where to set allowNone
+ self.waitForRPC()
+
+ def Next(self):
+ self._debuggerUI.DisableWhileDebuggerRunning()
+ #dot = DebuggerOperationThread(self._debuggerServer.set_next)
+ #dot.start()
+ self._debuggerServer.set_next()
+ self.waitForRPC()
+
+ def Continue(self):
+ self._debuggerUI.DisableWhileDebuggerRunning()
+ #dot = DebuggerOperationThread(self._debuggerServer.set_continue)
+ #dot.start()
+ self._debuggerServer.set_continue()
+ self.waitForRPC()
+
+ def Return(self):
+ self._debuggerUI.DisableWhileDebuggerRunning()
+ #dot = DebuggerOperationThread(self._debuggerServer.set_return)
+ #dot.start()
+ self._debuggerServer.set_return()
+ self.waitForRPC()
+
+ def setWaiting(self, value):
+ self._waiting = value
+
+ def getWaiting(self):
+ return self._waiting
+
+ def readQueue(self):
+ if self._queue.qsize():
+ try:
+ item = self._queue.get_nowait()
+ if item.getQuit():
+ self.interaction(None, None, None, True)
+ else:
+ data = bz2.decompress(item.getFramesXML().data)
+ self.interaction(item.getMessage().data, data, item.getInfo(), False)
+ except Queue.Empty:
+ pass
+
+ def pushBreakpoints(self):
+ rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict())
+ rbt.start()
+
+
+ def waitForRPC(self):
+ self.setWaiting(True)
+ while self.getWaiting():
+ try:
+ self.readQueue()
+ import time
+ time.sleep(0.02)
+ except:
+ tp, val, tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+ wx.GetApp().Yield(True)
+ if _VERBOSE: print "Exiting waitForRPC."
+
+ def interaction(self, message, frameXML, info, quit):
+
+ #This method should be hit as the debugger starts.
+ if self._firstInteraction:
+ self._firstInteraction = False
+ self._debuggerServer = xmlrpclib.ServerProxy(self._debugger_url, allow_none=1)
+ self._breakServer = xmlrpclib.ServerProxy(self._break_url, allow_none=1)
+ self.pushBreakpoints()
+ self.setWaiting(False)
+ if _VERBOSE: print "+"*40
+ if(quit):
+ self._debuggerUI.StopExecution(None)
+ return ""
+ if(info != ""):
+ if _VERBOSE: print "Hit interaction with exception"
+ #self._debuggerUI.StopExecution(None)
+ #self._debuggerUI.SetStatusText("Got exception: " + str(info))
+ self._debuggerUI.SwitchToOutputTab()
+ else:
+ if _VERBOSE: print "Hit interaction no exception"
+ self._debuggerUI.SetStatusText(message)
+ self._debuggerUI.LoadFramesListXML(frameXML)
+ self._debuggerUI.EnableWhileDebuggerStopped()
+ if _VERBOSE: print "+"*40
+
+class DebuggerService(Service.Service):
+
+ #----------------------------------------------------------------------------
+ # Constants
+ #----------------------------------------------------------------------------
+ TOGGLE_BREAKPOINT_ID = wx.NewId()
+ CLEAR_ALL_BREAKPOINTS = wx.NewId()
+ RUN_ID = wx.NewId()
+ DEBUG_ID = wx.NewId()
+
+ def ComparePaths(first, second):
+ one = DebuggerService.ExpandPath(first)
+ two = DebuggerService.ExpandPath(second)
+ if _WINDOWS:
+ return one.lower() == two.lower()
+ else:
+ return one == two
+ ComparePaths = staticmethod(ComparePaths)
+
+ # Make sure we're using an expanded path on windows.
+ def ExpandPath(path):
+ if _WINDOWS:
+ try:
+ return win32api.GetLongPathName(path)
+ except:
+ print "Cannot get long path for %s" % path
+
+ return path
+
+ ExpandPath = staticmethod(ExpandPath)
+
+ #----------------------------------------------------------------------------
+ # Overridden methods
+ #----------------------------------------------------------------------------
+
+ def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT):
+ Service.Service.__init__(self, serviceName, embeddedWindowLocation)
+ self.BREAKPOINT_DICT_STRING = "MasterBreakpointDict"
+ config = wx.ConfigBase_Get()
+ pickledbps = config.Read(self.BREAKPOINT_DICT_STRING)
+ if pickledbps:
+ try:
+ self._masterBPDict = pickle.loads(pickledbps.encode('ascii'))
+ except:
+ tp, val, tb = sys.exc_info()
+ traceback.print_exception(tp,val,tb)
+ self._masterBPDict = {}
+ else:
+ self._masterBPDict = {}
+
+ def OnCloseFrame(self, event):
+ # IS THIS THE RIGHT PLACE?
+ try:
+ config = wx.ConfigBase_Get()
+ config.Write(self.BREAKPOINT_DICT_STRING, pickle.dumps(self._masterBPDict))
+ except:
+ tp,val,tb = sys.exc_info()
+ traceback.print_exception(tp, val, tb)
+ return True
+
+ def _CreateView(self):
+ return DebuggerView(self)
+
+
+ #----------------------------------------------------------------------------
+ # Service specific methods
+ #----------------------------------------------------------------------------
+
+ def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
+ #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
+
+ config = wx.ConfigBase_Get()
+
+ debuggerMenu = wx.Menu()
+ if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS):
+
+ debuggerMenu.Append(DebuggerService.RUN_ID, _("&Run...\tCtrl+R"), _("Runs a file"))
+ wx.EVT_MENU(frame, DebuggerService.RUN_ID, frame.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_ID, frame.ProcessUpdateUIEvent)
+
+ debuggerMenu.Append(DebuggerService.DEBUG_ID, _("&Debug...\tCtrl+D"), _("Debugs a file"))
+ wx.EVT_MENU(frame, DebuggerService.DEBUG_ID, frame.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_ID, frame.ProcessUpdateUIEvent)
+
+ debuggerMenu.AppendSeparator()
+
+ debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint...\tCtrl+B"), _("Toggle a breakpoint"))
+ wx.EVT_MENU(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessUpdateUIEvent)
+
+ debuggerMenu.Append(DebuggerService.CLEAR_ALL_BREAKPOINTS, _("&Clear All Breakpoints"), _("Clear All Breakpoints"))
+ wx.EVT_MENU(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessUpdateUIEvent)
+
+
+ viewMenuIndex = menuBar.FindMenu(_("&Project"))
+ menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run"))
+
+ return True
+
+
+
+ #----------------------------------------------------------------------------
+ # Event Processing Methods
+ #----------------------------------------------------------------------------
+
+ def ProcessEventBeforeWindows(self, event):
+ return False
+
+
+ def ProcessEvent(self, event):
+ if Service.Service.ProcessEvent(self, event):
+ return True
+
+ an_id = event.GetId()
+ if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
+ self.OnToggleBreakpoint(event)
+ return True
+ elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
+ self.ClearAllBreakpoints()
+ return True
+ elif an_id == DebuggerService.RUN_ID:
+ self.OnRunProject(event)
+ return True
+ elif an_id == DebuggerService.DEBUG_ID:
+ self.OnDebugProject(event)
+ return True
+ return False
+
+ def ProcessUpdateUIEvent(self, event):
+ if Service.Service.ProcessUpdateUIEvent(self, event):
+ return True
+
+ an_id = event.GetId()
+ if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
+ currentView = self.GetDocumentManager().GetCurrentView()
+ event.Enable(isinstance(currentView, PythonEditor.PythonView))
+ return True
+ elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
+ event.Enable(self.HasBreakpointsSet())
+ return True
+ elif an_id == DebuggerService.RUN_ID:
+ event.Enable(self.HasAnyFiles())
+ return True
+ elif an_id == DebuggerService.DEBUG_ID:
+ event.Enable(self.HasAnyFiles())
+ return True
+ else:
+ return False
+
+ #----------------------------------------------------------------------------
+ # Class Methods
+ #----------------------------------------------------------------------------
+
+ def OnDebugProject(self, event):
+ if not Executor.GetPythonExecutablePath():
+ return
+ if DebugCommandUI.DebuggerRunning():
+ wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
+ return
+ self.ShowWindow(True)
+ projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
+ project = projectService.GetView().GetDocument()
+ dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug Python File', projectService, None, pythonOnly=True, okButtonName="Debug", debugging=True)
+ if dlg.ShowModal() == wx.ID_OK:
+ fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
+ dlg.Destroy()
+ else:
+ dlg.Destroy()
+ return
+ self.PromptToSaveFiles()
+
+ shortFile = os.path.basename(fileToDebug)
+ fileToDebug = DebuggerService.ExpandPath(fileToDebug)
+ try:
+ page = DebugCommandUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self)
+ count = Service.ServiceView.bottomTab.GetPageCount()
+ Service.ServiceView.bottomTab.AddPage(page, "Debugging: " + shortFile)
+ Service.ServiceView.bottomTab.SetSelection(count)
+ page.Execute(initialArgs, startIn, environment)
+ except:
+ pass
+
+ def HasAnyFiles(self):
+ docs = wx.GetApp().GetDocumentManager().GetDocuments()
+ return len(docs) > 0
+
+ def PromptToSaveFiles(self, running=True):
+ filesModified = False
+ docs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for doc in docs:
+ if doc.IsModified():
+ filesModified = True
+ break
+ if filesModified:
+ frame = self.GetView().GetFrame()
+ if running:
+ yesNoMsg = wx.MessageDialog(frame,
+ _("Files have been modified.\nWould you like to save all files before running?"),
+ _("Run"),
+ wx.YES_NO
+ )
+ else:
+ yesNoMsg = wx.MessageDialog(frame,
+ _("Files have been modified.\nWould you like to save all files before debugging?"),
+ _("Debug"),
+ wx.YES_NO
+ )
+ if yesNoMsg.ShowModal() == wx.ID_YES:
+ docs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for doc in docs:
+ doc.Save()
+
+ def OnExit(self):
+ DebugCommandUI.ShutdownAllDebuggers()
+
+ def OnRunProject(self, event):
+ if not Executor.GetPythonExecutablePath():
+ return
+ projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
+ project = projectService.GetView().GetDocument()
+ dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None)
+ if dlg.ShowModal() == wx.ID_OK:
+ fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
+
+
+ dlg.Destroy()
+ else:
+ dlg.Destroy()
+ return
+ self.PromptToSaveFiles()
+ # This will need to change when we can run more than .py and .bpel files.
+ if not isPython:
+ projectService.RunProcessModel(fileToRun)
+ return
+
+ self.ShowWindow(True)
+ shortFile = os.path.basename(fileToRun)
+ page = RunCommandUI(Service.ServiceView.bottomTab, -1, str(fileToRun))
+ count = Service.ServiceView.bottomTab.GetPageCount()
+ Service.ServiceView.bottomTab.AddPage(page, "Running: " + shortFile)
+ Service.ServiceView.bottomTab.SetSelection(count)
+ page.Execute(initialArgs, startIn, environment)
+
+ def OnToggleBreakpoint(self, event, line=-1, fileName=None):
+ if not fileName:
+ view = wx.GetApp().GetDocumentManager().GetCurrentView()
+ # Test to make sure we aren't the project view.
+ if not hasattr(view, 'MarkerExists'):
+ return
+ fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
+ if line < 0:
+ line = view.GetCtrl().GetCurrentLine()
+ if self.BreakpointSet(fileName, line + 1):
+ self.ClearBreak(fileName, line + 1)
+ else:
+ self.SetBreak(fileName, line + 1)
+ # Now refresh all the markers icons in all the open views.
+ self.ClearAllBreakpointMarkers()
+ self.SetAllBreakpointMarkers()
+
+ def SilentToggleBreakpoint(self, fileName, line):
+ found = False
+ for lineNumber in self.GetBreakpointList(fileName):
+ if int(lineNumber) == int(line):
+ found = True
+ break
+ if found:
+ self.SetBreak(fileName, line)
+ else:
+ self.ClearBreak(fileName, line)
+
+ def SetBreak(self, fileName, line):
+ expandedName = DebuggerService.ExpandPath(fileName)
+ if not self._masterBPDict.has_key(expandedName):
+ self._masterBPDict[expandedName] = [line]
+ else:
+ self._masterBPDict[expandedName] += [line]
+ # If we're already debugging, pass this bp off to the DebuggerCallback
+ self.NotifyDebuggersOfBreakpointChange()
+
+ def NotifyDebuggersOfBreakpointChange(self):
+ DebugCommandUI.NotifyDebuggersOfBreakpointChange()
+
+ def GetBreakpointList(self, fileName):
+ expandedName = DebuggerService.ExpandPath(fileName)
+ if not self._masterBPDict.has_key(expandedName):
+ return []
+ else:
+ return self._masterBPDict[expandedName]
+
+ def BreakpointSet(self, fileName, line):
+ expandedName = DebuggerService.ExpandPath(fileName)
+ if not self._masterBPDict.has_key(expandedName):
+ return False
+ else:
+ newList = []
+ for number in self._masterBPDict[expandedName]:
+ if(int(number) == int(line)):
+ return True
+ return False
+
+ def ClearBreak(self, fileName, line):
+ expandedName = DebuggerService.ExpandPath(fileName)
+ if not self._masterBPDict.has_key(expandedName):
+ print "In ClearBreak: no key"
+ return
+ else:
+ newList = []
+ for number in self._masterBPDict[expandedName]:
+ if(int(number) != int(line)):
+ newList.append(number)
+ self._masterBPDict[expandedName] = newList
+ self.NotifyDebuggersOfBreakpointChange()
+
+ def HasBreakpointsSet(self):
+ for key, value in self._masterBPDict.items():
+ if len(value) > 0:
+ return True
+ return False
+
+ def ClearAllBreakpoints(self):
+ self._masterBPDict = {}
+ self.NotifyDebuggersOfBreakpointChange()
+ self.ClearAllBreakpointMarkers()
+
+ def ClearAllBreakpointMarkers(self):
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
+ openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
+
+ def GetMasterBreakpointDict(self):
+ return self._masterBPDict
+
+ def SetAllBreakpointMarkers(self):
+ openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for openDoc in openDocs:
+ if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
+ self.SetCurrentBreakpointMarkers(openDoc.GetFirstView())
+
+ def SetCurrentBreakpointMarkers(self, view):
+ if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'):
+ view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
+ for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()):
+ view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
+
+class DebuggerOptionsPanel(wx.Panel):
+
+
+ def __init__(self, parent, id):
+ wx.Panel.__init__(self, parent, id)
+ SPACE = 10
+ config = wx.ConfigBase_Get()
+ localHostStaticText = wx.StaticText(self, -1, _("Local Host Name:"))
+ self._LocalHostTextCtrl = wx.TextCtrl(self, -1, config.Read("DebuggerHostName", DEFAULT_HOST), size = (150, -1))
+ portNumberStaticText = wx.StaticText(self, -1, _("Port Range:"))
+ dashStaticText = wx.StaticText(self, -1, _("through to"))
+ startingPort=config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
+ self._PortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort, size = (50, -1))
+ self._PortNumberTextCtrl.SetMin(1)#What are real values?
+ self._PortNumberTextCtrl.SetMax(65514) #What are real values?
+ self.Bind(wx.lib.intctrl.EVT_INT, self.MinPortChange, self._PortNumberTextCtrl)
+
+ self._EndPortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort + PORT_COUNT, size = (50, -1))
+ self._EndPortNumberTextCtrl.SetMin(22)#What are real values?
+ self._EndPortNumberTextCtrl.SetMax(65535)#What are real values?
+ self._EndPortNumberTextCtrl.Enable( False )
+ debuggerPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
+ debuggerPanelSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+ debuggerPanelSizer.Add( localHostStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
+ debuggerPanelSizer.Add( self._LocalHostTextCtrl, (0,1), (1,3), flag=wx.EXPAND|wx.ALIGN_CENTER)
+ debuggerPanelSizer.Add( portNumberStaticText, (1,0), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
+ debuggerPanelSizer.Add( self._PortNumberTextCtrl, (1,1), flag=wx.ALIGN_CENTER)
+ debuggerPanelSizer.Add( dashStaticText, (1,2), flag=wx.ALIGN_CENTER)
+ debuggerPanelSizer.Add( self._EndPortNumberTextCtrl, (1,3), flag=wx.ALIGN_CENTER)
+ FLUSH_PORTS_ID = wx.NewId()
+ self._flushPortsButton = wx.Button(self, FLUSH_PORTS_ID, "Reset Port List")
+ wx.EVT_BUTTON(parent, FLUSH_PORTS_ID, self.FlushPorts)
+ debuggerPanelSizer.Add(self._flushPortsButton, (2,2), (1,2), flag=wx.ALIGN_RIGHT)
+
+ debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE)
+ self.SetSizer(debuggerPanelBorderSizer)
+ self.Layout()
+ parent.AddPage(self, _("Debugger"))
+
+ def FlushPorts(self, event):
+ if self._PortNumberTextCtrl.IsInBounds():
+ config = wx.ConfigBase_Get()
+ config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
+ DebugCommandUI.NewPortRange()
+ else:
+ wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
+
+ def MinPortChange(self, event):
+ self._EndPortNumberTextCtrl.Enable( True )
+ self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT)
+ self._EndPortNumberTextCtrl.Enable( False )
+
+ def OnOK(self, optionsDialog):
+ config = wx.ConfigBase_Get()
+ config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue())
+ if self._PortNumberTextCtrl.IsInBounds():
+ config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
+
+class CommandPropertiesDialog(wx.Dialog):
+
+ def __init__(self, parent, title, projectService, currentProjectDocument, pythonOnly=False, okButtonName="Run", debugging=False):
+ if _WINDOWS:
+ wx.Dialog.__init__(self, parent, -1, title)
+ else:
+ wx.Dialog.__init__(self, parent, -1, title, size=(390,270))
+ self._projService = projectService
+ self._pmext = None
+ self._pyext = None
+ for template in self._projService.GetDocumentManager().GetTemplates():
+ if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
+ self._pmext = template.GetDefaultExtension()
+ if template.GetDocumentType() == PythonEditor.PythonDocument:
+ self._pyext = template.GetDefaultExtension()
+ self._pythonOnly = pythonOnly
+
+ self._currentProj = currentProjectDocument
+ projStaticText = wx.StaticText(self, -1, _("Project:"))
+ fileStaticText = wx.StaticText(self, -1, _("File:"))
+ argsStaticText = wx.StaticText(self, -1, _("Arguments:"))
+ startInStaticText = wx.StaticText(self, -1, _("Start in:"))
+ pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:"))
+ postpendStaticText = _("Postpend win32api path")
+ cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
+ self._projectNameList, self._projectDocumentList, selectedIndex = self.GetProjectList()
+ self._projList = wx.Choice(self, -1, (200,-1), choices=self._projectNameList)
+ self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList)
+ HALF_SPACE = 5
+ flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = 10, hgap = 10)
+
+ flexGridSizer.Add(projStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
+ flexGridSizer.Add(self._projList, 1, flag=wx.EXPAND)
+ flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
+
+ flexGridSizer.Add(fileStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
+ self._fileList = wx.Choice(self, -1, (200,-1))
+ self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList)
+ flexGridSizer.Add(self._fileList, 1, flag=wx.EXPAND)
+ flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
+
+ config = wx.ConfigBase_Get()
+ self._lastArguments = config.Read("LastRunArguments")
+ self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments))
+ self._argsEntry.SetToolTipString(str(self._lastArguments))
+ def TextChanged(event):
+ self._argsEntry.SetToolTipString(event.GetString())
+ self.Bind(wx.EVT_TEXT, TextChanged, self._argsEntry)
+
+ flexGridSizer.Add(argsStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
+ flexGridSizer.Add(self._argsEntry, 1, flag=wx.EXPAND)
+ flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
+
+ flexGridSizer.Add(startInStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
+ self._lastStartIn = config.Read("LastRunStartIn")
+ if not self._lastStartIn:
+ self._lastStartIn = str(os.getcwd())
+ self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn)
+ self._startEntry.SetToolTipString(self._lastStartIn)
+ def TextChanged2(event):
+ self._startEntry.SetToolTipString(event.GetString())
+ self.Bind(wx.EVT_TEXT, TextChanged2, self._startEntry)
+
+ flexGridSizer.Add(self._startEntry, 1, wx.EXPAND)
+ self._findDir = wx.Button(self, -1, _("Browse..."), size=(60,-1))
+ self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir)
+ flexGridSizer.Add(self._findDir, 0, wx.RIGHT, 10)
+
+ flexGridSizer.Add(pythonPathStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
+ if os.environ.has_key('PYTHONPATH'):
+ startval = os.environ['PYTHONPATH']
+ else:
+ startval = ""
+ self._lastPythonPath = config.Read("LastPythonPath", startval)
+ self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath)
+ self._pythonPathEntry.SetToolTipString(self._lastPythonPath)
+ flexGridSizer.Add(self._pythonPathEntry, 1, wx.EXPAND)
+ flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
+ flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
+ if debugging:
+ self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText)
+ checked = bool(config.ReadInt("PythonPathPostpend", 1))
+ self._postpendCheckBox.SetValue(checked)
+ flexGridSizer.Add(self._postpendCheckBox, 1, wx.EXPAND)
+ flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
+ cpPanelBorderSizer.Add(flexGridSizer, 0, wx.ALL, 10)
+
+ box = wx.BoxSizer(wx.HORIZONTAL)
+ self._okButton = wx.Button(self, wx.ID_OK, okButtonName, size=(75,-1))
+ self._okButton.SetDefault()
+ self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog"))
+ box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
+ self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton)
+ btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"), size=(75,-1))
+ btn.SetHelpText(_("The Cancel button cancels the dialog."))
+ box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
+ cpPanelBorderSizer.Add(box, 0, wx.ALIGN_RIGHT|wx.BOTTOM, 5)
+
+ self.SetSizer(cpPanelBorderSizer)
+ if _WINDOWS:
+ self.GetSizer().Fit(self)
+
+ self.Layout()
+
+ # Set up selections based on last values used.
+ self._fileNameList = None
+ self._selectedFileIndex = 0
+ lastProject = config.Read("LastRunProject")
+ lastFile = config.Read("LastRunFile")
+
+ if lastProject in self._projectNameList:
+ selectedIndex = self._projectNameList.index(lastProject)
+ elif selectedIndex < 0:
+ selectedIndex = 0
+ self._projList.Select(selectedIndex)
+ self._selectedProjectIndex = selectedIndex
+ self._selectedProjectDocument = self._projectDocumentList[selectedIndex]
+ self.PopulateFileList(self._selectedProjectDocument, lastFile)
+
+ def OnOKClick(self, event):
+ startIn = self._startEntry.GetValue()
+ fileToRun = self._fileList.GetStringSelection()
+ if not fileToRun:
+ wx.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged."))
+ return
+ isPython = fileToRun.endswith(self._pyext)
+ if isPython and not os.path.exists(startIn):
+ wx.MessageBox(_("Starting directory does not exist. Please change this value."))
+ return
+ config = wx.ConfigBase_Get()
+ config.Write("LastRunProject", self._projectNameList[self._selectedProjectIndex])
+ config.Write("LastRunFile", fileToRun)
+ # Don't update the arguments or starting directory unless we're runing python.
+ if isPython:
+ config.Write("LastRunArguments", self._argsEntry.GetValue())
+ config.Write("LastRunStartIn", self._startEntry.GetValue())
+ config.Write("LastPythonPath",self._pythonPathEntry.GetValue())
+ if hasattr(self, "_postpendCheckBox"):
+ config.WriteInt("PythonPathPostpend", int(self._postpendCheckBox.GetValue()))
+
+ self.EndModal(wx.ID_OK)
+
+ def GetSettings(self):
+ filename = self._fileNameList[self._selectedFileIndex]
+ args = self._argsEntry.GetValue()
+ startIn = self._startEntry.GetValue()
+ isPython = filename.endswith(self._pyext)
+ env = os.environ
+ if hasattr(self, "_postpendCheckBox"):
+ postpend = self._postpendCheckBox.GetValue()
+ else:
+ postpend = False
+ if postpend:
+ env['PYTHONPATH'] = self._pythonPathEntry.GetValue() + os.pathsep + os.path.join(os.getcwd(), "3rdparty", "pywin32")
+ else:
+ env['PYTHONPATH'] = self._pythonPathEntry.GetValue()
+
+ return filename, args, startIn, isPython, env
+
+ def OnFileSelected(self, event):
+ self._selectedFileIndex = self._fileList.GetSelection()
+ self.EnableForFileType(event.GetString())
+
+ def EnableForFileType(self, fileName):
+ show = fileName.endswith(self._pyext)
+ self._startEntry.Enable(show)
+ self._findDir.Enable(show)
+ self._argsEntry.Enable(show)
+
+ if not show:
+ self._lastStartIn = self._startEntry.GetValue()
+ self._startEntry.SetValue("")
+ self._lastArguments = self._argsEntry.GetValue()
+ self._argsEntry.SetValue("")
+ else:
+ self._startEntry.SetValue(self._lastStartIn)
+ self._argsEntry.SetValue(self._lastArguments)
+
+
+
+ def OnFindDirClick(self, event):
+ dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(),
+ style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self._startEntry.SetValue(dlg.GetPath())
+
+ dlg.Destroy()
+
+ def EvtListBox(self, event):
+ if event.GetString():
+ index = self._projectNameList.index(event.GetString())
+ self._selectedProjectDocument = self._projectDocumentList[index]
+ self._selectedProjectIndex = index
+ self.PopulateFileList(self._selectedProjectDocument)
+
+ def FilterFileList(self, list):
+ if self._pythonOnly:
+ files = filter(lambda f: f.endswith(self._pyext), list)
+ else:
+ files = filter(lambda f: (self._pmext and f.endswith(self._pmext)) or f.endswith(self._pyext), list)
+ return files
+
+ def PopulateFileList(self, project, shortNameToSelect=None):
+ self._fileNameList = self.FilterFileList(project.GetFiles()[:])
+ self._fileList.Clear()
+ if not self._fileNameList:
+ return
+ self._fileNameList.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower()))
+ strings = map(lambda file: os.path.basename(file), self._fileNameList)
+ for index in range(0, len(strings)):
+ if shortNameToSelect == strings[index]:
+ self._selectedFileIndex = index
+ break
+ self._fileList.Hide()
+ self._fileList.AppendItems(strings)
+ self._fileList.Show()
+ if self._selectedFileIndex not in range(0, len(strings)) : self._selectedFileIndex = 0
+ self._fileList.SetSelection(self._selectedFileIndex)
+ self.EnableForFileType(strings[self._selectedFileIndex])
+
+ def GetProjectList(self):
+ docList = []
+ nameList = []
+ found = False
+ index = -1
+ count = 0
+ for document in self._projService.GetDocumentManager().GetDocuments():
+ if document.GetDocumentTemplate().GetDocumentType() == ProjectEditor.ProjectDocument and len(document.GetFiles()):
+ docList.append(document)
+ nameList.append(os.path.basename(document.GetFilename()))
+ if document == self._currentProj:
+ found = True
+ index = count
+ count += 1
+ return nameList, docList, index
+#----------------------------------------------------------------------
+from wx import ImageFromStream, BitmapFromImage
+from wx import EmptyIcon
+import cStringIO
+#----------------------------------------------------------------------
+def getBreakData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x11\x08\x06\
+\x00\x00\x00\xd4\xaf,\xc4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x97IDAT8\x8d\xbdSA\x0e\xc3 \x0c\x8b\x13\xfe=\x1e^\xe2\x1dF\xbb\x8c\
+\xd2\x0c\xa9\xda,q\x88\x05\x8e\x1d\x00P\x93;\xd0[\xa7W\x04\xe8\x8d\x0f\xdfxU\
+c%\x02\xbd\xbd\x05HQ+Xv\xb0\xa3VN\xf9\xd4\x01\xbd\x11j\x18\x1d\x00\x10\xa8AD\
+\xa4\xa4\xd6_\x9b\x19\xbb\x03\xd8c|\x8f\x00\xe0\x93\xa8g>\x15 C\xee:\xe7\x8f\
+\x08\xdesj\xcf\xe6\xde(\xddn\xec\x18f0w\xe0m;\x8d\x9b\xe4\xb1\xd4\n\xa6\x0e2\
+\xc4{\x1f\xeb\xdf?\xe5\xff\t\xa8\x1a$\x0cg\xac\xaf\xb0\xf4\x992<\x01\xec\xa0\
+U9V\xf9\x18\xc8\x00\x00\x00\x00IEND\xaeB`\x82'
+
+def getBreakBitmap():
+ return BitmapFromImage(getBreakImage())
+
+def getBreakImage():
+ stream = cStringIO.StringIO(getBreakData())
+ return ImageFromStream(stream)
+
+def getBreakIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getBreakBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getClearOutputData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\xb4IDAT8\x8d\xa5\x92\xdd\r\x03!\x0c\x83\xbf\xa0n\xd4\x9d\xda5\xb81\
+\xbaS\xbb\x12\xee\x03?\xe5\x08\xe5N\xba\xbc Db\xec\xd8p\xb1l\xb8\xa7\x83\xfe\
+\xb0\x02H\x92F\xc0_\xa3\x99$\x99\x99\xedznc\xe36\x81\x88\x98"\xb2\x02\xa2\
+\x1e\xc4Q\x9aUD\x161\xcd\xde\x1c\x83\x15\x084)\x8d\xc5)\x06\xab\xaaZ\x92\xee\
+\xce\x11W\xdbGD\x0cIT\x06\xe7\x00\xdeY\xfe\xcc\x89\x06\xf0\xf2\x99\x00\xe0\
+\x91\x7f\xab\x83\xed\xa4\xc8\xafK\x0c\xcf\x92\x83\x99\x8d\xe3p\xef\xe4\xa1\
+\x0b\xe57j\xc8:\x06\t\x08\x87.H\xb2n\xa8\xc9\xa9\x12vQ\xfeG"\xe3\xacw\x00\
+\x10$M\xd3\x86_\xf0\xe5\xfc\xb4\xfa\x02\xcb\x13j\x10\xc5\xd7\x92D\x00\x00\
+\x00\x00IEND\xaeB`\x82'
+
+def getClearOutputBitmap():
+ return BitmapFromImage(getClearOutputImage())
+
+def getClearOutputImage():
+ stream = cStringIO.StringIO(getClearOutputData())
+ return ImageFromStream(stream)
+
+def getClearOutputIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getClearOutputBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getCloseData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x12\x00\x00\x00\x12\x08\x06\
+\x00\x00\x00V\xce\x8eW\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
+\x00\x86IDAT8\x8d\xed\x90\xb1\r\x80 \x10E_"c\xd80\x02-\x138\x87;8\x8f\x8d\
+\x8b\xb0\x02\xa5\xad\rS\x88\xcd\x11) \x82\xb6\xbe\xea\xf2\xc9\xbd\xfc\x03~\
+\xdeb\x81\xb9\x90\xabJ^%\x00N\x849\x0e\xf0\x85\xbc\x8a\x12YZR2\xc7\x1eIB\xcb\
+\xb2\xcb\x9at\x9d\x95c\xa5Y|\x92\x0c\x0f\xa2\r8e\x1e\x81\x1d8z\xdb8\xee?Ig\
+\xfa\xb7\x92)\xcb\xacd\x01XZ$QD\xba\xf0\xa6\x80\xd5\x18cZ\x1b\x95$?\x1f\xb9\
+\x00\x1d\x94\x1e*e_\x8a~\x00\x00\x00\x00IEND\xaeB`\x82'
+
+def getCloseBitmap():
+ return BitmapFromImage(getCloseImage())
+
+def getCloseImage():
+ stream = cStringIO.StringIO(getCloseData())
+ return ImageFromStream(stream)
+
+def getCloseIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getCloseBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getContinueData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x9eIDAT8\x8d\xbd\x92\xd1\r\x83@\x0cC\xed\x8a\x11X\xac\x1b\xddF,\xd6\
+\x11\x90\xdc\x0f\x9a\x93s)\x14Z\xa9\x91\x10\n\x97\xbc\xd89\x80?\x84\x1a\xa4\
+\x83\xfc\x1c$\x1e)7\xdf<Y0\xaf\x0b\xe6\xf5\x1d\xa1\xb5\x13C\x03 !\xaa\xfd\
+\xed\n:mr\xc0\x1d\x8f\xc9\x9a!\t$\xe5\xd3I\xe2\xe5B$\x99\x00[\x01\xe8\xc5\
+\xd9G\xfaN`\xd8\x81I\xed\x8c\xb19\x94\x8d\xcbL\x00;t\xcf\x9fwPh\xdb\x0e\xe8\
+\xd3,\x17\x8b\xc7\x9d\xbb>\x8a \xec5\x94\tc\xc4\x12\xab\x94\xeb\x7fkWr\xc9B%\
+\xfc\xd2\xfcM<\x01\xf6tn\x12O3c\xe6\x00\x00\x00\x00IEND\xaeB`\x82'
+
+def getContinueBitmap():
+ return BitmapFromImage(getContinueImage())
+
+def getContinueImage():
+ stream = cStringIO.StringIO(getContinueData())
+ return ImageFromStream(stream)
+
+def getContinueIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getContinueBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getNextData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\
+\x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\
+gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\
+\x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\
+\xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\
+)\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\
+`\x82'
+
+def getNextBitmap():
+ return BitmapFromImage(getNextImage())
+
+def getNextImage():
+ stream = cStringIO.StringIO(getNextData())
+ return ImageFromStream(stream)
+
+def getNextIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getNextBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getStepInData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\
+\x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\
+\x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\
+]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\
+\x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\
+\x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
+
+def getStepInBitmap():
+ return BitmapFromImage(getStepInImage())
+
+def getStepInImage():
+ stream = cStringIO.StringIO(getStepInData())
+ return ImageFromStream(stream)
+
+def getStepInIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getStepInBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getStopData():
+ return \
+"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00FIDAT8\x8d\xed\x91\xc1\t\xc00\x0c\x03O!\x0b\xa9\xfb\xef\xa6\xfcB\xa1\
+N\t\xf4Wr\xa0\x8f\xb1\x0f\x81\xe1\x97\xe4-\xb6}_V%\xc8\xc2, \t\x92\xe6]\xfbZ\
+\xf7\x08\xa0W\xc3\xea5\xdb\rl_IX\xe5\xf0d\x00\xfa\x8d#\x7f\xc4\xf7'\xab\x00\
+\x00\x00\x00IEND\xaeB`\x82"
+
+def getStopBitmap():
+ return BitmapFromImage(getStopImage())
+
+def getStopImage():
+ stream = cStringIO.StringIO(getStopData())
+ return ImageFromStream(stream)
+
+def getStopIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getStopBitmap())
+ return icon
+
+#----------------------------------------------------------------------
+def getStepReturnData():
+ return \
+"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\
+\xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\
+\x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\
+\x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\
+\x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\
+\xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\
+\xaeB`\x82"
+
+def getStepReturnBitmap():
+ return BitmapFromImage(getStepReturnImage())
+
+def getStepReturnImage():
+ stream = cStringIO.StringIO(getStepReturnData())
+ return ImageFromStream(stream)
+
+def getStepReturnIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getStepReturnBitmap())
+ return icon
+
+def getAddWatchData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\
+\x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\
+\xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\
+\xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\
+\xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\
+\x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
+
+def getAddWatchBitmap():
+ return BitmapFromImage(getAddWatchImage())
+
+def getAddWatchImage():
+ stream = cStringIO.StringIO(getAddWatchData())
+ return ImageFromStream(stream)
+
+def getAddWatchIcon():
+ icon = EmptyIcon()
+ icon.CopyFromBitmap(getAddWatchBitmap())
+ return icon