More updates to the docview library modules and sample apps from the

ActiveGrid folks.  Their sample IDE is now able to integrate with
Subversion.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34158 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2005-05-19 00:21:49 +00:00
parent 4809f5df5d
commit 6f1a3f9c1a
19 changed files with 1791 additions and 1064 deletions

View File

@@ -98,6 +98,10 @@ optionally specify where the new control point has to be drawn.
wxMSW: setting foreground colour for wx.CheckBox now works when using wxMSW: setting foreground colour for wx.CheckBox now works when using
XP themes. XP themes.
More updates to the docview library modules and sample apps from the
ActiveGrid folks. Their sample IDE is now able to integrate with
Subversion.

View File

@@ -28,6 +28,7 @@ licenseData = [
("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.5.4/wx_wxlicense.html"), ("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.5.4/wx_wxlicense.html"),
("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"), ("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"),
("process.py", "See file", "http://starship.python.net/~tmick/"), ("process.py", "See file", "http://starship.python.net/~tmick/"),
("pysvn", "Apache License", "http://pysvn.tigris.org/"),
] ]
if not ACTIVEGRID_BASE_IDE: # add licenses for database connections only if not the base IDE if not ACTIVEGRID_BASE_IDE: # add licenses for database connections only if not the base IDE

View File

@@ -66,13 +66,18 @@ class CanvasView(wx.lib.docview.View):
if activate and self._canvas: if activate and self._canvas:
# In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI: if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
self._canvas.SetFocus() self.SetFocus()
else: else:
wx.CallAfter(self._canvas.SetFocus) wx.CallAfter(self.SetFocus)
def SetFocus(self):
if self._canvas:
self._canvas.SetFocus()
def OnFocus(self, event): def OnFocus(self, event):
self._canvas.SetFocus() self.SetFocus()
self.FocusColorPropertyShape(True) self.FocusColorPropertyShape(True)
event.Skip() event.Skip()
@@ -82,6 +87,17 @@ class CanvasView(wx.lib.docview.View):
event.Skip() event.Skip()
def HasFocus(self):
winWithFocus = wx.Window.FindFocus()
if not winWithFocus:
return False
while winWithFocus:
if winWithFocus == self._canvas:
return True
winWithFocus = winWithFocus.GetParent()
return False
def OnClose(self, deleteWindow = True): def OnClose(self, deleteWindow = True):
statusC = wx.GetApp().CloseChildDocuments(self.GetDocument()) statusC = wx.GetApp().CloseChildDocuments(self.GetDocument())
statusP = wx.lib.docview.View.OnClose(self, deleteWindow = deleteWindow) statusP = wx.lib.docview.View.OnClose(self, deleteWindow = deleteWindow)
@@ -528,7 +544,10 @@ class CanvasView(wx.lib.docview.View):
# draw new selection # draw new selection
if self._propShape and self._propShape in self._diagram.GetShapeList(): if self._propShape and self._propShape in self._diagram.GetShapeList():
if self.HasFocus():
self._propShape.SetBrush(SELECT_BRUSH) self._propShape.SetBrush(SELECT_BRUSH)
else:
self._propShape.SetBrush(INACTIVE_SELECT_BRUSH)
if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken
self._propShape.SetTextColour("WHITE", 0) self._propShape.SetTextColour("WHITE", 0)
self._propShape.Draw(dc) self._propShape.Draw(dc)

View File

@@ -190,6 +190,7 @@ class Adb(bdb.Bdb):
def stop_here(self, frame): def stop_here(self, frame):
if( self._userBreak ): if( self._userBreak ):
self._userBreak = False
return True return True
@@ -447,10 +448,21 @@ class DebuggerHarness(object):
item_node.setAttribute('name', str(name)) item_node.setAttribute('name', str(name))
top_element.appendChild(item_node) top_element.appendChild(item_node)
cantIntro = [types.FunctionType,
types.LambdaType,
types.UnicodeType,
types.StringType,
types.NoneType,
types.IntType,
types.LongType,
types.FloatType,
types.BooleanType]
def addAny(self, top_element, name, item, doc, ply): def addAny(self, top_element, name, item, doc, ply):
tp = type(item) tp = type(item)
if ply < 1:
self.addNode(top_element,name, self.saferepr(item), doc) if tp in DebuggerHarness.cantIntro or ply < 1:
self.addNode(top_element,name, item, doc)
elif tp is types.TupleType or tp is types.ListType: elif tp is types.TupleType or tp is types.ListType:
self.addTupleOrList(top_element, name, item, doc, ply - 1) self.addTupleOrList(top_element, name, item, doc, ply - 1)
elif tp is types.DictType or tp is types.DictProxyType: elif tp is types.DictType or tp is types.DictProxyType:
@@ -459,23 +471,141 @@ class DebuggerHarness(object):
self.addModule(top_element, name, item, doc, ply -1) self.addModule(top_element, name, item, doc, ply -1)
elif inspect.isclass(item) or tp is types.InstanceType: elif inspect.isclass(item) or tp is types.InstanceType:
self.addClass(top_element, name, item, doc, ply -1) self.addClass(top_element, name, item, doc, ply -1)
#elif hasattr(item, '__dict__'):
# self.addDictAttr(top_element, name, item, doc, ply -1)
elif hasattr(item, '__dict__'): elif hasattr(item, '__dict__'):
self.addDict(top_element, name, item.__dict__, doc, ply -1) self.addDictAttr(top_element, name, item, doc, ply -1)
else: else:
self.addNode(top_element,name, self.saferepr(item), doc) self.addNode(top_element,name, item, doc)
def canIntrospect(self, item):
tp = type(item)
if tp in DebuggerHarness.cantIntro:
return False
elif tp is types.TupleType or tp is types.ListType:
return len(item) > 0
elif tp is types.DictType or tp is types.DictProxyType:
return len(item) > 0
elif inspect.ismodule(item):
return True
elif inspect.isclass(item) or tp is types.InstanceType:
if hasattr(item, '__dict__'):
return True
elif hasattr(item, '__name__'):
return True
elif hasattr(item, '__module__'):
return True
elif hasattr(item, '__doc__'):
return True
else:
return False
elif hasattr(item, '__dict__'):
return len(item.__dict__) > 0
else:
return False
def addNode(self, parent_node, name, item, document):
item_node = document.createElement("dict_nv_element")
item_node.setAttribute('value', self.saferepr(item))
item_node.setAttribute('name', str(name))
introVal = str(self.canIntrospect(item))
item_node.setAttribute('intro', str(introVal))
parent_node.appendChild(item_node)
def addTupleOrList(self, top_node, name, tupple, doc, ply): def addTupleOrList(self, top_node, name, tupple, doc, ply):
tupleNode = doc.createElement('tuple') tupleNode = doc.createElement('tuple')
tupleNode.setAttribute('name', str(name)) tupleNode.setAttribute('name', str(name))
tupleNode.setAttribute('value', str(type(tupple))) tupleNode.setAttribute('value', self.saferepr(tupple))
top_node.appendChild(tupleNode) top_node.appendChild(tupleNode)
count = 0 count = 0
for item in tupple: for item in tupple:
self.addAny(tupleNode, name +'[' + str(count) + ']',item, doc, ply -1) self.addAny(tupleNode, name +'[' + str(count) + ']',item, doc, ply -1)
count += 1 count += 1
def addDictAttr(self, root_node, name, thing, document, ply):
dict_node = document.createElement('thing')
dict_node.setAttribute('name', name)
dict_node.setAttribute('value', self.saferepr(thing))
root_node.appendChild(dict_node)
self.addDict(dict_node, '', thing.__dict__, document, ply) # Not decreminting ply
def addDict(self, root_node, name, dict, document, ply):
if name != '':
dict_node = document.createElement('dict')
dict_node.setAttribute('name', name)
dict_node.setAttribute('value', self.saferepr(dict))
root_node.appendChild(dict_node)
else:
dict_node = root_node
for key in dict.keys():
strkey = str(key)
try:
value = dict[key]
self.addAny(dict_node, strkey, value, document, ply-1)
except:
if _VERBOSE:
tp,val,tb=sys.exc_info()
print "Error recovering key: ", str(key), " from node ", str(name), " Val = ", str(val)
traceback.print_exception(tp, val, tb)
def addClass(self, root_node, name, class_item, document, ply):
item_node = document.createElement('class')
item_node.setAttribute('name', str(name))
item_node.setAttribute('value', self.saferepr(class_item))
root_node.appendChild(item_node)
try:
if hasattr(class_item, '__dict__'):
self.addDict(item_node, '', class_item.__dict__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
try:
if hasattr(class_item, '__name__'):
self.addAny(item_node,'__name__',class_item.__name__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
try:
if hasattr(class_item, '__module__'):
self.addAny(item_node, '__module__', class_item.__module__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
try:
if hasattr(class_item, '__doc__'):
self.addAny(item_node, '__doc__', class_item.__doc__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
try:
if hasattr(class_item, '__bases__'):
self.addAny(item_node, '__bases__', class_item.__bases__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
def addModule(self, root_node, name, module_item, document, ply):
item_node = document.createElement('module')
item_node.setAttribute('name', str(name))
item_node.setAttribute('value', self.saferepr(module_item))
root_node.appendChild(item_node)
try:
if hasattr(module_item, '__file__'):
self.addAny(item_node, '__file__', module_item.__file__, document, ply -1)
except:
pass
try:
if hasattr(module_item, '__doc__'):
self.addAny(item_node,'__doc__', module_item.__doc__, document, ply -1)
except:
pass
def getFrameXML(self, base_frame): def getFrameXML(self, base_frame):
doc = getDOMImplementation().createDocument(None, "stack", None) doc = getDOMImplementation().createDocument(None, "stack", None)
@@ -506,7 +636,7 @@ class DebuggerHarness(object):
#print "Frame: %s %s %s" %(message, frame.f_lineno, filename) #print "Frame: %s %s %s" %(message, frame.f_lineno, filename)
self.message_frame_dict[message] = frame self.message_frame_dict[message] = frame
self.addDict(frameNode, "locals", frame.f_locals, document, 2) self.addDict(frameNode, "locals", frame.f_locals, document, 2)
self.addNode(frameNode, "globals", "", document) self.addNode(frameNode, "globals", frame.f_globals, document)
def getRepr(self, varName, globals, locals): def getRepr(self, varName, globals, locals):
try: try:
@@ -514,101 +644,15 @@ class DebuggerHarness(object):
except: except:
return 'Error: Could not recover value.' return 'Error: Could not recover value.'
def addNode(self, parent_node, name, value, document):
item_node = document.createElement("dict_nv_element")
item_node.setAttribute('value', self.saferepr(value))
item_node.setAttribute('name', str(name))
parent_node.appendChild(item_node)
def addDictAttr(self, root_node, name, thing, document, ply):
dict_node = document.createElement('thing')
root_node.setAttribute('name', name)
root_node.setAttribute('value', str(type(dict)) + " add attr")
self.addDict(root_node, name, thing.__dict__, document, ply) # Not decreminting ply
def saferepr(self, thing): def saferepr(self, thing):
try: try:
return repr(thing) return repr(thing)
except: except:
tp, val, tb = sys.exc_info() tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
return repr(val) return repr(val)
def addDict(self, root_node, name, dict, document, ply):
dict_node = document.createElement('dict')
dict_node.setAttribute('name', name)
dict_node.setAttribute('value', str(type(dict)) + " add dict")
root_node.appendChild(dict_node)
for key in dict.keys():
strkey = str(key)
try:
self.addAny(dict_node, strkey, dict[key], document, ply-1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
print "Error recovering key: ", str(key), " from node ", str(name), " Val = ", str(val)
traceback.print_exception(tp, val, tb)
self.addAny(dict_node, strkey, "Exception getting " + str(name) + "[" + strkey + "]: " + str(val), document, ply -1)
def addClass(self, root_node, name, class_item, document, ply):
item_node = document.createElement('class')
item_node.setAttribute('name', str(name))
root_node.appendChild(item_node)
try:
if hasattr(class_item, '__dict__'):
self.addAny(item_node, '__dict__', class_item.__dict__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
self.addAny(item_node, '__dict__', "Exception getting __dict__: " + str(val), document, ply -1)
try:
if hasattr(class_item, '__name__'):
self.addAny(item_node,'__name__',class_item.__name__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
self.addAny(item_node,'__name__',"Exception getting class.__name__: " + val, document, ply -1)
try:
if hasattr(class_item, '__module__'):
self.addAny(item_node, '__module__', class_item.__module__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
self.addAny(item_node, '__module__', "Exception getting class.__module__: " + val, document, ply -1)
try:
if hasattr(class_item, '__doc__'):
self.addAny(item_node, '__doc__', class_item.__doc__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
self.addAny(item_node, '__doc__', "Exception getting class.__doc__: " + val, document, ply -1)
try:
if hasattr(class_item, '__bases__'):
self.addAny(item_node, '__bases__', class_item.__bases__, document, ply -1)
except:
tp,val,tb=sys.exc_info()
if _VERBOSE:
traceback.print_exception(tp, val, tb)
self.addAny(item_node, '__bases__', "Exception getting class.__bases__: " + val, document, ply -1)
def addModule(self, root_node, name, module_item, document, ply):
item_node = document.createElement('module')
item_node.setAttribute('name', str(name))
root_node.appendChild(item_node)
try:
if hasattr(module_item, '__file__'):
self.addAny(item_node, '__file__', module_item.__file__, document, ply -1)
except:
pass
try:
if hasattr(module_item, '__doc__'):
self.addAny(item_node,'__doc__', module_item.__doc__, document, ply -1)
except:
pass
# The debugger calls this method when it reaches a breakpoint. # The debugger calls this method when it reaches a breakpoint.
def interaction(self, message, frame, info): def interaction(self, message, frame, info):
if _VERBOSE: if _VERBOSE:
@@ -683,6 +727,7 @@ if __name__ == '__main__':
try: try:
harness = DebuggerHarness() harness = DebuggerHarness()
harness.run() harness.run()
harness.do_exit(kill=True)
except SystemExit: except SystemExit:
print "Exiting..." print "Exiting..."
except: except:

View File

@@ -103,6 +103,8 @@ class OutputReaderThread(threading.Thread):
self._keepGoing = False self._keepGoing = False
start = time.time() start = time.time()
output = "" output = ""
except TypeError:
pass
except: except:
tp, val, tb = sys.exc_info() tp, val, tb = sys.exc_info()
print "Exception in OutputReaderThread.run():", tp, val print "Exception in OutputReaderThread.run():", tp, val
@@ -163,6 +165,7 @@ class Executor:
self._stdOutReader = None self._stdOutReader = None
self._stdErrReader = None self._stdErrReader = None
self._process = None self._process = None
DebuggerService.executors.append(self)
def OutCall(self, text): def OutCall(self, text):
evt = UpdateTextEvent(value = text) evt = UpdateTextEvent(value = text)
@@ -197,6 +200,7 @@ class Executor:
self._stdOutReader.AskToStop() self._stdOutReader.AskToStop()
if(self._stdErrReader != None): if(self._stdErrReader != None):
self._stdErrReader.AskToStop() self._stdErrReader.AskToStop()
DebuggerService.executors.remove(self)
class RunCommandUI(wx.Panel): class RunCommandUI(wx.Panel):
@@ -371,7 +375,7 @@ class DebugCommandUI(wx.Panel):
def ShutdownAllDebuggers(): def ShutdownAllDebuggers():
for debugger in DebugCommandUI.debuggers: for debugger in DebugCommandUI.debuggers:
debugger.StopExecution() debugger.StopExecution(None)
ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers) ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
@@ -428,7 +432,6 @@ class DebugCommandUI(wx.Panel):
self._parentNoteBook = parent self._parentNoteBook = parent
self._command = command self._command = command
self._textCtrl = None
self._service = service self._service = service
self._executor = None self._executor = None
self.STEP_ID = wx.NewId() self.STEP_ID = wx.NewId()
@@ -490,18 +493,10 @@ class DebugCommandUI(wx.Panel):
tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane")) tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane"))
wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput) wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput)
tb.Realize()
self.framesTab = None self.framesTab = None
self.DisableWhileDebuggerRunning() self.DisableWhileDebuggerRunning()
self._notebook = wx.Notebook(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.LB_DEFAULT, "Debugger") self.framesTab = self.MakeFramesUI(self, wx.NewId(), None)
sizer.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId(), None)
self.framesTab = self.MakeFramesTab(self._notebook, wx.NewId(), None)
self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId(), None)
self._notebook.AddPage(self.consoleTab, "Output")
self._notebook.AddPage(self.framesTab, "Frames")
self._notebook.AddPage(self.breakPointsTab, "Break Points")
self._statusBar = wx.StatusBar( self, -1) self._statusBar = wx.StatusBar( self, -1)
self._statusBar.SetFieldsCount(1) self._statusBar.SetFieldsCount(1)
sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
@@ -509,6 +504,7 @@ class DebugCommandUI(wx.Panel):
self.SetStatusText("Starting debug...") self.SetStatusText("Starting debug...")
self.SetSizer(sizer) self.SetSizer(sizer)
tb.Realize()
sizer.Fit(self) sizer.Fit(self)
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST) self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST)
@@ -550,14 +546,12 @@ class DebugCommandUI(wx.Panel):
def BreakPointChange(self): def BreakPointChange(self):
if not self._stopped: if not self._stopped:
self._callback.pushBreakpoints() self._callback.pushBreakpoints()
self.breakPointsTab.PopulateBPList() self.framesTab.PopulateBPList()
def __del__(self): def __del__(self):
if self in DebugCommandUI.debuggers: if self in DebugCommandUI.debuggers:
DebugCommandUI.debuggers.remove(self) DebugCommandUI.debuggers.remove(self)
def SwitchToOutputTab(self):
self._notebook.SetSelection(0)
def DisableWhileDebuggerRunning(self): def DisableWhileDebuggerRunning(self):
self._tb.EnableTool(self.STEP_ID, False) self._tb.EnableTool(self.STEP_ID, False)
@@ -573,7 +567,6 @@ class DebugCommandUI(wx.Panel):
openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
if self.framesTab: if self.framesTab:
self.framesTab.ClearWhileRunning() self.framesTab.ClearWhileRunning()
#wx.GetApp().ProcessPendingEvents() #Yield(True)
def EnableWhileDebuggerStopped(self): def EnableWhileDebuggerStopped(self):
self._tb.EnableTool(self.STEP_ID, True) self._tb.EnableTool(self.STEP_ID, True)
@@ -583,8 +576,6 @@ class DebugCommandUI(wx.Panel):
if _WATCHES_ON: if _WATCHES_ON:
self._tb.EnableTool(self.ADD_WATCH_ID, True) self._tb.EnableTool(self.ADD_WATCH_ID, True)
self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False) self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
#if _WINDOWS:
# wx.GetApp().GetTopWindow().RequestUserAttention()
def ExecutorFinished(self): def ExecutorFinished(self):
if _VERBOSE: print "In ExectorFinished" if _VERBOSE: print "In ExectorFinished"
@@ -689,60 +680,25 @@ class DebugCommandUI(wx.Panel):
self._parentNoteBook.GetPage(index).Show(False) self._parentNoteBook.GetPage(index).Show(False)
self._parentNoteBook.RemovePage(index) self._parentNoteBook.RemovePage(index)
def GetConsoleTextControl(self):
return self._textCtrl
def OnClearOutput(self, event):
self._textCtrl.SetReadOnly(False)
self._textCtrl.ClearAll()
self._textCtrl.SetReadOnly(True)
def OnAddWatch(self, event): def OnAddWatch(self, event):
if self.framesTab: if self.framesTab:
self.framesTab.OnWatch(event) self.framesTab.OnWatch(event)
def MakeConsoleTab(self, parent, id, debugger): def MakeFramesUI(self, parent, id, debugger):
panel = wx.Panel(parent, id)
sizer = wx.BoxSizer(wx.HORIZONTAL)
self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self._textCtrl.SetViewLineNumbers(False)
self._textCtrl.SetReadOnly(True)
if wx.Platform == '__WXMSW__':
font = "Courier New"
else:
font = "Courier"
self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
panel.SetSizer(sizer)
sizer.Fit(panel)
return panel
def MakeFramesTab(self, parent, id, debugger):
panel = FramesUI(parent, id, self) panel = FramesUI(parent, id, self)
return panel return panel
def MakeBreakPointsTab(self, parent, id, debugger):
panel = BreakpointsUI(parent, id, self)
return panel
def AppendText(self, event): def AppendText(self, event):
self._textCtrl.SetReadOnly(False) self.framesTab.AppendText(event.value)
self._textCtrl.AddText(event.value)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetReadOnly(True)
def AppendErrorText(self, event): def AppendErrorText(self, event):
self._textCtrl.SetReadOnly(False) self.framesTab.AppendErrorText(event.value)
self._textCtrl.SetFontColor(wx.RED)
self._textCtrl.StyleClearAll() def OnClearOutput(self, event):
self._textCtrl.AddText(event.value) self.framesTab.ClearOutput()
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetFontColor(wx.BLACK) def SwitchToOutputTab(self):
self._textCtrl.StyleClearAll() self.framesTab.SwitchToOutputTab()
self._textCtrl.SetReadOnly(True)
class BreakpointsUI(wx.Panel): class BreakpointsUI(wx.Panel):
def __init__(self, parent, id, ui): def __init__(self, parent, id, ui):
@@ -753,7 +709,6 @@ class BreakpointsUI(wx.Panel):
self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID) self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID)
self.syncLineID = wx.NewId() self.syncLineID = wx.NewId()
self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID) self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID)
sizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
p1 = self p1 = self
self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT) self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT)
@@ -768,6 +723,11 @@ class BreakpointsUI(wx.Panel):
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl) self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl)
def OnLeftDoubleClick(event):
self.SyncBPLine(event)
wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick)
self.PopulateBPList() self.PopulateBPList()
p1.SetSizer(sizer) p1.SetSizer(sizer)
@@ -903,25 +863,24 @@ class FramesUI(wx.SplitterWindow):
def __init__(self, parent, id, ui): def __init__(self, parent, id, ui):
wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D) wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
self._ui = ui self._ui = ui
sizer = wx.BoxSizer(wx.VERTICAL)
self._p1 = p1 = wx.ScrolledWindow(self, -1) self._p1 = p1 = wx.ScrolledWindow(self, -1)
p1.Bind(wx.EVT_SIZE, self.OnSize)
self._framesListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(250,150), style=wx.LC_REPORT) sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self._framesListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) framesLabel = wx.StaticText(self, -1, "Stack Frame:")
self._framesListCtrl.InsertColumn(0, "Frame") sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2)
self._framesListCtrl.SetColumnWidth(0, 250)
self._framesListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick) self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "])
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._framesListCtrl) sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._framesListCtrl) self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl)
sizer2 = wx.BoxSizer(wx.VERTICAL) sizer2 = wx.BoxSizer(wx.VERTICAL)
self._p2 = p2 = wx.ScrolledWindow(self, -1) p1.SetSizer(sizer2)
p2.Bind(wx.EVT_SIZE, self.OnSize)
self._treeCtrl = wx.gizmos.TreeListCtrl(p2, -1, size=(530,250), style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT) self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick) self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
sizer2.Add(self._framesListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
tree = self._treeCtrl tree = self._treeCtrl
tree.AddColumn("Thing") tree.AddColumn("Thing")
tree.AddColumn("Value") tree.AddColumn("Value")
@@ -930,11 +889,80 @@ class FramesUI(wx.SplitterWindow):
tree.SetColumnWidth(1, 355) tree.SetColumnWidth(1, 355)
self._root = tree.AddRoot("Frame") self._root = tree.AddRoot("Frame")
tree.SetItemText(self._root, "", 1) tree.SetItemText(self._root, "", 1)
tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback)
self._p2 = p2 = wx.Window(self, -1)
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
p2.SetSizer(sizer3)
p2.Bind(wx.EVT_SIZE, self.OnSize)
self._notebook = wx.Notebook(p2, -1, size=(20,20))
self._notebook.Hide()
sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId())
#self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
self._notebook.AddPage(self.consoleTab, "Output")
#self._notebook.AddPage(self.inspectConsoleTab, "Interact")
self._notebook.AddPage(self.breakPointsTab, "Break Points")
self.SetMinimumPaneSize(20) self.SetMinimumPaneSize(20)
self.SplitVertically(p1, p2, 250) self.SplitVertically(p1, p2, 550)
self.currentItem = None self.currentItem = None
self.Layout() self._notebook.Show(True)
def PopulateBPList(self):
self.breakPointsTab.PopulateBPList()
def OnSize(self, event):
self._notebook.SetSize(self._p2.GetSize())
def MakeConsoleTab(self, parent, id):
panel = wx.Panel(parent, id)
sizer = wx.BoxSizer(wx.HORIZONTAL)
self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
self._textCtrl.SetViewLineNumbers(False)
self._textCtrl.SetReadOnly(True)
if wx.Platform == '__WXMSW__':
font = "Courier New"
else:
font = "Courier"
self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
panel.SetSizer(sizer)
#sizer.Fit(panel)
return panel
def MakeInspectConsoleTab(self, parent, id):
def OnEnterPressed(event):
print "Enter text was %s" % event.GetString()
def OnText(event):
print "Command was %s" % event.GetString()
panel = wx.Panel(parent, id)
try:
sizer = wx.BoxSizer(wx.HORIZONTAL)
self._ictextCtrl = wx.TextCtrl(panel, wx.NewId(), style=wx.TE_MULTILINE|wx.TE_RICH|wx.HSCROLL)
sizer.Add(self._ictextCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
self._ictextCtrl.Bind(wx.EVT_TEXT_ENTER, OnEnterPressed)
self._ictextCtrl.Bind(wx.EVT_TEXT, OnText)
if wx.Platform == '__WXMSW__':
font = "Courier New"
else:
font = "Courier"
self._ictextCtrl.SetDefaultStyle(wx.TextAttr(font=wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font)))
panel.SetSizer(sizer)
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
return panel
def MakeBreakPointsTab(self, parent, id):
panel = BreakpointsUI(parent, id, self._ui)
return panel
def OnRightClick(self, event): def OnRightClick(self, event):
#Refactor this... #Refactor this...
@@ -944,13 +972,6 @@ class FramesUI(wx.SplitterWindow):
if not _WATCHES_ON and watchOnly: if not _WATCHES_ON and watchOnly:
return return
menu = wx.Menu() menu = wx.Menu()
if not watchOnly:
if not hasattr(self, "introspectID"):
self.introspectID = wx.NewId()
self.Bind(wx.EVT_MENU, self.OnIntrospect, id=self.introspectID)
item = wx.MenuItem(menu, self.introspectID, "Attempt Introspection")
menu.AppendItem(item)
menu.AppendSeparator()
if _WATCHES_ON: if _WATCHES_ON:
if not hasattr(self, "watchID"): if not hasattr(self, "watchID"):
self.watchID = wx.NewId() self.watchID = wx.NewId()
@@ -1016,13 +1037,13 @@ class FramesUI(wx.SplitterWindow):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
try: try:
list = self._framesListCtrl list = self._framesChoiceCtrl
frameNode = self._stack[int(self.currentItem)] frameNode = self._stack[int(self.currentItem)]
message = frameNode.getAttribute("message") message = frameNode.getAttribute("message")
binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain) binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain)
xmldoc = bz2.decompress(binType.data) xmldoc = bz2.decompress(binType.data)
domDoc = parseString(xmldoc) domDoc = parseString(xmldoc)
#wx.MessageBox(xmldoc, "result of introspection")
nodeList = domDoc.getElementsByTagName('replacement') nodeList = domDoc.getElementsByTagName('replacement')
replacementNode = nodeList.item(0) replacementNode = nodeList.item(0)
if len(replacementNode.childNodes): if len(replacementNode.childNodes):
@@ -1030,6 +1051,7 @@ class FramesUI(wx.SplitterWindow):
tree = self._treeCtrl tree = self._treeCtrl
parent = tree.GetItemParent(self._introspectItem) parent = tree.GetItemParent(self._introspectItem)
treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem) treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem)
self._treeCtrl.Expand(treeNode)
tree.Delete(self._introspectItem) tree.Delete(self._introspectItem)
except: except:
tp,val,tb = sys.exc_info() tp,val,tb = sys.exc_info()
@@ -1037,16 +1059,15 @@ class FramesUI(wx.SplitterWindow):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
def OnSize(self, event):
self._treeCtrl.SetSize(self._p2.GetSize())
w,h = self._p1.GetClientSizeTuple()
self._framesListCtrl.SetDimensions(0, 0, w, h)
def ClearWhileRunning(self): def ClearWhileRunning(self):
list = self._framesListCtrl list = self._framesChoiceCtrl
list.DeleteAllItems() list.Clear()
list.Enable(False)
tree = self._treeCtrl tree = self._treeCtrl
tree.Hide() root = self._root
tree.DeleteChildren(root)
#tree.Hide()
def OnListRightClick(self, event): def OnListRightClick(self, event):
if not hasattr(self, "syncFrameID"): if not hasattr(self, "syncFrameID"):
@@ -1059,7 +1080,7 @@ class FramesUI(wx.SplitterWindow):
menu.Destroy() menu.Destroy()
def OnSyncFrame(self, event): def OnSyncFrame(self, event):
list = self._framesListCtrl list = self._framesChoiceCtrl
frameNode = self._stack[int(self.currentItem)] frameNode = self._stack[int(self.currentItem)]
file = frameNode.getAttribute("file") file = frameNode.getAttribute("file")
line = frameNode.getAttribute("line") line = frameNode.getAttribute("line")
@@ -1069,18 +1090,24 @@ class FramesUI(wx.SplitterWindow):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
try: try:
domDoc = parseString(framesXML) domDoc = parseString(framesXML)
list = self._framesListCtrl list = self._framesChoiceCtrl
list.DeleteAllItems() list.Clear()
self._stack = [] self._stack = []
nodeList = domDoc.getElementsByTagName('frame') nodeList = domDoc.getElementsByTagName('frame')
frame_count = -1 frame_count = -1
for index in range(0, nodeList.length): for index in range(0, nodeList.length):
frameNode = nodeList.item(index) frameNode = nodeList.item(index)
message = frameNode.getAttribute("message") message = frameNode.getAttribute("message")
list.InsertStringItem(index, message) list.Append(message)
self._stack.append(frameNode) self._stack.append(frameNode)
frame_count += 1 frame_count += 1
list.Select(frame_count) index = len(self._stack) - 1
list.SetSelection(index)
node = self._stack[index]
self.currentItem = index
self.PopulateTreeFromFrameNode(node)
self.OnSyncFrame(None)
self._p1.FitInside() self._p1.FitInside()
frameNode = nodeList.item(index) frameNode = nodeList.item(index)
file = frameNode.getAttribute("file") file = frameNode.getAttribute("file")
@@ -1092,19 +1119,23 @@ class FramesUI(wx.SplitterWindow):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
def ListItemDeselected(self, event):
pass
def ListItemSelected(self, event): def ListItemSelected(self, event):
self.currentItem = event.m_itemIndex message = event.GetString()
frameNode = self._stack[int(self.currentItem)] index = 0
self.PopulateTreeFromFrameNode(frameNode) for node in self._stack:
# Temporarily doing this to test out automatically swicting to source line. if node.getAttribute("message") == message:
self.currentItem = index
self.PopulateTreeFromFrameNode(node)
self.OnSyncFrame(None) self.OnSyncFrame(None)
return
index = index + 1
def PopulateTreeFromFrameNode(self, frameNode): def PopulateTreeFromFrameNode(self, frameNode):
list = self._framesChoiceCtrl
list.Enable(True)
tree = self._treeCtrl tree = self._treeCtrl
tree.Show(True) #tree.Show(True)
root = self._root root = self._root
tree.DeleteChildren(root) tree.DeleteChildren(root)
children = frameNode.childNodes children = frameNode.childNodes
@@ -1118,6 +1149,19 @@ class FramesUI(wx.SplitterWindow):
tree.Expand(firstChild) tree.Expand(firstChild)
self._p2.FitInside() self._p2.FitInside()
def IntrospectCallback(self, event):
tree = self._treeCtrl
item = event.GetItem()
if _VERBOSE:
print "In introspectCallback item is %s, pydata is %s" % (event.GetItem(), tree.GetPyData(item))
if tree.GetPyData(item) != "Introspect":
event.Skip()
return
self._introspectItem = item
self._parentChain = self.GetItemChain(item)
self.OnIntrospect(event)
event.Skip()
def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None): def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None):
tree = self._treeCtrl tree = self._treeCtrl
if insertBefore != None: if insertBefore != None:
@@ -1125,7 +1169,12 @@ class FramesUI(wx.SplitterWindow):
else: else:
treeNode = tree.AppendItem(parent, name) treeNode = tree.AppendItem(parent, name)
children = node.childNodes children = node.childNodes
if children.length == 0: intro = node.getAttribute('intro')
if intro == "True":
tree.SetItemHasChildren(treeNode, True)
tree.SetPyData(treeNode, "Introspect")
if node.getAttribute("value"):
tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1) tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1)
for index in range(0, children.length): for index in range(0, children.length):
subNode = children.item(index) subNode = children.item(index)
@@ -1136,15 +1185,23 @@ class FramesUI(wx.SplitterWindow):
value = self.StripOuterSingleQuotes(subNode.getAttribute("value")) value = self.StripOuterSingleQuotes(subNode.getAttribute("value"))
n = tree.AppendItem(treeNode, name) n = tree.AppendItem(treeNode, name)
tree.SetItemText(n, value, 1) tree.SetItemText(n, value, 1)
intro = subNode.getAttribute('intro')
if intro == "True":
tree.SetItemHasChildren(n, True)
tree.SetPyData(n, "Introspect")
return treeNode return treeNode
def StripOuterSingleQuotes(self, string): def StripOuterSingleQuotes(self, string):
if string.startswith("'") and string.endswith("'"): if string.startswith("'") and string.endswith("'"):
return string[1:-1] retval = string[1:-1]
elif type(string) == types.UnicodeType: elif string.startswith("\"") and string.endswith("\""):
return string[1:-1] retval = string[1:-1]
else: else:
return string retval = string
if retval.startswith("u'") and retval.endswith("'"):
retval = retval[1:]
return retval
def HasChildren(self, node): def HasChildren(self, node):
try: try:
@@ -1153,6 +1210,30 @@ class FramesUI(wx.SplitterWindow):
tp,val,tb=sys.exc_info() tp,val,tb=sys.exc_info()
return False return False
def AppendText(self, text):
self._textCtrl.SetReadOnly(False)
self._textCtrl.AddText(text)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetReadOnly(True)
def AppendErrorText(self, text):
self._textCtrl.SetReadOnly(False)
self._textCtrl.SetFontColor(wx.RED)
self._textCtrl.StyleClearAll()
self._textCtrl.AddText(text)
self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
self._textCtrl.SetFontColor(wx.BLACK)
self._textCtrl.StyleClearAll()
self._textCtrl.SetReadOnly(True)
def ClearOutput(self, event):
self._textCtrl.SetReadOnly(False)
self._textCtrl.ClearAll()
self._textCtrl.SetReadOnly(True)
def SwitchToOutputTab(self):
self._notebook.SetSelection(0)
class DebuggerView(Service.ServiceView): class DebuggerView(Service.ServiceView):
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
@@ -1417,6 +1498,7 @@ class DebuggerCallback:
if _VERBOSE: print "+"*40 if _VERBOSE: print "+"*40
class DebuggerService(Service.Service): class DebuggerService(Service.Service):
executors = []
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Constants # Constants
@@ -1427,6 +1509,12 @@ class DebuggerService(Service.Service):
DEBUG_ID = wx.NewId() DEBUG_ID = wx.NewId()
DEBUG_WEBSERVER_ID = wx.NewId() DEBUG_WEBSERVER_ID = wx.NewId()
def KillAllRunningProcesses():
execs = DebuggerService.executors
for executor in execs:
executor.DoStopExecution()
KillAllRunningProcesses = staticmethod(KillAllRunningProcesses)
def ComparePaths(first, second): def ComparePaths(first, second):
one = DebuggerService.ExpandPath(first) one = DebuggerService.ExpandPath(first)
two = DebuggerService.ExpandPath(second) two = DebuggerService.ExpandPath(second)
@@ -1614,6 +1702,14 @@ class DebuggerService(Service.Service):
pass pass
def OnDebugWebServer(self, event): def OnDebugWebServer(self, event):
if _WINDOWS and not _PYWIN32_INSTALLED:
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."))
return
if not Executor.GetPythonExecutablePath():
return
if DebugCommandUI.DebuggerRunning():
wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
return
import WebServerService import WebServerService
wsService = wx.GetApp().GetService(WebServerService.WebServerService) wsService = wx.GetApp().GetService(WebServerService.WebServerService)
fileName, args = wsService.StopAndPrepareToDebug() fileName, args = wsService.StopAndPrepareToDebug()

View File

@@ -103,7 +103,7 @@ class FindInDirService(FindService.FindService):
dirCtrl = wx.TextCtrl(frame, -1, config.Read(FIND_MATCHDIR, ""), size=(200,-1)) dirCtrl = wx.TextCtrl(frame, -1, config.Read(FIND_MATCHDIR, ""), size=(200,-1))
dirCtrl.SetToolTipString(dirCtrl.GetValue()) dirCtrl.SetToolTipString(dirCtrl.GetValue())
lineSizer.Add(dirCtrl, 0, wx.LEFT, HALF_SPACE) lineSizer.Add(dirCtrl, 0, wx.LEFT, HALF_SPACE)
findDirButton = wx.Button(frame, -1, "Browse...") findDirButton = wx.Button(frame, -1, _("Browse..."))
lineSizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) lineSizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE)
contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE)

View File

@@ -16,6 +16,8 @@ import wx.lib.pydocview
import sys import sys
import wx.grid import wx.grid
import os.path import os.path
import activegrid.util
_ = wx.GetTranslation _ = wx.GetTranslation
ACTIVEGRID_BASE_IDE = False ACTIVEGRID_BASE_IDE = False
@@ -77,7 +79,11 @@ class IDEApplication(wx.lib.pydocview.DocApp):
import PHPEditor import PHPEditor
import wx.lib.ogl as ogl import wx.lib.ogl as ogl
import DebuggerService import DebuggerService
import atexit
atexit.register(DebuggerService.DebuggerService.KillAllRunningProcesses)
import AboutDialog import AboutDialog
import SVNService
if not ACTIVEGRID_BASE_IDE: if not ACTIVEGRID_BASE_IDE:
import DataModelEditor import DataModelEditor
import ProcessModelEditor import ProcessModelEditor
@@ -287,8 +293,9 @@ class IDEApplication(wx.lib.pydocview.DocApp):
deploymentService = self.InstallService(DeploymentService.DeploymentService()) deploymentService = self.InstallService(DeploymentService.DeploymentService())
dataModelService = self.InstallService(DataModelEditor.DataModelService()) dataModelService = self.InstallService(DataModelEditor.DataModelService())
welcomeService = self.InstallService(WelcomeService.WelcomeService()) welcomeService = self.InstallService(WelcomeService.WelcomeService())
optionsService = self.InstallService(wx.lib.pydocview.DocOptionsService(allowModeChanges=False)) optionsService = self.InstallService(wx.lib.pydocview.DocOptionsService(supportedModes=wx.lib.docview.DOC_MDI))
aboutService = self.InstallService(wx.lib.pydocview.AboutService(AboutDialog.AboutDialog)) aboutService = self.InstallService(wx.lib.pydocview.AboutService(AboutDialog.AboutDialog))
svnService = self.InstallService(SVNService.SVNService())
if not ACTIVEGRID_BASE_IDE: if not ACTIVEGRID_BASE_IDE:
projectService.AddRunHandler(processModelService) projectService.AddRunHandler(processModelService)
@@ -307,6 +314,7 @@ class IDEApplication(wx.lib.pydocview.DocApp):
optionsService.AddOptionsPanel(PHPEditor.PHPOptionsPanel) optionsService.AddOptionsPanel(PHPEditor.PHPOptionsPanel)
optionsService.AddOptionsPanel(STCTextEditor.TextOptionsPanel) optionsService.AddOptionsPanel(STCTextEditor.TextOptionsPanel)
optionsService.AddOptionsPanel(HtmlEditor.HtmlOptionsPanel) optionsService.AddOptionsPanel(HtmlEditor.HtmlOptionsPanel)
optionsService.AddOptionsPanel(SVNService.SVNOptionsPanel)
filePropertiesService.AddCustomEventHandler(projectService) filePropertiesService.AddCustomEventHandler(projectService)
@@ -326,7 +334,6 @@ class IDEApplication(wx.lib.pydocview.DocApp):
propertyService.StartBackgroundTimer() propertyService.StartBackgroundTimer()
self.SetDefaultIcon(getActiveGridIcon()) self.SetDefaultIcon(getActiveGridIcon())
self.SetUseTabbedMDI(True)
if not ACTIVEGRID_BASE_IDE: if not ACTIVEGRID_BASE_IDE:
embeddedWindows = wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT | wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOMLEFT |wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM | wx.lib.pydocview.EMBEDDED_WINDOW_RIGHT embeddedWindows = wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT | wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOMLEFT |wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM | wx.lib.pydocview.EMBEDDED_WINDOW_RIGHT
else: else:
@@ -344,13 +351,17 @@ class IDEApplication(wx.lib.pydocview.DocApp):
if not projectService.OpenSavedProjects() and not docManager.GetDocuments() and self.IsSDI(): # Have to open something if it's SDI and there are no projects... if not projectService.OpenSavedProjects() and not docManager.GetDocuments() and self.IsSDI(): # Have to open something if it's SDI and there are no projects...
projectTemplate.CreateDocument('', wx.lib.docview.DOC_NEW).OnNewDocument() projectTemplate.CreateDocument('', wx.lib.docview.DOC_NEW).OnNewDocument()
TIPS_FILE_PARTS = ("activegrid", "tool", "data", "tips.txt")
tips_path = activegrid.util.mainModuleDir
for segment in TIPS_FILE_PARTS:
tips_path = os.path.join(tips_path, segment)
if not ACTIVEGRID_BASE_IDE: if not ACTIVEGRID_BASE_IDE:
if not welcomeService.RunWelcomeIfFirstTime(): if not welcomeService.RunWelcomeIfFirstTime():
if os.path.exists("activegrid/tool/data/tips.txt"): if os.path.exists(tips_path):
wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider("activegrid/tool/data/tips.txt", 0)) wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0))
else: else:
if os.path.exists("activegrid/tool/data/tips.txt"): if os.path.exists(tips_path):
wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider("activegrid/tool/data/tips.txt", 0)) wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0))
wx.UpdateUIEvent.SetUpdateInterval(200) # Overhead of updating menus was too much. Change to update every 200 milliseconds. wx.UpdateUIEvent.SetUpdateInterval(200) # Overhead of updating menus was too much. Change to update every 200 milliseconds.

View File

@@ -84,6 +84,7 @@ class OutlineView(Service.ServiceView):
item = self.GetControl().GetSelection() item = self.GetControl().GetSelection()
if item: if item:
self.GetControl().CallDoSelectCallback(item) self.GetControl().CallDoSelectCallback(item)
event.Skip()
def ResumeActionOnSelect(self): def ResumeActionOnSelect(self):

View File

@@ -153,7 +153,7 @@ class PHPCtrl(CodeEditor.CodeCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE):
CodeEditor.CodeCtrl.__init__(self, parent, ID, style) CodeEditor.CodeCtrl.__init__(self, parent, ID, style)
self.SetLexer(wx.stc.STC_LEX_HTML) self.SetLexer(wx.stc.STC_LEX_PHP)
self.SetStyleBits(7) self.SetStyleBits(7)
self.SetKeyWords(4, string.join(PHPKEYWORDS)) self.SetKeyWords(4, string.join(PHPKEYWORDS))
self.SetProperty("fold.html", "1") self.SetProperty("fold.html", "1")

View File

@@ -23,9 +23,11 @@ import sys
import activegrid.util.xmlmarshaller import activegrid.util.xmlmarshaller
import UICommon import UICommon
import Wizard import Wizard
import SVNService
from IDE import ACTIVEGRID_BASE_IDE from IDE import ACTIVEGRID_BASE_IDE
if not ACTIVEGRID_BASE_IDE: if not ACTIVEGRID_BASE_IDE:
import ProcessModelEditor import ProcessModelEditor
from SVNService import SVN_INSTALLED
_ = wx.GetTranslation _ = wx.GetTranslation
@@ -127,6 +129,8 @@ class ProjectDocument(wx.lib.docview.Document):
for path in paths: for path in paths:
if path.startswith(curPath): if path.startswith(curPath):
path = "." + path[curPathLen:] # use relative path path = "." + path[curPathLen:] # use relative path
if os.sep != '/':
path = path.replace(os.sep, '/', -1) # always save out with '/' as path separator for cross-platform compatibility.
else: else:
pass # use absolute path pass # use absolute path
newFilePaths.append(path) newFilePaths.append(path)
@@ -911,6 +915,15 @@ class ProjectView(wx.lib.docview.View):
return self._GetItemFile(item) return self._GetItemFile(item)
def GetSelectedFiles(self):
filenames = []
for item in self._treeCtrl.GetSelections():
filename = self._GetItemFile(item)
if filename and filename not in filenames:
filenames.append(filename)
return filenames
def AddProjectToView(self, document): def AddProjectToView(self, document):
rootItem = self._treeCtrl.GetRootItem() rootItem = self._treeCtrl.GetRootItem()
projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document)) projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document))
@@ -927,6 +940,17 @@ class ProjectView(wx.lib.docview.View):
document.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame())) document.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame()))
def HasFocus(self):
winWithFocus = wx.Window.FindFocus()
if not winWithFocus:
return False
while winWithFocus:
if winWithFocus == self._treeCtrl:
return True
winWithFocus = winWithFocus.GetParent()
return False
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Control events # Control events
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
@@ -980,7 +1004,7 @@ class ProjectView(wx.lib.docview.View):
def OnAddDirToProject(self, event): def OnAddDirToProject(self, event):
frame = wx.Dialog(None, -1, _("Add All Files from Directory to Project"), size= (320,200)) frame = wx.Dialog(None, -1, _("Add Directory Files to Project"), size= (320,200))
contentSizer = wx.BoxSizer(wx.VERTICAL) contentSizer = wx.BoxSizer(wx.VERTICAL)
flexGridSizer = wx.FlexGridSizer(cols = 2, vgap=HALF_SPACE, hgap=HALF_SPACE) flexGridSizer = wx.FlexGridSizer(cols = 2, vgap=HALF_SPACE, hgap=HALF_SPACE)
@@ -989,7 +1013,7 @@ class ProjectView(wx.lib.docview.View):
dirCtrl = wx.TextCtrl(frame, -1, os.path.dirname(self.GetDocument().GetFilename()), size=(250,-1)) dirCtrl = wx.TextCtrl(frame, -1, os.path.dirname(self.GetDocument().GetFilename()), size=(250,-1))
dirCtrl.SetToolTipString(dirCtrl.GetValue()) dirCtrl.SetToolTipString(dirCtrl.GetValue())
lineSizer.Add(dirCtrl, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) lineSizer.Add(dirCtrl, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
findDirButton = wx.Button(frame, -1, "Browse...") findDirButton = wx.Button(frame, -1, _("Browse..."))
lineSizer.Add(findDirButton, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, HALF_SPACE) lineSizer.Add(findDirButton, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, HALF_SPACE)
flexGridSizer.Add(lineSizer, 1, wx.EXPAND) flexGridSizer.Add(lineSizer, 1, wx.EXPAND)
@@ -1178,7 +1202,10 @@ class ProjectView(wx.lib.docview.View):
else: # Project context else: # Project context
itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None] itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None]
menuBar = self._GetParentFrame().GetMenuBar() menuBar = self._GetParentFrame().GetMenuBar()
itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT, None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, ProjectService.RENAME_ID, ProjectService.DELETE_FILE_ID, None, wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID] itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT]
if SVN_INSTALLED:
itemIDs = itemIDs + [None, SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID]
itemIDs = itemIDs + [None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, ProjectService.RENAME_ID, ProjectService.DELETE_FILE_ID, None, wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID]
for itemID in itemIDs: for itemID in itemIDs:
if not itemID: if not itemID:
menu.AppendSeparator() menu.AppendSeparator()
@@ -1384,8 +1411,9 @@ class ProjectView(wx.lib.docview.View):
findFile.Destroy() findFile.Destroy()
if newpath: if newpath:
# update Project Model with new location # update Project Model with new location
self.GetDocument().RemoveFile(filepath) project = self._GetItemProject(item)
self.GetDocument().AddFile(newpath) project.RemoveFile(filepath)
project.AddFile(newpath)
filepath = newpath filepath = newpath
doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT) doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT)
@@ -1614,9 +1642,8 @@ class ProjectPropertiesDialog(wx.Dialog):
sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE) sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE) sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
sizer.Fit(self)
self.SetDimensions(-1, -1, 310, -1, wx.SIZE_USE_EXISTING)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
self.Layout() self.Layout()
@@ -1742,7 +1769,7 @@ class ProjectService(Service.Service):
wx.EVT_MENU(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessEvent) wx.EVT_MENU(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
if not menuBar.FindItemById(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID): if not menuBar.FindItemById(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID):
projectMenu.Append(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, _("Add All Files to Project..."), _("Adds a directory's documents to the current project")) projectMenu.Append(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project"))
wx.EVT_MENU(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessEvent) wx.EVT_MENU(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) wx.EVT_UPDATE_UI(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
if not menuBar.FindItemById(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID): if not menuBar.FindItemById(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID):

View File

@@ -194,9 +194,14 @@ class TextView(wx.lib.docview.View):
if activate and self.GetCtrl(): if activate and self.GetCtrl():
# In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI: if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
self.GetCtrl().SetFocus() self.SetFocus()
else: else:
wx.CallAfter(self.GetCtrl().SetFocus) wx.CallAfter(self.SetFocus)
def SetFocus(self):
if self.GetCtrl():
self.GetCtrl().SetFocus()
def OnClose(self, deleteWindow = True): def OnClose(self, deleteWindow = True):

View File

@@ -0,0 +1,736 @@
#----------------------------------------------------------------------------
# Name: SVNService.py
# Purpose: Subversion Service for pydocview
#
# Author: Morgan Hua
#
# Created: 5/13/05
# CVS-ID: $Id$
# Copyright: (c) 2005 ActiveGrid, Inc.
# License: wxWindows License
#----------------------------------------------------------------------------
import wx
import os.path
import ProjectEditor
import MessageService
import sys # for errors
import traceback # for errors
try:
import pysvn # python-subversion integration
SVN_INSTALLED = True
except ImportError:
SVN_INSTALLED = False
_ = wx.GetTranslation
#----------------------------------------------------------------------------
# Constants
#----------------------------------------------------------------------------
SVN_CONFIG_DIR = "SVNConfigDir"
SVN_REPOSITORY_URL = "SVNRepositoryURL"
SPACE = 10
HALF_SPACE = 5
#----------------------------------------------------------------------------
# Classes
#----------------------------------------------------------------------------
class SVNService(wx.lib.pydocview.DocService):
SVN_UPDATE_ID = wx.NewId()
SVN_CHECKIN_ID = wx.NewId()
SVN_CHECKOUT_ID = wx.NewId()
SVN_REVERT_ID = wx.NewId()
SVN_ADD_ID = wx.NewId()
SVN_DELETE_ID = wx.NewId()
SVN_COMMAND_LIST = [SVN_UPDATE_ID, SVN_CHECKIN_ID, SVN_CHECKOUT_ID, SVN_REVERT_ID, SVN_ADD_ID, SVN_DELETE_ID]
def __init__(self):
self._defaultURL = "svn://"
global SVN_INSTALLED
if SVN_INSTALLED:
config = wx.ConfigBase_Get()
configDir = config.Read(SVN_CONFIG_DIR, "")
self._client = pysvn.Client(configDir)
try:
self._defaultURL = self._client.info('.').url
except:
pass
self._client.callback_cancel = self.IfCancel
self._client.callback_notify = self.UpdateStatus
self._client.callback_get_log_message = self.GetLogMessage
self._client.callback_get_login = self.GetLogin
self._client.callback_ssl_server_trust_prompt = self.GetSSLServerTrust
self._client.callback_ssl_client_cert_password_prompt = self.SSLClientPassword
self._client.callback_ssl_client_cert_prompt = self.SSLClientCert
self._client.callback_ssl_server_prompt = self.SSLServerPrompt
#----------------------------------------------------------------------------
# pysvn.Client() Callback Methods
#----------------------------------------------------------------------------
def IfCancel(self):
""" return True if user wants to cancel current command """
return False
def UpdateStatus(self, eventDict):
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.AddLines(_("%s %s\n") % (eventDict['action'], eventDict['path']))
def GetLogMessage(self):
dlg = wx.TextEntryDialog(wx.GetApp().GetTopWindow(),
_("Comment"),
_("SVN Log Message"))
if dlg.ShowModal() == wx.ID_OK:
retcode = True
message = dlg.GetValue()
else:
retcode = False
message = _("Cancel Action")
dlg.Destroy()
return retcode, message
def GetLogin(self, realm, username, maySave):
dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Login"))
sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
sizer.Add(wx.StaticText(dlg, -1, _("Username:")), 0, wx.ALIGN_CENTER_VERTICAL)
usernameTxt = wx.TextCtrl(dlg, -1, username, size = (200, -1))
sizer.Add(usernameTxt, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(wx.StaticText(dlg, -1, _("Password:")), 0, wx.ALIGN_CENTER_VERTICAL)
passwordTxt = wx.TextCtrl(dlg, -1, size=(200, -1), style=wx.TE_PASSWORD)
sizer.Add(passwordTxt, 0, wx.ALIGN_CENTER_VERTICAL)
savePasswordCheckbox = wx.CheckBox(dlg, -1, _("Remember Username and Password"))
if not maySave:
savePasswordCheckbox.Enable(False)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
okBtn = wx.Button(dlg, wx.ID_OK)
okBtn.SetDefault()
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
contentSizer = wx.BoxSizer(wx.VERTICAL)
contentSizer.Add(sizer, 0, wx.LEFT|wx.TOP|wx.RIGHT, SPACE)
contentSizer.Add(savePasswordCheckbox, 0, wx.TOP|wx.LEFT|wx.BOTTOM, SPACE)
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
dlg.SetSizer(contentSizer)
dlg.Fit()
dlg.Layout()
if dlg.ShowModal() == wx.ID_OK:
retcode = True
username = usernameTxt.GetValue().strip()
password = passwordTxt.GetValue()
save = savePasswordCheckBox.IsChecked()
else:
retcode = False
username = None
password = None
save = False
dlg.Destroy()
return retcode, username, password, save
def SSLServerPrompt(self):
""" Not implemented, as per pysvn documentation """
return
def GetSSLServerTrust(self, trustDict):
dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SSL Server Certificate"))
sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
for k in ['hostname', 'valid_from', 'valid_to', 'issuer_dname', 'realm']:
if trustDict.has_key(k):
sizer.Add(wx.StaticText(dlg, -1, "%s:" % k), 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(wx.StaticText(dlg, -1, "%s" % trustDict[k]), 0, wx.ALIGN_CENTER_VERTICAL)
box = wx.StaticBoxSizer(wx.StaticBox(dlg, -1, _("Certificate Info")), wx.VERTICAL)
box.Add(sizer, 0, wx.EXPAND)
certRadio = wx.RadioBox(dlg, -1, _("Certificate"), choices=[_("Accept Always"), _("Accept Once"), _("Reject")], majorDimension=1, style=wx.RA_SPECIFY_COLS)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
okBtn = wx.Button(dlg, wx.ID_OK)
okBtn.SetDefault()
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
contentSizer = wx.BoxSizer(wx.VERTICAL)
contentSizer.Add(box, 0, wx.TOP|wx.LEFT|wx.RIGHT|wx.EXPAND, SPACE)
contentSizer.Add(certRadio, 0, wx.TOP|wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, SPACE)
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
dlg.SetSizer(contentSizer)
dlg.Fit()
dlg.Layout()
# default values for reject
retcode = False
acceptedFailures = 0
save = False
if dlg.ShowModal() == wx.ID_OK:
cert = certRadio.GetStringSelection()
if cert == _("Accept Always"):
retcode = True
acceptedFailures = trustDict.get('failures')
save = True
elif cert == _("Accept Once"):
retcode = True
acceptedFailures = trustDict.get('failures')
save = False
return retcode, acceptedFailures, save
def SSLClientPassword(self, realm, maySave):
dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SSL Client Certificate Login"))
sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
sizer.Add(wx.StaticText(dlg, -1, _("Realm:")), 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(wx.StaticText(dlg, -1, realm), 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(wx.StaticText(dlg, -1, _("Password:")), 0, wx.ALIGN_CENTER_VERTICAL)
passwordTxt = wx.TextCtrl(dlg, -1, size=(200, -1), style=wx.TE_PASSWORD)
sizer.Add(passwordTxt, 0, wx.ALIGN_CENTER_VERTICAL)
savePasswordCheckbox = wx.CheckBox(dlg, -1, _("Remember Password"))
if not maySave:
savePasswordCheckbox.Enable(False)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
okBtn = wx.Button(dlg, wx.ID_OK)
okBtn.SetDefault()
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
contentSizer = wx.BoxSizer(wx.VERTICAL)
contentSizer.Add(sizer, 0, wx.LEFT|wx.TOP|wx.RIGHT, SPACE)
contentSizer.Add(savePasswordCheckbox, 0, wx.TOP|wx.LEFT|wx.BOTTOM, SPACE)
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
dlg.SetSizer(contentSizer)
dlg.Fit()
dlg.Layout()
if dlg.ShowModal() == wx.ID_OK:
retcode = True
password = passwordTxt.GetValue()
save = savePasswordCheckBox.IsChecked()
else:
retcode = False
password = None
save = False
dlg.Destroy()
return retcode, password, save
def SSLClientCert(self):
dlg = wx.FileDialog(wx.GetApp().GetTopWindow(),
message="Choose certificate", defaultDir=os.getcwd(),
style=wx.OPEN|wx.CHANGE_DIR
)
if dlg.ShowModal() == wx.ID_OK:
retcode = True
certfile = dlg.GetPath()
else:
retcode = False
certfile = None
dlg.Destroy()
return retcode, certfile
#----------------------------------------------------------------------------
# Service Methods
#----------------------------------------------------------------------------
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
menu = menuBar.GetMenu(menuBar.FindMenu(_("Project")))
menu.AppendSeparator()
wx.EVT_MENU(frame, SVNService.SVN_UPDATE_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_UPDATE_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_UPDATE_ID, _("SVN Update"), _("Update file from Subversion"))
wx.EVT_MENU(frame, SVNService.SVN_CHECKIN_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_CHECKIN_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_CHECKIN_ID, _("SVN Commit..."), _("Commit file changes to Subversion"))
wx.EVT_MENU(frame, SVNService.SVN_CHECKOUT_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_CHECKOUT_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_CHECKOUT_ID, _("SVN Checkout..."), _("Checkout file from Subversion"))
wx.EVT_MENU(frame, SVNService.SVN_REVERT_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_REVERT_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_REVERT_ID, _("SVN Revert"), _("Revert file from Subversion"))
menu.AppendSeparator()
wx.EVT_MENU(frame, SVNService.SVN_ADD_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_ADD_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_ADD_ID, _("SVN Add"), _("Add file to Subversion"))
wx.EVT_MENU(frame, SVNService.SVN_DELETE_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_DELETE_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_DELETE_ID, _("SVN Delete"), _("Delete file from Subversion"))
def ProcessEvent(self, event):
id = event.GetId()
if not SVN_INSTALLED:
if id in SVNService.SVN_COMMAND_LIST:
wx.MessageBox(_("pysvn not found. Please install pysvn"), _("Python Subversion"))
return True
return False
if id == SVNService.SVN_UPDATE_ID:
filenames = self.GetCurrentDocuments()
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.ClearLines()
view.AddLines(_("SVN Update:\n"))
for filename in filenames:
view.AddLines("%s\n" % filename)
try:
status = self._client.update(filename)
if status.number > 0:
view.AddLines(_("Updated to revision %s\n") % status.number)
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for doc in openDocs:
if doc.GetFilename() == filename:
yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(),
_("Updated file '%s' is currently open. Close it?") % os.path.basename(filename),
_("Close File"),
wx.YES_NO|wx.ICON_QUESTION)
if yesNoMsg.ShowModal() == wx.ID_YES:
doc.DeleteAllViews()
break
else:
view.AddLines(_("Update failed.\n"))
except pysvn.ClientError, e:
view.AddLines("%s\n" % str(e))
wx.MessageBox(str(e), _("SVN Update"), wx.OK | wx.ICON_EXCLAMATION)
except:
extype, ex, tb = sys.exc_info()
view.AddLines("Update failed: (%s) %s\n" % (extype, str(ex)))
for line in traceback.format_tb(tb):
view.AddLines(line)
wx.MessageBox(_("Update failed."), _("SVN Update"), wx.OK | wx.ICON_EXCLAMATION)
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
return True
elif id == SVNService.SVN_CHECKIN_ID:
filenames = self.GetCurrentDocuments()
# ask user if dirty files should be saved first
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for filename in filenames:
for doc in openDocs:
if doc.GetFilename() == filename and doc.IsModified():
yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(),
_("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename),
_("SVN Commit"),
wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
status = yesNoMsg.ShowModal()
if status == wx.ID_YES:
doc.Save()
elif status == wx.ID_NO:
pass
else: # elif status == wx.CANCEL:
return True
break
shortFilenames = []
for i, filename in enumerate(filenames):
shortFilename = os.path.basename(filename)
shortFilenames.append(shortFilename)
dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Commit"))
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.StaticText(dlg, -1, _("Comment:")), 0, wx.ALIGN_CENTER_VERTICAL)
commentText = wx.TextCtrl(dlg, -1, size=(250,-1), style=wx.TE_MULTILINE)
sizer.Add(commentText, 1, wx.EXPAND|wx.TOP, HALF_SPACE)
sizer.Add(wx.StaticText(dlg, -1, _("Files:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, SPACE)
fileList = wx.CheckListBox(dlg, -1, choices = shortFilenames)
for i in range(fileList.GetCount()):
fileList.Check(i, True)
sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
okBtn = wx.Button(dlg, wx.ID_OK)
okBtn.SetDefault()
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
contentSizer = wx.BoxSizer(wx.VERTICAL)
contentSizer.Add(sizer, 0, wx.ALL, SPACE)
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
dlg.SetSizer(contentSizer)
dlg.Fit()
dlg.Layout()
if dlg.ShowModal() == wx.ID_OK:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.ClearLines()
view.AddLines(_("SVN Commit:\n"))
try:
selFilenames = []
for i in range(fileList.GetCount()):
if fileList.IsChecked(i):
selFilenames.append(filenames[i])
view.AddLines("%s\n" % filenames[i])
if len(selFilenames):
comment = commentText.GetValue()
status = self._client.checkin(selFilenames, comment)
if status is None:
view.AddLines(_("Nothing to commit.\n"))
elif status.number > 0:
view.AddLines(_("Committed as revision %s.\n") % status.number)
else:
view.AddLines(_("Commit failed.\n"))
except pysvn.ClientError, e:
view.AddLines("%s\n" % str(e))
wx.MessageBox(str(e), _("SVN Commit"), wx.OK | wx.ICON_EXCLAMATION)
except:
extype, ex, tb = sys.exc_info()
view.AddLines("Commit failed: (%s) %s\n" % (extype, str(ex)))
for line in traceback.format_tb(tb):
view.AddLines(line)
wx.MessageBox(_("Commit failed."), _("SVN Commit"), wx.OK | wx.ICON_EXCLAMATION)
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
dlg.Destroy()
return True
elif id == SVNService.SVN_CHECKOUT_ID:
config = wx.ConfigBase_Get()
svnUrl = config.Read(SVN_REPOSITORY_URL, self._defaultURL)
dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Checkout"))
gridSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
gridSizer.Add(wx.StaticText(dlg, -1, _("Repository URL:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, HALF_SPACE)
svnURLText = wx.TextCtrl(dlg, -1, svnUrl, size = (200, -1))
svnURLText.SetToolTipString(svnUrl)
gridSizer.Add(svnURLText, 0)
gridSizer.Add(wx.StaticText(dlg, -1, _("Checkout to dir:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, HALF_SPACE)
localPath = wx.TextCtrl(dlg, -1, size = (200, -1))
localPath.SetToolTipString(_("Path in local file system where files will be located."))
findDirButton = wx.Button(dlg, -1, _("Browse..."))
def OnBrowseButton(event):
dirDlg = wx.DirDialog(wx.GetApp().GetTopWindow(), _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE)
dir = localPath.GetValue()
if len(dir):
dirDlg.SetPath(dir)
if dirDlg.ShowModal() == wx.ID_OK:
localPath.SetValue(dirDlg.GetPath())
localPath.SetToolTipString(localPath.GetValue())
localPath.SetInsertionPointEnd()
dirDlg.Destroy()
wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(localPath, 1, wx.EXPAND)
sizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE)
gridSizer.Add(sizer, 0)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
okBtn = wx.Button(dlg, wx.ID_OK)
okBtn.SetDefault()
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
contentSizer = wx.BoxSizer(wx.VERTICAL)
contentSizer.Add(gridSizer, 0, wx.ALL, SPACE)
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
dlg.SetSizer(contentSizer)
dlg.Fit()
dlg.Layout()
if dlg.ShowModal() == wx.ID_OK:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.ClearLines()
view.AddLines(_("SVN Checkout:\n"))
svnUrl = svnURLText.GetValue()
toLocation = localPath.GetValue()
try:
self._client.checkout(svnUrl, toLocation)
view.AddLines(_("Checkout completed.\n"))
except pysvn.ClientError, e:
view.AddLines(_("Checkout failed. %s\n") % str(e))
wx.MessageBox(_("Checkout failed. %s") % str(e), _("SVN Checkout"), wx.OK | wx.ICON_EXCLAMATION)
except:
extype, ex, tb = sys.exc_info()
view.AddLines("Checkout failed: (%s) %s\n" % (extype, str(ex)))
for line in traceback.format_tb(tb):
view.AddLines(line)
wx.MessageBox(_("Checkout failed."), _("SVN Checkout"), wx.OK | wx.ICON_EXCLAMATION)
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
dlg.Destroy()
return True
elif id == SVNService.SVN_REVERT_ID:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
filenames = self.GetCurrentDocuments()
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.ClearLines()
view.AddLines(_("SVN Revert:\n"))
for filename in filenames:
view.AddLines("%s\n" % filename)
try:
self._client.revert(filenames)
view.AddLines(_("Revert completed.\n"))
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for doc in openDocs[:]: # need to make a copy of the list otherwise ordinality changes as we close the files
if doc.GetFilename() in filenames:
yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(),
_("Reverted file '%s' is currently open. Close it?") % os.path.basename(doc.GetFilename()),
_("Close File"),
wx.YES_NO|wx.ICON_QUESTION)
if yesNoMsg.ShowModal() == wx.ID_YES:
doc.DeleteAllViews()
except pysvn.ClientError, e:
view.AddLines("%s\n" % str(e))
wx.MessageBox(str(e), _("SVN Revert"), wx.OK | wx.ICON_EXCLAMATION)
except:
extype, ex, tb = sys.exc_info()
view.AddLines("Revert failed: (%s) %s\n" % (extype, str(ex)))
for line in traceback.format_tb(tb):
view.AddLines(line)
wx.MessageBox(_("Revert failed."), _("SVN Revert"), wx.OK | wx.ICON_EXCLAMATION)
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
return True
elif id == SVNService.SVN_ADD_ID:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
filenames = self.GetCurrentDocuments()
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.ClearLines()
view.AddLines(_("SVN Add:\n"))
for filename in filenames:
view.AddLines("%s\n" % filename)
try:
self._client.add(filenames)
view.AddLines(_("Add completed.\n"))
except pysvn.ClientError, e:
view.AddLines("%s\n" % str(e))
wx.MessageBox(str(e), _("SVN Add"), wx.OK | wx.ICON_EXCLAMATION)
except:
extype, ex, tb = sys.exc_info()
view.AddLines("Add failed: (%s) %s\n" % (extype, str(ex)))
for line in traceback.format_tb(tb):
view.AddLines(line)
wx.MessageBox(_("Add failed."), _("SVN Add"), wx.OK | wx.ICON_EXCLAMATION)
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
return True
elif id == SVNService.SVN_DELETE_ID:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
filenames = self.GetCurrentDocuments()
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
view.ClearLines()
view.AddLines(_("SVN Delete:\n"))
for filename in filenames:
view.AddLines("%s\n" % filename)
try:
self._client.remove(filenames)
view.AddLines(_("Delete completed.\n"))
except pysvn.ClientError, e:
view.AddLines("%s\n" % str(e))
wx.MessageBox(str(e), _("SVN Delete"), wx.OK | wx.ICON_EXCLAMATION)
except:
extype, ex, tb = sys.exc_info()
view.AddLines("Delete failed: (%s) %s\n" % (extype, str(ex)))
for line in traceback.format_tb(tb):
view.AddLines(line)
wx.MessageBox(_("Delete failed."), _("SVN Delete"), wx.OK | wx.ICON_EXCLAMATION)
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
return True
return False
def ProcessUpdateUIEvent(self, event):
id = event.GetId()
if id in [SVNService.SVN_UPDATE_ID,
SVNService.SVN_CHECKIN_ID,
SVNService.SVN_REVERT_ID,
SVNService.SVN_ADD_ID,
SVNService.SVN_DELETE_ID]:
if self.GetCurrentDocuments():
event.Enable(True)
else:
event.Enable(False)
return True
elif id == SVNService.SVN_CHECKOUT_ID:
event.Enable(True)
return True
return False
def GetCurrentDocuments(self):
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
if projectService:
projView = projectService.GetView()
if projView.HasFocus():
filenames = projView.GetSelectedFiles()
if len(filenames):
return filenames
else:
return None
doc = wx.GetApp().GetTopWindow().GetDocumentManager().GetCurrentDocument()
if doc:
filenames = [doc.GetFilename()]
else:
filenames = None
return filenames
class SVNOptionsPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
config = wx.ConfigBase_Get()
svnService = wx.GetApp().GetService(SVNService)
svnUrl = config.Read(SVN_REPOSITORY_URL, svnService._defaultURL)
configDir = config.Read(SVN_CONFIG_DIR, "")
borderSizer = wx.BoxSizer(wx.VERTICAL)
sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
sizer.Add(wx.StaticText(self, -1, _("SVN Config Dir:")), 0, wx.ALIGN_CENTER_VERTICAL)
self._svnConfigDir = wx.TextCtrl(self, -1, configDir, size = (200, -1))
if configDir == "":
self._svnConfigDir.SetToolTipString(_("Path Subversion configuration directory."))
else:
self._svnConfigDir.SetToolTipString(configDir)
findDirButton = wx.Button(self, -1, _("Browse..."))
def OnBrowseButton(event):
dirDlg = wx.DirDialog(self, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE)
dir = self._svnConfigDir.GetValue()
if len(dir):
dirDlg.SetPath(dir)
if dirDlg.ShowModal() == wx.ID_OK:
self._svnConfigDir.SetValue(dirDlg.GetPath())
self._svnConfigDir.SetToolTipString(self._svnConfigDir.GetValue())
self._svnConfigDir.SetInsertionPointEnd()
dirDlg.Destroy()
wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer.Add(self._svnConfigDir, 1, wx.EXPAND)
hsizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE)
sizer.Add(hsizer, 0)
sizer.Add(wx.StaticText(self, -1, _("SVN URL:")), 0, wx.ALIGN_CENTER_VERTICAL)
self._svnURLText = wx.TextCtrl(self, -1, svnUrl, size = (200, -1))
self._svnURLText.SetToolTipString(svnUrl)
sizer.Add(self._svnURLText, 0)
borderSizer.Add(sizer, 0, wx.ALL, SPACE)
self.SetSizer(borderSizer)
self.Layout()
parent.AddPage(self, _("SVN"))
def OnOK(self, optionsDialog):
config = wx.ConfigBase_Get()
config.Write(SVN_CONFIG_DIR, self._svnConfigDir.GetValue())
config.Write(SVN_REPOSITORY_URL, self._svnURLText.GetValue())

View File

@@ -10,75 +10,19 @@
# License: wxWindows License # License: wxWindows License
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
import logging
import cStringIO
import traceback import traceback
import sys import sys
import string
import os import os
def classForName(className): def _registerMainModuleDir():
pathList = className.split('.') global mainModuleDir
moduleName = string.join(pathList[:-1], '.') if sys.executable.find('python') != -1:
code = __import__(moduleName) utilModuleDir = os.path.dirname(__file__)
for name in pathList[1:]: if not os.path.isabs(utilModuleDir):
code = code.__dict__[name] utilModuleDir = os.path.join(os.getcwd(), utilModuleDir)
return code mainModuleDir = os.path.normpath(os.path.join(utilModuleDir, os.path.join(os.path.pardir, os.path.pardir)))
else:
mainModuleDir = os.path.dirname(sys.executable)
def hasattrignorecase(object, name): _registerMainModuleDir()
for attr in dir(object):
if attr.lower() == name.lower():
return True
for attr in dir(object):
if attr.lower() == '_' + name.lower():
return True
return False
def setattrignorecase(object, name, value):
for attr in object.__dict__:
if attr.lower() == name.lower():
object.__dict__[attr] = value
return
## for attr in dir(object):
## if attr.lower() == '_' + name.lower():
## object.__dict__[attr] = value
## return
object.__dict__[name] = value
def getattrignorecase(object, name):
for attr in object.__dict__:
if attr.lower() == name.lower():
return object.__dict__[attr]
## for attr in dir(object):
## if attr.lower() == '_' + name.lower():
## return object.__dict__[attr]
return object.__dict__[name]
def defaultLoad(fileObject, knownTypes=None):
xml = fileObject.read()
loadedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
if hasattr(fileObject, 'name'):
loadedObject.fileName = os.path.abspath(fileObject.name)
loadedObject.initialize()
return loadedObject
def defaultSave(fileObject, objectToSave, knownTypes=None):
xml = xmlmarshaller.marshal(objectToSave, prettyPrint=True, knownTypes=knownTypes)
fileObject.write(xml)
fileObject.close()
def clone(objectToClone):
xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True)
clonedObject = xmlmarshaller.unmarshal(xml)
if hasattr(objectToClone, 'fileName'):
clonedObject.fileName = objectToClone.fileName
clonedObject.initialize()
return clonedObject
def exceptionToString(e):
sio = cStringIO.StringIO()
traceback.print_exception(e.__class__, e, sys.exc_traceback, file=sio)
return sio.getvalue()

View File

@@ -0,0 +1,93 @@
#----------------------------------------------------------------------------
# Name: objutils.py
# Purpose: Object Utilities
#
# Author: Alan Mullendore
#
# Created: 5/10/05
# CVS-ID: $Id$
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
# License: wxWindows License
#----------------------------------------------------------------------------
import logging
import traceback
import sys
import os
import xmlmarshaller
def defaultLoad(fileObject, knownTypes=None):
xml = fileObject.read()
loadedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
if hasattr(fileObject, 'name'):
loadedObject.fileName = os.path.abspath(fileObject.name)
loadedObject.initialize()
return loadedObject
def defaultSave(fileObject, objectToSave, knownTypes=None, withEncoding=1, encoding='utf-8'):
xml = xmlmarshaller.marshal(objectToSave, prettyPrint=True, knownTypes=knownTypes, withEncoding=withEncoding, encoding=encoding)
fileObject.write(xml)
fileObject.flush()
def clone(objectToClone, knownTypes=None, encoding='utf-8'):
xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, knownTypes=knownTypes, encoding=encoding)
clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
if hasattr(objectToClone, 'fileName'):
clonedObject.fileName = objectToClone.fileName
try:
clonedObject.initialize()
except AttributeError:
pass
return clonedObject
def classForName(className):
pathList = className.split('.')
moduleName = '.'.join(pathList[:-1])
code = __import__(moduleName)
for name in pathList[1:]:
code = code.__dict__[name]
return code
def hasattrignorecase(object, name):
namelow = name.lower()
for attr in dir(object):
if attr.lower() == namelow:
return True
for attr in dir(object):
if attr.lower() == '_' + namelow:
return True
return False
def setattrignorecase(object, name, value):
namelow = name.lower()
for attr in object.__dict__:
if attr.lower() == namelow:
object.__dict__[attr] = value
return
object.__dict__[name] = value
def getattrignorecase(object, name):
namelow = name.lower()
for attr in object.__dict__:
if attr.lower() == namelow:
return object.__dict__[attr]
return object.__dict__[name]
def hasPropertyValue(obj, attr):
hasProp = False
try:
prop = obj.__class__.__dict__[attr]
if (isinstance(prop, property)):
hasProp = hasattr(obj, attr)
if (hasProp):
# It's a property and it has a value but sometimes we don't want it.
# If there is a _hasattr method execute it and the
# result will tell us whether to include this value
try:
hasProp = obj._hasattr(attr)
except:
pass
except KeyError:
pass
return hasProp

View File

@@ -9,14 +9,17 @@
# Copyright: (c) 2004-2005 ActiveGrid, Inc. # Copyright: (c) 2004-2005 ActiveGrid, Inc.
# License: wxWindows License # License: wxWindows License
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
from activegrid import util import __builtin__
import inspect import sys
from types import * from types import *
import xml.sax import xml.sax
import xml.sax.handler import xml.sax.handler
import __builtin__
from xml.sax import saxutils from xml.sax import saxutils
import objutils
MODULE_PATH = "__main__"
### ToDO remove maxOccurs "unbounded" resolves to -1 hacks after bug 177 is fixed ### ToDO remove maxOccurs "unbounded" resolves to -1 hacks after bug 177 is fixed
""" """
@@ -147,52 +150,6 @@ MEMBERS_TO_SKIP = ('__module__', '__doc__', '__xmlname__', '__xmlattributes__',
'__xmldefaultnamespace__', '__xmlattrnamespaces__', '__xmldefaultnamespace__', '__xmlattrnamespaces__',
'__xmlattrgroups__') '__xmlattrgroups__')
#WELL_KNOWN_OBJECTS = { #"xs:element" : "activegrid.model.schema.XsdElement",
#"xs:complexType" : "activegrid.model.schema.XsdComplexType",
#"xs:sequence" : "activegrid.model.schema.XsdSequence",
#"xs:element" : "activegrid.model.schema.XsdElement",
#"xs:key" : "activegrid.model.schema.XsdKey",
#"xs:field" : "activegrid.model.schema.XsdKeyField",
#"xs:keyref" : "activegrid.model.schema.XsdKeyRef",
#"xs:selector" : "activegrid.model.schema.XsdKeySelector",
#"xs:schema" : "activegrid.model.schema.Schema",
#"ag:schemaOptions":"activegrid.model.schema.SchemaOptions",
#"ag:debug" : "activegrid.model.processmodel.DebugOperation",
#"ag:body" : "activegrid.model.processmodel.Body", # alan (start)
#"ag:cssRule" : "activegrid.model.processmodel.CssRule",
#"ag:datasource" : "activegrid.data.dataservice.DataSource",
#"ag:deployment" : "activegrid.server.deployment.Deployment",
#"ag:glue" : "activegrid.model.processmodel.Glue",
#"ag:hr" : "activegrid.model.processmodel.HorizontalRow",
#"ag:image" : "activegrid.model.processmodel.Image",
#"ag:inputs" : "activegrid.model.processmodel.Inputs",
#"ag:label" : "activegrid.model.processmodel.Label",
#"ag:processmodel" : "activegrid.model.processmodel.ProcessModel",
#"ag:processmodelref" : "activegrid.server.deployment.ProcessModelRef",
#"ag:query" : "activegrid.model.processmodel.Query",
#"ag:schemaref" : "activegrid.server.deployment.SchemaRef",
#"ag:set" : "activegrid.model.processmodel.SetOperation",
#"ag:text" : "activegrid.model.processmodel.Text",
#"ag:title" : "activegrid.model.processmodel.Title",
#"ag:view" : "activegrid.model.processmodel.View",
#"bpws:case" : "activegrid.model.processmodel.BPELCase",
#"bpws:invoke" : "activegrid.model.processmodel.BPELInvoke",
#"bpws:otherwise" : "activegrid.model.processmodel.BPELOtherwise",
#"bpws:process" : "activegrid.model.processmodel.BPELProcess",
#"bpws:reply" : "activegrid.model.processmodel.BPELReply",
#"bpws:switch" : "activegrid.model.processmodel.BPELSwitch",
#"bpws:variable" : "activegrid.model.processmodel.BPELVariable",
#"projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel",
#"wsdl:message" : "activegrid.model.processmodel.WSDLMessage",
#"wsdl:part" : "activegrid.model.processmodel.WSDLPart",
#"xforms:group" : "activegrid.model.processmodel.XFormsGroup",
#"xforms:input" : "activegrid.model.processmodel.XFormsInput",
#"xforms:label" : "activegrid.model.processmodel.XFormsLabel",
#"xforms:output" : "activegrid.model.processmodel.XFormsOutput",
#"xforms:secret" : "activegrid.model.processmodel.XFormsSecret",
#"xforms:submit" : "activegrid.model.processmodel.XFormsSubmit"} # alan(end)
################################################################################ ################################################################################
# #
# classes and functions # classes and functions
@@ -200,7 +157,6 @@ MEMBERS_TO_SKIP = ('__module__', '__doc__', '__xmlname__', '__xmlattributes__',
################################################################################ ################################################################################
def _objectfactory(objname, objargs=None, xsname=None): def _objectfactory(objname, objargs=None, xsname=None):
try:
'''dynamically create an object based on the objname and return '''dynamically create an object based on the objname and return
it. look it up in the BASETYPE_ELEMENT_MAP first. it. look it up in the BASETYPE_ELEMENT_MAP first.
''' '''
@@ -220,25 +176,23 @@ def _objectfactory(objname, objargs=None, xsname=None):
pathlist = objname.split('.') pathlist = objname.split('.')
modulename = '.'.join(pathlist[0:-1]) modulename = '.'.join(pathlist[0:-1])
## print "[objectfactory] objtype is %s" % objtype ## print "[objectfactory] object [%s] %s(%r)" % (objname, objtype, objargs)
## print "[objectfactory] objargs is %s" % `objargs` if objname == 'bool':
return not objargs[0].lower() == 'false'
## since the bool constructor will turn a string of non-zero elif objname == 'str': # don't strip strings - blanks are significant !!!
## length into True, we call it with no argument (yielding a if len(objargs) > 0:
## False) if the string contains 'false' return saxutils.unescape(objargs[0]).encode()
if objtype == 'bool' and objargs[0].lower() == 'false': else:
objargs = None return ''
elif objname == 'unicode': # don't strip strings - blanks are significant !!!
## if objtype == 'str': if len(objargs) > 0:
## print type(objargs) return saxutils.unescape(objargs[0]).encode()
## print "string we're unescaping: '%s'" % objargs[0] else:
## objargs = saxutils.unescape(objargs[0]) return ''
if objtype in ('float', 'int', 'str', 'long'): elif objtype in ('float', 'int', 'str', 'long'):
objargs = [x.strip() for x in objargs] objargs = [x.strip() for x in objargs]
if objtype == 'str': try:
objargs = [saxutils.unescape(x) for x in objargs]
if __builtin__.__dict__.has_key(objname): if __builtin__.__dict__.has_key(objname):
module = __builtin__ module = __builtin__
else: else:
@@ -379,7 +333,7 @@ class XMLObjectFactory(xml.sax.ContentHandler):
if attrname == "maxOccurs" and attr == "unbounded": if attrname == "maxOccurs" and attr == "unbounded":
attr = "-1" attr = "-1"
attr = _objectfactory(type, attr) attr = _objectfactory(type, attr)
util.setattrignorecase(obj, _toAttrName(obj, attrname), attr) objutils.setattrignorecase(obj, _toAttrName(obj, attrname), attr)
## obj.__dict__[_toAttrName(obj, attrname)] = attr ## obj.__dict__[_toAttrName(obj, attrname)] = attr
# stuff any child attributes meant to be in a sequence via the __xmlflattensequence__ # stuff any child attributes meant to be in a sequence via the __xmlflattensequence__
flattenDict = {} flattenDict = {}
@@ -407,9 +361,7 @@ class XMLObjectFactory(xml.sax.ContentHandler):
try: try:
## print "[endElement] obj.__dict__ is: ", obj.__dict__ ## print "[endElement] obj.__dict__ is: ", obj.__dict__
sequencevalue = obj.__dict__[sequencename] sequencevalue = obj.__dict__[sequencename]
except AttributeError: except (AttributeError, KeyError):
sequencevalue = None
except KeyError:
sequencevalue = None sequencevalue = None
if sequencevalue == None: if sequencevalue == None:
sequencevalue = [] sequencevalue = []
@@ -420,7 +372,7 @@ class XMLObjectFactory(xml.sax.ContentHandler):
obj.append(child) obj.append(child)
else: else:
## print "childname = %s, obj = %s, child = %s" % (childname, repr(obj), repr(child)) ## print "childname = %s, obj = %s, child = %s" % (childname, repr(obj), repr(child))
util.setattrignorecase(obj, _toAttrName(obj, childname), child) objutils.setattrignorecase(obj, _toAttrName(obj, childname), child)
obj.__dict__[_toAttrName(obj, childname)] = child obj.__dict__[_toAttrName(obj, childname)] = child
if complexType: if complexType:
@@ -474,6 +426,8 @@ def xsdToPythonType(xsdType):
def _getXmlValue(pythonValue): def _getXmlValue(pythonValue):
if (isinstance(pythonValue, bool)): if (isinstance(pythonValue, bool)):
return str(pythonValue).lower() return str(pythonValue).lower()
elif (isinstance(pythonValue, unicode)):
return pythonValue.encode()
else: else:
return str(pythonValue) return str(pythonValue)
@@ -488,7 +442,17 @@ def unmarshal(xmlstr, knownTypes=None):
return objectfactory.getRootObject() return objectfactory.getRootObject()
def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPrint=False, indent=0, knownTypes=None): def marshal(obj, elementName=None, prettyPrint=False, indent=0, knownTypes=None, withEncoding=True, encoding=None):
xmlstr = ''.join(_marshal(obj, elementName, prettyPrint=prettyPrint, indent=indent, knownTypes=knownTypes))
if withEncoding:
if encoding is None:
return '<?xml version="1.0" encoding="%s"?>\n%s' % (sys.getdefaultencoding(), xmlstr)
else:
return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, xmlstr.encode(encoding))
else:
return xmlstr
def _marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPrint=False, indent=0, knownTypes=None):
if prettyPrint or indent: if prettyPrint or indent:
prefix = ' '*indent prefix = ' '*indent
newline = '\n' newline = '\n'
@@ -563,7 +527,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
except KeyError: except KeyError:
continue continue
## # But, check and see if it is a property first: ## # But, check and see if it is a property first:
## if (hasPropertyValue(obj, attr)): ## if (objutils.hasPropertyValue(obj, attr)):
## value = getattr(obj, attr) ## value = getattr(obj, attr)
## else: ## else:
## continue ## continue
@@ -593,7 +557,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
if hasattr(obj, '__xmlattrnamespaces__'): if hasattr(obj, '__xmlattrnamespaces__'):
## print "marshal: found __xmlattrnamespaces__" ## print "marshal: found __xmlattrnamespaces__"
for nameSpaceKey, nameSpaceAttributes in getattr(obj, '__xmlattrnamespaces__').items(): for nameSpaceKey, nameSpaceAttributes in getattr(obj, '__xmlattrnamespaces__').items():
if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as it selement if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as it's element
continue continue
if attr in nameSpaceAttributes: if attr in nameSpaceAttributes:
attrNameSpacePrefix = nameSpaceKey + ':' attrNameSpacePrefix = nameSpaceKey + ':'
@@ -607,95 +571,76 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, value) objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, value)
## print "marshal: new objattrs is: ", objattrs ## print "marshal: new objattrs is: ", objattrs
objtype = type(obj)
if isinstance(obj, NoneType): if isinstance(obj, NoneType):
#print "marshal: skipping an element with no type"
return '' return ''
# return '%s<%s objtype="None"/>%s' % (prefix, elementName, newline)
elif isinstance(obj, bool): elif isinstance(obj, bool):
xmlString = '%s<%s objtype="bool">%s</%s>%s' % (prefix, elementName, obj, elementName, newline) return ['%s<%s objtype="bool">%s</%s>%s' % (prefix, elementName, obj, elementName, newline)]
#print "marshal: returning a bool element: \n", xmlString
return xmlString
elif isinstance(obj, int): elif isinstance(obj, int):
xmlString = '''%s<%s objtype="int">%s</%s>%s''' % (prefix, elementName, str(obj), elementName, newline) return ['''%s<%s objtype="int">%s</%s>%s''' % (prefix, elementName, str(obj), elementName, newline)]
#print "marshal: returning a int element: \n", xmlString
return xmlString
elif isinstance(obj, long): elif isinstance(obj, long):
xmlString = '%s<%s objtype="long">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline) return ['%s<%s objtype="long">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline)]
#print "marshal: returning a long element: \n", xmlString
return xmlString
elif isinstance(obj, float): elif isinstance(obj, float):
xmlString = '%s<%s objtype="float">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline) return ['%s<%s objtype="float">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline)]
#print "marshal: returning a float element: \n", xmlString elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string
return xmlString return ['''%s<%s>%s</%s>%s''' % (prefix, elementName, saxutils.escape(obj.encode()), elementName, newline)]
elif isinstance(obj, basestring): elif isinstance(obj, basestring):
xmlString = '''%s<%s>%s</%s>%s''' % (prefix, elementName, saxutils.escape(obj), elementName, newline) return ['''%s<%s>%s</%s>%s''' % (prefix, elementName, saxutils.escape(obj), elementName, newline)]
#print "marshal: returning a str element: \n", xmlString
return xmlString
## elif isinstance(obj, unicode):
## return '''%s<%s>%s</%s>%s''' % (prefix, elementName, obj, elementName, newline)
elif isinstance(obj, list): elif isinstance(obj, list):
if len(obj) < 1: if len(obj) < 1:
#print "marshal: skipping an empty list"
return '' return ''
xmlString = '%s<%s objtype="list">%s' % (prefix, elementName, newline) xmlString = ['%s<%s objtype="list">%s' % (prefix, elementName, newline)]
for item in obj: for item in obj:
xmlString += marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes) xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
xmlString += '%s</%s>%s' % (prefix, elementName, newline) xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
#print "marshal: returning a list element: \n", xmlString
return xmlString return xmlString
elif isinstance(obj, tuple): elif isinstance(obj, tuple):
if len(obj) < 1: if len(obj) < 1:
#print "marshal: skipping an empty tuple"
return '' return ''
xmlString = '%s<%s objtype="list" mutable="false">%s' % (prefix, elementName, newline) xmlString = ['%s<%s objtype="list" mutable="false">%s' % (prefix, elementName, newline)]
for item in obj: for item in obj:
xmlString += marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes) xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
xmlString += '%s</%s>%s' % (prefix, elementName, newline) xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
#print "marshal: returning a tuple element: \n", xmlString
return xmlString return xmlString
elif isinstance(obj, dict): elif isinstance(obj, dict):
xmlString = '%s<%s objtype="dict">%s' % (prefix, elementName, newline) xmlString = ['%s<%s objtype="dict">%s' % (prefix, elementName, newline)]
subprefix = prefix + ' '*increment subprefix = prefix + ' '*increment
subindent = indent + 2*increment subindent = indent + 2*increment
for key, val in obj.iteritems(): for key, val in obj.iteritems():
xmlString += "%s<key>%s%s%s</key>%s%s<value>%s%s%s</value>%s" \ xmlString.append("%s<key>%s" % (subprefix, newline))
% (subprefix, newline, marshal(key, indent=subindent, knownTypes=knownTypes), subprefix, newline, subprefix, newline, marshal(val, nameSpaces=nameSpaces, indent=subindent, knownTypes=knownTypes), subprefix, newline) xmlString.extend(_marshal(key, indent=subindent, knownTypes=knownTypes))
xmlString += '%s</%s>%s' % (prefix, elementName, newline) xmlString.append("%s</key>%s%s<value>%s" % (subprefix, newline, subprefix, newline))
#print "marshal: returning a dict element: \n", xmlString xmlString.extend(_marshal(val, nameSpaces=nameSpaces, indent=subindent, knownTypes=knownTypes))
xmlString.append("%s</value>%s" % (subprefix, newline))
xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
return xmlString return xmlString
else: else:
moduleName = obj.__class__.__module__ moduleName = obj.__class__.__module__
if (moduleName == "activegrid.model.schema"): if (moduleName == "activegrid.model.schema"):
## print "marshal: found an activegrid.model.schema class element" xmlString = ['%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs)]
xmlString = '%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs)
else: else:
## print "marshal: found a ", moduleName, " class element"
# Only add the objtype if the element tag is unknown to us. # Only add the objtype if the element tag is unknown to us.
try: try:
objname = knownTypes[elementName] objname = knownTypes[elementName]
## print "successfully mapped ", elementName, " to known-objtype ", objname xmlString = ['%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs)]
xmlString = '%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs)
except KeyError: except KeyError:
## print "failed to map elementName: ", elementName, "; knownTypes: ", knownTypes xmlString = ['%s<%s%s%s objtype="%s.%s"' % (prefix, elementName, nameSpaceAttrs, objattrs, moduleName, className)]
xmlString = '%s<%s%s%s objtype="%s.%s"' % (prefix, elementName, nameSpaceAttrs, objattrs, moduleName, className)
## print "UnknownTypeException: Unknown type (%s.%s) passed to marshaller" % (moduleName, className) ## print "UnknownTypeException: Unknown type (%s.%s) passed to marshaller" % (moduleName, className)
# get the member, value pairs for the object, filtering out # get the member, value pairs for the object, filtering out the types we don't support
# the types we don't support.
## print "marshal: elementString: \n", xmlString
if (elementAdd != None): if (elementAdd != None):
prefix += increment*' ' prefix += increment*' '
indent += increment indent += increment
xmlMemberString = '' xmlMemberString = []
if hasattr(obj, '__xmlbody__'): if hasattr(obj, '__xmlbody__'):
xmlMemberString = getattr(obj, obj.__xmlbody__) xmlbody = getattr(obj, obj.__xmlbody__)
if xmlbody != None:
xmlMemberString.append(xmlbody)
else: else:
entryList = obj.__dict__.items() entryList = obj.__dict__.items()
## # Add in properties ## # Add in properties
## for key in obj.__class__.__dict__.iterkeys(): ## for key in obj.__class__.__dict__.iterkeys():
## if (key not in members_to_skip and key not in obj.__dict__ ## if (key not in members_to_skip and key not in obj.__dict__
## and hasPropertyValue(obj, key)): ## and objutils.hasPropertyValue(obj, key)):
## value = getattr(obj, key) ## value = getattr(obj, key)
## entryList.append((key, value)) ## entryList.append((key, value))
entryList.sort() entryList.sort()
@@ -719,7 +664,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
if (eName != '__nogroup__'): if (eName != '__nogroup__'):
prefix += increment*' ' prefix += increment*' '
indent += increment indent += increment
xmlMemberString += '%s<%s objtype="None">%s' % (prefix, eName, newline) xmlMemberString.append('%s<%s objtype="None">%s' % (prefix, eName, newline))
for name in eList: for name in eList:
value = obj.__dict__[name] value = obj.__dict__[name]
## print " ", name, " = ", value ## print " ", name, " = ", value
@@ -754,91 +699,38 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
xmlname = name xmlname = name
## xmlname = name.lower() ## xmlname = name.lower()
for seqitem in value: for seqitem in value:
xmlMemberString += marshal(seqitem, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes) xmlMemberString.extend(_marshal(seqitem, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
else: else:
if (hasattr(obj, "__xmlrename__") and name in obj.__xmlrename__): if (hasattr(obj, "__xmlrename__") and name in obj.__xmlrename__):
xmlname = obj.__xmlrename__[name] xmlname = obj.__xmlrename__[name]
else: else:
xmlname = name xmlname = name
## xmlname = name.lower()
## # skip
## if xmlname.startswith('_') and not xmlname.startswith('__'):
## xmlname = xmlname[1:]
## if (indent > 30): ## if (indent > 30):
## print "getting pretty deep, xmlname = ", xmlname ## print "getting pretty deep, xmlname = ", xmlname
## print "marshal: marshalling ", xmlname xmlMemberString.extend(_marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
xmlMemberString += marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)
## print "marshal: back with new xmlMemberString: \n", xmlMemberString
if (eName != '__nogroup__'): if (eName != '__nogroup__'):
## print "marshal: Completing attrGroup ", eName ## print "marshal: Completing attrGroup ", eName
xmlMemberString += '%s</%s>%s' % (prefix, eName, newline) xmlMemberString.append('%s</%s>%s' % (prefix, eName, newline))
prefix = prefix[:-increment] prefix = prefix[:-increment]
indent -= increment indent -= increment
# if we have nested elements, add them here, otherwise close the element tag immediately. # if we have nested elements, add them here, otherwise close the element tag immediately.
if xmlMemberString: xmlMemberString = filter(lambda x: len(x)>0, xmlMemberString)
xmlString += '>' if len(xmlMemberString) > 0:
xmlString.append('>')
if hasattr(obj, '__xmlbody__'): if hasattr(obj, '__xmlbody__'):
xmlString += xmlMemberString xmlString.extend(xmlMemberString)
xmlString += '</%s>%s' % (elementName, newline) xmlString.append('</%s>%s' % (elementName, newline))
else: else:
xmlString += newline xmlString.append(newline)
if (elementAdd != None): if (elementAdd != None):
xmlString += '%s<%s>%s' % (prefix, elementAdd, newline) xmlString.append('%s<%s>%s' % (prefix, elementAdd, newline))
xmlString += xmlMemberString xmlString.extend(xmlMemberString)
if (elementAdd != None): if (elementAdd != None):
xmlString += '%s</%s>%s' % (prefix, elementAdd, newline) xmlString.append('%s</%s>%s' % (prefix, elementAdd, newline))
prefix = prefix[:-increment] prefix = prefix[:-increment]
indent -= increment indent -= increment
xmlString += '%s</%s>%s' % (prefix, elementName, newline) xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
else: else:
xmlString = xmlString + '/>%s' % newline xmlString.append('/>%s' % newline)
return xmlString return xmlString
# We don't use this anymore but in case we want to get properties this is how
# you do it
def hasPropertyValue(obj, attr):
hasProp = False
try:
prop = obj.__class__.__dict__[attr]
if (isinstance(prop, property)):
hasProp = hasattr(obj, attr)
if (hasProp):
# It's a property and it has a value but sometimes we don't want it.
# If there is a _hasattr method execute it and the
# result will tell us whether to include this value
try:
hasProp = obj._hasattr(attr)
except:
pass
except KeyError:
pass
return hasProp
if __name__ == '__main__':
from xmlmarshallertests import Person, marshalledint, marshalledlist
l = [1, 2, 3]
d = {'1': 1, '2': 2}
outerlist = [l]
xmlstr = marshal(d, "d", prettyPrint=True)
print xmlstr
person = Person()
person.firstName = "Albert"
person.lastName = "Camus"
person.addressLine1 = "23 Absurd St."
person.city = "Ennui"
person.state = "MO"
person.zip = "54321"
person._phoneNumber = "808-303-2323"
person.favoriteWords = ['angst', 'ennui', 'existence']
person.weight = 150
xmlstring = marshal(person, 'person', prettyPrint=True)
print xmlstring
obj = unmarshal(marshalledlist)
print "obj has type %s and value %s" % (type(obj), str(obj))
for item in obj:
print "item: %s" % str(item)

View File

@@ -1,183 +0,0 @@
#----------------------------------------------------------------------------
# Name: xmlmarshallertests.py
# Purpose:
#
# Author: John Spurling
#
# Created: 8/16/04
# CVS-ID: $Id$
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
# License: wxWindows License
#----------------------------------------------------------------------------
import unittest
import xmlmarshaller
from xmlprettyprinter import xmlprettyprint
marshalledPersonObject = """
<person objtype="Person">
<firstName>Albert</firstName>
<lastName>Camus</lastName>
<address>23 Absurd St.</address>
<city>Ennui</city>
<state>MO</state>
<zip>54321</zip>
<_phoneNumber>808-303-2323</_phoneNumber>
<favoriteWords objtype="list">
<item>angst</item>
<item>ennui</item>
<item>existence</item>
</favoriteWords>
<weight objtype="float">150</weight>
</person>
"""
marshalledint = '''
<item objtype="int">23</item>
'''
marshalledlist = '''
<mylist objtype="list">
<item>foo</item>
<item>bar</item>
</mylist>
'''
## a dummy class taken from the old XmlMarshaller module.
## class Person:
## def __init__(self):
## # These are not necessary but are nice if you want to tailor
## # the Python object <-> XML binding
## # The xml element name to use for this object, otherwise it
## # will use a fully qualified Python name like __main__.Person
## # which can be ugly.
## self.__xmlname__ = "person"
## self.firstName = None
## self.lastName = None
## self.addressLine1 = None
## self.addressLine2 = None
## self.city = None
## self.state = None
## self.zip = None
## self._phoneNumber = None
## self.favoriteWords = None
## self.weight = None
class Person:
__xmlflattensequence__ = {'asequence': ('the_earth_is_flat',)}
class XmlMarshallerTestFunctions(unittest.TestCase):
def setUp(self):
'''common setup code goes here.'''
pass
def testInt(self):
xml = xmlmarshaller.marshal(1)
print "\n#########################################"
print "# testString test case #"
print "#########################################"
print "marshalled int object:\n"
print xmlprettyprint(xml)
def testDict(self):
xml = xmlmarshaller.marshal({'one': 1,
'two': 2,
'three': 3})
print "\n#########################################"
print "# testString test case #"
print "#########################################"
print "marshalled dict object:\n"
print xmlprettyprint(xml)
def testBool(self):
xmltrue = xmlmarshaller.marshal(True)
xmlfalse = xmlmarshaller.marshal(False)
print "\n#########################################"
print "# testBool test case #"
print "#########################################"
print "marshalled boolean true object:\n"
print xmlprettyprint(xmltrue)
print "\nmarshalled boolean false object:\n"
print xmlprettyprint(xmlfalse)
pytrue = xmlmarshaller.unmarshal(xmltrue)
assert pytrue is True
pyfalse = xmlmarshaller.unmarshal(xmlfalse)
assert pyfalse is False
def testString(self):
xml = xmlmarshaller.marshal(
"all your marshalled objects are belong to us")
print "\n#########################################"
print "# testString test case #"
print "#########################################"
print xmlprettyprint(xml)
def testEmptyElement(self):
person = Person()
person.firstName = "Albert"
person.__xmlattributes__ = ('firstName',)
xml = xmlmarshaller.marshal(person, 'person')
print "\n#########################################"
print "# testEmptyElement test case #"
print "#########################################"
print xml
assert (xml == """<person objtype="__main__.Person" firstName="Albert"/>""")
def testXMLFlattenSequence(self):
person = Person()
person.asequence = ('one', 'two')
xml = xmlmarshaller.marshal(person, 'person')
print "\n#########################################"
print "# testXMLFlattenSequence test case #"
print "#########################################"
print xml
assert (xml == """<person objtype="__main__.Person"><the_earth_is_flat>one</the_earth_is_flat><the_earth_is_flat>two</the_earth_is_flat></person>""")
unmarshalledperson = xmlmarshaller.unmarshal(xml)
assert(hasattr(unmarshalledperson, 'asequence'))
assert(len(unmarshalledperson.asequence) == 2)
def testInstance(self):
print "\n#########################################"
print "# testInstance test case #"
print "#########################################"
class Foo:
def __init__(self):
self.alist = [1,2]
self.astring = 'f00'
f = Foo()
xml = xmlmarshaller.marshal(f, 'foo')
print xml
def testPerson(self):
person = Person()
person.firstName = "Albert"
person.lastName = "Camus"
person.addressLine1 = "23 Absurd St."
person.city = "Ennui"
person.state = "MO"
person.zip = "54321"
person._phoneNumber = "808-303-2323"
person.favoriteWords = ['angst', 'ennui', 'existence']
person.weight = 150
# __xmlattributes__ = ('fabulousness',)
person.fabulousness = "tres tres"
xml = xmlmarshaller.marshal(person)
print "\n#########################################"
print "# testPerson test case #"
print "#########################################"
print "Person object marshalled into XML:\n"
print xml
# When encountering a "person" element, use the Person class
## elementMappings = { "person" : Person }
## obj = unmarshal(xml, elementMappings = elementMappings)
## print "Person object recreated from XML with attribute types indicated:"
## print obj.person.__class__
## for (attr, value) in obj.person.__dict__.items():
## if not attr.startswith("__"):
## print attr, "=", value, type(value)
## print
if __name__ == "__main__":
unittest.main()

View File

@@ -60,7 +60,7 @@ class TextEditorApplication(pydocview.DocApp):
# Install services - these can install menu and toolbar items # Install services - these can install menu and toolbar items
textService = self.InstallService(TextEditor.TextService()) textService = self.InstallService(TextEditor.TextService())
findService = self.InstallService(FindService.FindService()) findService = self.InstallService(FindService.FindService())
optionsService = self.InstallService(pydocview.DocOptionsService()) optionsService = self.InstallService(pydocview.DocOptionsService(supportedModes=wx.lib.docview.DOC_MDI))
windowMenuService = self.InstallService(pydocview.WindowMenuService()) windowMenuService = self.InstallService(pydocview.WindowMenuService())
filePropertiesService = self.InstallService(pydocview.FilePropertiesService()) filePropertiesService = self.InstallService(pydocview.FilePropertiesService())
if os.path.exists("splash.jpg"): if os.path.exists("splash.jpg"):

File diff suppressed because it is too large Load Diff

View File

@@ -773,6 +773,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
# self._notebook.SetSizer(wx.NotebookSizer(self._notebook)) # self._notebook.SetSizer(wx.NotebookSizer(self._notebook))
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged) wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick) wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
templates = wx.GetApp().GetDocumentManager().GetTemplates() templates = wx.GetApp().GetDocumentManager().GetTemplates()
iconList = wx.ImageList(16, 16, initialCount = len(templates)) iconList = wx.ImageList(16, 16, initialCount = len(templates))
@@ -825,6 +826,17 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
self._notebook.GetPage(index).GetView().Activate() self._notebook.GetPage(index).GetView().Activate()
def OnNotebookMouseOver(self, event):
# wxBug: On Windows XP the tooltips don't automatically disappear when you move the mouse and it is on a notebook tab, has nothing to do with this code!!!
index, type = self._notebook.HitTest(event.GetPosition())
if index > -1:
doc = self._notebook.GetPage(index).GetView().GetDocument()
self._notebook.SetToolTip(wx.ToolTip(doc.GetFilename()))
else:
self._notebook.SetToolTip(wx.ToolTip(""))
event.Skip()
def OnNotebookRightClick(self, event): def OnNotebookRightClick(self, event):
""" """
Handles right clicks for the notebook, enabling users to either close Handles right clicks for the notebook, enabling users to either close
@@ -842,6 +854,15 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
doc.DeleteAllViews() doc.DeleteAllViews()
wx.EVT_MENU(self, id, OnRightMenuSelect) wx.EVT_MENU(self, id, OnRightMenuSelect)
if self._notebook.GetPageCount() > 1: if self._notebook.GetPageCount() > 1:
id = wx.NewId()
menu.Append(id, _("Close All but \"%s\"" % doc.GetPrintableName()))
def OnRightMenuSelect(event):
for i in range(self._notebook.GetPageCount()-1, -1, -1): # Go from len-1 to 0
if i != index:
doc = self._notebook.GetPage(i).GetView().GetDocument()
if not self.GetDocumentManager().CloseDocument(doc, False):
return
wx.EVT_MENU(self, id, OnRightMenuSelect)
menu.AppendSeparator() menu.AppendSeparator()
tabsMenu = wx.Menu() tabsMenu = wx.Menu()
menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu) menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu)
@@ -899,6 +920,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
""" """
index = self.GetNotebookPageIndex(panel) index = self.GetNotebookPageIndex(panel)
if index > -1: if index > -1:
self._notebook.SetFocus()
self._notebook.SetSelection(index) self._notebook.SetSelection(index)
@@ -1263,7 +1285,7 @@ class DocOptionsService(DocService):
""" """
def __init__(self, showGeneralOptions=True, allowModeChanges=True): def __init__(self, showGeneralOptions=True, supportedModes=wx.lib.docview.DOC_SDI & wx.lib.docview.DOC_MDI):
""" """
Initializes the options service with the option of suppressing the default Initializes the options service with the option of suppressing the default
general options pane that is included with the options service by setting general options pane that is included with the options service by setting
@@ -1273,7 +1295,7 @@ class DocOptionsService(DocService):
""" """
DocService.__init__(self) DocService.__init__(self)
self.ClearOptionsPanels() self.ClearOptionsPanels()
self._allowModeChanges = allowModeChanges self._supportedModes = supportedModes
self._toolOptionsID = wx.NewId() self._toolOptionsID = wx.NewId()
if showGeneralOptions: if showGeneralOptions:
self.AddOptionsPanel(GeneralOptionsPanel) self.AddOptionsPanel(GeneralOptionsPanel)
@@ -1310,20 +1332,20 @@ class DocOptionsService(DocService):
return False return False
def GetAllowModeChanges(self): def GetSupportedModes(self):
""" """
Return true if the default general options pane should allow users to Return the modes supported by the application. Use docview.DOC_SDI and
change the document interface mode between SDI and MDI modes. docview.DOC_MDI flags to check if SDI and/or MDI modes are supported.
""" """
return self._allowModeChanges return self._supportedModes
def SetAllowModeChanges(self, allowModeChanges): def SetSupportedModes(self, _supportedModessupportedModes):
""" """
Set to true if the default general options pane should allow users to Sets the modes supported by the application. Use docview.DOC_SDI and
change the document interface mode between SDI and MDI modes. docview.DOC_MDI flags to set if SDI and/or MDI modes are supported.
""" """
self._allowModeChanges = allowModeChanges self._supportedModes = supportedModes
def ClearOptionsPanels(self): def ClearOptionsPanels(self):
@@ -1430,20 +1452,27 @@ class GeneralOptionsPanel(wx.Panel):
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
self._showTipsCheckBox = wx.CheckBox(self, -1, _("Show tips at start up")) self._showTipsCheckBox = wx.CheckBox(self, -1, _("Show tips at start up"))
self._showTipsCheckBox.SetValue(config.ReadInt("ShowTipAtStartup", True)) self._showTipsCheckBox.SetValue(config.ReadInt("ShowTipAtStartup", True))
if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges(): if self._AllowModeChanges():
choices = [_("Show each document in its own window"), _("Show all documents in a single window with tabs")] supportedModes = wx.GetApp().GetService(DocOptionsService).GetSupportedModes()
choices = []
self._sdiChoice = _("Show each document in its own window")
self._mdiChoice = _("Show all documents in a single window with tabs")
self._winMdiChoice = _("Show all documents in a single window with child windows")
if supportedModes & wx.lib.docview.DOC_SDI:
choices.append(self._sdiChoice)
choices.append(self._mdiChoice)
if wx.Platform == "__WXMSW__": if wx.Platform == "__WXMSW__":
choices.append(_("Show all documents in a single window with child windows")) choices.append(self._winMdiChoice)
self._documentRadioBox = wx.RadioBox(self, -1, _("Document Interface"), self._documentRadioBox = wx.RadioBox(self, -1, _("Document Interface"),
choices = choices, choices = choices,
majorDimension=1, majorDimension=1,
) )
if config.ReadInt("UseWinMDI", False): if config.ReadInt("UseWinMDI", False):
self._documentRadioBox.SetSelection(2) self._documentRadioBox.SetStringSelection(self._winMdiChoice)
elif config.ReadInt("UseMDI", True): elif config.ReadInt("UseMDI", True):
self._documentRadioBox.SetSelection(1) self._documentRadioBox.SetStringSelection(self._mdiChoice)
else: else:
self._documentRadioBox.SetSelection(0) self._documentRadioBox.SetStringSelection(self._sdiChoice)
def OnDocumentInterfaceSelect(event): def OnDocumentInterfaceSelect(event):
if not self._documentInterfaceMessageShown: if not self._documentInterfaceMessageShown:
msgTitle = wx.GetApp().GetAppName() msgTitle = wx.GetApp().GetAppName()
@@ -1457,7 +1486,7 @@ class GeneralOptionsPanel(wx.Panel):
wx.EVT_RADIOBOX(self, self._documentRadioBox.GetId(), OnDocumentInterfaceSelect) wx.EVT_RADIOBOX(self, self._documentRadioBox.GetId(), OnDocumentInterfaceSelect)
optionsBorderSizer = wx.BoxSizer(wx.VERTICAL) optionsBorderSizer = wx.BoxSizer(wx.VERTICAL)
optionsSizer = wx.BoxSizer(wx.VERTICAL) optionsSizer = wx.BoxSizer(wx.VERTICAL)
if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges(): if self._AllowModeChanges():
optionsSizer.Add(self._documentRadioBox, 0, wx.ALL, HALF_SPACE) optionsSizer.Add(self._documentRadioBox, 0, wx.ALL, HALF_SPACE)
optionsSizer.Add(self._showTipsCheckBox, 0, wx.ALL, HALF_SPACE) optionsSizer.Add(self._showTipsCheckBox, 0, wx.ALL, HALF_SPACE)
optionsBorderSizer.Add(optionsSizer, 0, wx.ALL, SPACE) optionsBorderSizer.Add(optionsSizer, 0, wx.ALL, SPACE)
@@ -1467,15 +1496,20 @@ class GeneralOptionsPanel(wx.Panel):
parent.AddPage(self, _("Options")) parent.AddPage(self, _("Options"))
def _AllowModeChanges(self):
supportedModes = wx.GetApp().GetService(DocOptionsService).GetSupportedModes()
return supportedModes & wx.lib.docview.DOC_SDI and supportedModes & wx.lib.docview.DOC_MDI or wx.Platform == "__WXMSW__" and supportedModes & wx.lib.docview.DOC_MDI # More than one mode is supported, allow selection
def OnOK(self, optionsDialog): def OnOK(self, optionsDialog):
""" """
Updates the config based on the selections in the options panel. Updates the config based on the selections in the options panel.
""" """
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
config.WriteInt("ShowTipAtStartup", self._showTipsCheckBox.GetValue()) config.WriteInt("ShowTipAtStartup", self._showTipsCheckBox.GetValue())
if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges(): if self._AllowModeChanges():
config.WriteInt("UseMDI", (self._documentRadioBox.GetSelection() == 1)) config.WriteInt("UseMDI", (self._documentRadioBox.GetStringSelection() == self._mdiChoice))
config.WriteInt("UseWinMDI", (self._documentRadioBox.GetSelection() == 2)) config.WriteInt("UseWinMDI", (self._documentRadioBox.GetStringSelection() == self._winMdiChoice))
class DocApp(wx.PySimpleApp): class DocApp(wx.PySimpleApp):