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