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
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"),
("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"),
("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

View File

@@ -66,13 +66,18 @@ class CanvasView(wx.lib.docview.View):
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
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
self._canvas.SetFocus()
self.SetFocus()
else:
wx.CallAfter(self._canvas.SetFocus)
wx.CallAfter(self.SetFocus)
def SetFocus(self):
if self._canvas:
self._canvas.SetFocus()
def OnFocus(self, event):
self._canvas.SetFocus()
self.SetFocus()
self.FocusColorPropertyShape(True)
event.Skip()
@@ -82,6 +87,17 @@ class CanvasView(wx.lib.docview.View):
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):
statusC = wx.GetApp().CloseChildDocuments(self.GetDocument())
statusP = wx.lib.docview.View.OnClose(self, deleteWindow = deleteWindow)
@@ -528,7 +544,10 @@ class CanvasView(wx.lib.docview.View):
# draw new selection
if self._propShape and self._propShape in self._diagram.GetShapeList():
if self.HasFocus():
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
self._propShape.SetTextColour("WHITE", 0)
self._propShape.Draw(dc)

View File

@@ -190,6 +190,7 @@ class Adb(bdb.Bdb):
def stop_here(self, frame):
if( self._userBreak ):
self._userBreak = False
return True
@@ -447,10 +448,21 @@ class DebuggerHarness(object):
item_node.setAttribute('name', str(name))
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):
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:
self.addTupleOrList(top_element, name, item, doc, ply - 1)
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)
elif inspect.isclass(item) or tp is types.InstanceType:
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__'):
self.addDict(top_element, name, item.__dict__, doc, ply -1)
self.addDictAttr(top_element, name, item, doc, ply -1)
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):
tupleNode = doc.createElement('tuple')
tupleNode.setAttribute('name', str(name))
tupleNode.setAttribute('value', str(type(tupple)))
tupleNode.setAttribute('value', self.saferepr(tupple))
top_node.appendChild(tupleNode)
count = 0
for item in tupple:
self.addAny(tupleNode, name +'[' + str(count) + ']',item, doc, ply -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):
doc = getDOMImplementation().createDocument(None, "stack", None)
@@ -506,7 +636,7 @@ class DebuggerHarness(object):
#print "Frame: %s %s %s" %(message, frame.f_lineno, filename)
self.message_frame_dict[message] = frame
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):
try:
@@ -514,101 +644,15 @@ class DebuggerHarness(object):
except:
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):
try:
return repr(thing)
except:
tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
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.
def interaction(self, message, frame, info):
if _VERBOSE:
@@ -683,6 +727,7 @@ if __name__ == '__main__':
try:
harness = DebuggerHarness()
harness.run()
harness.do_exit(kill=True)
except SystemExit:
print "Exiting..."
except:

View File

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

View File

@@ -16,6 +16,8 @@ import wx.lib.pydocview
import sys
import wx.grid
import os.path
import activegrid.util
_ = wx.GetTranslation
ACTIVEGRID_BASE_IDE = False
@@ -77,7 +79,11 @@ class IDEApplication(wx.lib.pydocview.DocApp):
import PHPEditor
import wx.lib.ogl as ogl
import DebuggerService
import atexit
atexit.register(DebuggerService.DebuggerService.KillAllRunningProcesses)
import AboutDialog
import SVNService
if not ACTIVEGRID_BASE_IDE:
import DataModelEditor
import ProcessModelEditor
@@ -287,8 +293,9 @@ class IDEApplication(wx.lib.pydocview.DocApp):
deploymentService = self.InstallService(DeploymentService.DeploymentService())
dataModelService = self.InstallService(DataModelEditor.DataModelService())
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))
svnService = self.InstallService(SVNService.SVNService())
if not ACTIVEGRID_BASE_IDE:
projectService.AddRunHandler(processModelService)
@@ -307,6 +314,7 @@ class IDEApplication(wx.lib.pydocview.DocApp):
optionsService.AddOptionsPanel(PHPEditor.PHPOptionsPanel)
optionsService.AddOptionsPanel(STCTextEditor.TextOptionsPanel)
optionsService.AddOptionsPanel(HtmlEditor.HtmlOptionsPanel)
optionsService.AddOptionsPanel(SVNService.SVNOptionsPanel)
filePropertiesService.AddCustomEventHandler(projectService)
@@ -326,7 +334,6 @@ class IDEApplication(wx.lib.pydocview.DocApp):
propertyService.StartBackgroundTimer()
self.SetDefaultIcon(getActiveGridIcon())
self.SetUseTabbedMDI(True)
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
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...
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 welcomeService.RunWelcomeIfFirstTime():
if os.path.exists("activegrid/tool/data/tips.txt"):
wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider("activegrid/tool/data/tips.txt", 0))
if os.path.exists(tips_path):
wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0))
else:
if os.path.exists("activegrid/tool/data/tips.txt"):
wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider("activegrid/tool/data/tips.txt", 0))
if os.path.exists(tips_path):
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.

View File

@@ -84,6 +84,7 @@ class OutlineView(Service.ServiceView):
item = self.GetControl().GetSelection()
if item:
self.GetControl().CallDoSelectCallback(item)
event.Skip()
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):
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.SetKeyWords(4, string.join(PHPKEYWORDS))
self.SetProperty("fold.html", "1")

View File

@@ -23,9 +23,11 @@ import sys
import activegrid.util.xmlmarshaller
import UICommon
import Wizard
import SVNService
from IDE import ACTIVEGRID_BASE_IDE
if not ACTIVEGRID_BASE_IDE:
import ProcessModelEditor
from SVNService import SVN_INSTALLED
_ = wx.GetTranslation
@@ -127,6 +129,8 @@ class ProjectDocument(wx.lib.docview.Document):
for path in paths:
if path.startswith(curPath):
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:
pass # use absolute path
newFilePaths.append(path)
@@ -911,6 +915,15 @@ class ProjectView(wx.lib.docview.View):
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):
rootItem = self._treeCtrl.GetRootItem()
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()))
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
#----------------------------------------------------------------------------
@@ -980,7 +1004,7 @@ class ProjectView(wx.lib.docview.View):
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)
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.SetToolTipString(dirCtrl.GetValue())
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)
flexGridSizer.Add(lineSizer, 1, wx.EXPAND)
@@ -1178,7 +1202,10 @@ class ProjectView(wx.lib.docview.View):
else: # Project context
itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None]
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:
if not itemID:
menu.AppendSeparator()
@@ -1384,8 +1411,9 @@ class ProjectView(wx.lib.docview.View):
findFile.Destroy()
if newpath:
# update Project Model with new location
self.GetDocument().RemoveFile(filepath)
self.GetDocument().AddFile(newpath)
project = self._GetItemProject(item)
project.RemoveFile(filepath)
project.AddFile(newpath)
filepath = newpath
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(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)
sizer.Fit(self)
self.Layout()
@@ -1742,7 +1769,7 @@ class ProjectService(Service.Service):
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)
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_UPDATE_UI(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
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():
# 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:
self.GetCtrl().SetFocus()
self.SetFocus()
else:
wx.CallAfter(self.GetCtrl().SetFocus)
wx.CallAfter(self.SetFocus)
def SetFocus(self):
if self.GetCtrl():
self.GetCtrl().SetFocus()
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
#----------------------------------------------------------------------------
import logging
import cStringIO
import traceback
import sys
import string
import os
def classForName(className):
pathList = className.split('.')
moduleName = string.join(pathList[:-1], '.')
code = __import__(moduleName)
for name in pathList[1:]:
code = code.__dict__[name]
return code
def _registerMainModuleDir():
global mainModuleDir
if sys.executable.find('python') != -1:
utilModuleDir = os.path.dirname(__file__)
if not os.path.isabs(utilModuleDir):
utilModuleDir = os.path.join(os.getcwd(), utilModuleDir)
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):
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()
_registerMainModuleDir()

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.
# License: wxWindows License
#----------------------------------------------------------------------------
from activegrid import util
import inspect
import __builtin__
import sys
from types import *
import xml.sax
import xml.sax.handler
import __builtin__
from xml.sax import saxutils
import objutils
MODULE_PATH = "__main__"
### 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__',
'__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
@@ -200,7 +157,6 @@ MEMBERS_TO_SKIP = ('__module__', '__doc__', '__xmlname__', '__xmlattributes__',
################################################################################
def _objectfactory(objname, objargs=None, xsname=None):
try:
'''dynamically create an object based on the objname and return
it. look it up in the BASETYPE_ELEMENT_MAP first.
'''
@@ -220,25 +176,23 @@ def _objectfactory(objname, objargs=None, xsname=None):
pathlist = objname.split('.')
modulename = '.'.join(pathlist[0:-1])
## print "[objectfactory] objtype is %s" % objtype
## print "[objectfactory] objargs is %s" % `objargs`
## since the bool constructor will turn a string of non-zero
## length into True, we call it with no argument (yielding a
## False) if the string contains 'false'
if objtype == 'bool' and objargs[0].lower() == 'false':
objargs = None
## if objtype == 'str':
## print type(objargs)
## print "string we're unescaping: '%s'" % objargs[0]
## objargs = saxutils.unescape(objargs[0])
if objtype in ('float', 'int', 'str', 'long'):
## print "[objectfactory] object [%s] %s(%r)" % (objname, objtype, objargs)
if objname == 'bool':
return not objargs[0].lower() == 'false'
elif objname == 'str': # don't strip strings - blanks are significant !!!
if len(objargs) > 0:
return saxutils.unescape(objargs[0]).encode()
else:
return ''
elif objname == 'unicode': # don't strip strings - blanks are significant !!!
if len(objargs) > 0:
return saxutils.unescape(objargs[0]).encode()
else:
return ''
elif objtype in ('float', 'int', 'str', 'long'):
objargs = [x.strip() for x in objargs]
if objtype == 'str':
objargs = [saxutils.unescape(x) for x in objargs]
try:
if __builtin__.__dict__.has_key(objname):
module = __builtin__
else:
@@ -379,7 +333,7 @@ class XMLObjectFactory(xml.sax.ContentHandler):
if attrname == "maxOccurs" and attr == "unbounded":
attr = "-1"
attr = _objectfactory(type, attr)
util.setattrignorecase(obj, _toAttrName(obj, attrname), attr)
objutils.setattrignorecase(obj, _toAttrName(obj, attrname), attr)
## obj.__dict__[_toAttrName(obj, attrname)] = attr
# stuff any child attributes meant to be in a sequence via the __xmlflattensequence__
flattenDict = {}
@@ -407,9 +361,7 @@ class XMLObjectFactory(xml.sax.ContentHandler):
try:
## print "[endElement] obj.__dict__ is: ", obj.__dict__
sequencevalue = obj.__dict__[sequencename]
except AttributeError:
sequencevalue = None
except KeyError:
except (AttributeError, KeyError):
sequencevalue = None
if sequencevalue == None:
sequencevalue = []
@@ -420,7 +372,7 @@ class XMLObjectFactory(xml.sax.ContentHandler):
obj.append(child)
else:
## 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
if complexType:
@@ -474,6 +426,8 @@ def xsdToPythonType(xsdType):
def _getXmlValue(pythonValue):
if (isinstance(pythonValue, bool)):
return str(pythonValue).lower()
elif (isinstance(pythonValue, unicode)):
return pythonValue.encode()
else:
return str(pythonValue)
@@ -488,7 +442,17 @@ def unmarshal(xmlstr, knownTypes=None):
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:
prefix = ' '*indent
newline = '\n'
@@ -563,7 +527,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
except KeyError:
continue
## # But, check and see if it is a property first:
## if (hasPropertyValue(obj, attr)):
## if (objutils.hasPropertyValue(obj, attr)):
## value = getattr(obj, attr)
## else:
## continue
@@ -593,7 +557,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
if hasattr(obj, '__xmlattrnamespaces__'):
## print "marshal: found __xmlattrnamespaces__"
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
if attr in nameSpaceAttributes:
attrNameSpacePrefix = nameSpaceKey + ':'
@@ -607,95 +571,76 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, value)
## print "marshal: new objattrs is: ", objattrs
objtype = type(obj)
if isinstance(obj, NoneType):
#print "marshal: skipping an element with no type"
return ''
# return '%s<%s objtype="None"/>%s' % (prefix, elementName, newline)
elif isinstance(obj, bool):
xmlString = '%s<%s objtype="bool">%s</%s>%s' % (prefix, elementName, obj, elementName, newline)
#print "marshal: returning a bool element: \n", xmlString
return xmlString
return ['%s<%s objtype="bool">%s</%s>%s' % (prefix, elementName, obj, elementName, newline)]
elif isinstance(obj, int):
xmlString = '''%s<%s objtype="int">%s</%s>%s''' % (prefix, elementName, str(obj), elementName, newline)
#print "marshal: returning a int element: \n", xmlString
return xmlString
return ['''%s<%s objtype="int">%s</%s>%s''' % (prefix, elementName, str(obj), elementName, newline)]
elif isinstance(obj, long):
xmlString = '%s<%s objtype="long">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline)
#print "marshal: returning a long element: \n", xmlString
return xmlString
return ['%s<%s objtype="long">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline)]
elif isinstance(obj, float):
xmlString = '%s<%s objtype="float">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline)
#print "marshal: returning a float element: \n", xmlString
return xmlString
return ['%s<%s objtype="float">%s</%s>%s' % (prefix, elementName, str(obj), elementName, newline)]
elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string
return ['''%s<%s>%s</%s>%s''' % (prefix, elementName, saxutils.escape(obj.encode()), elementName, newline)]
elif isinstance(obj, basestring):
xmlString = '''%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)
return ['''%s<%s>%s</%s>%s''' % (prefix, elementName, saxutils.escape(obj), elementName, newline)]
elif isinstance(obj, list):
if len(obj) < 1:
#print "marshal: skipping an empty list"
return ''
xmlString = '%s<%s objtype="list">%s' % (prefix, elementName, newline)
xmlString = ['%s<%s objtype="list">%s' % (prefix, elementName, newline)]
for item in obj:
xmlString += marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)
xmlString += '%s</%s>%s' % (prefix, elementName, newline)
#print "marshal: returning a list element: \n", xmlString
xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
return xmlString
elif isinstance(obj, tuple):
if len(obj) < 1:
#print "marshal: skipping an empty tuple"
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:
xmlString += marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)
xmlString += '%s</%s>%s' % (prefix, elementName, newline)
#print "marshal: returning a tuple element: \n", xmlString
xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
return xmlString
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
subindent = indent + 2*increment
for key, val in obj.iteritems():
xmlString += "%s<key>%s%s%s</key>%s%s<value>%s%s%s</value>%s" \
% (subprefix, newline, marshal(key, indent=subindent, knownTypes=knownTypes), subprefix, newline, subprefix, newline, marshal(val, nameSpaces=nameSpaces, indent=subindent, knownTypes=knownTypes), subprefix, newline)
xmlString += '%s</%s>%s' % (prefix, elementName, newline)
#print "marshal: returning a dict element: \n", xmlString
xmlString.append("%s<key>%s" % (subprefix, newline))
xmlString.extend(_marshal(key, indent=subindent, knownTypes=knownTypes))
xmlString.append("%s</key>%s%s<value>%s" % (subprefix, newline, subprefix, newline))
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
else:
moduleName = obj.__class__.__module__
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:
## print "marshal: found a ", moduleName, " class element"
# Only add the objtype if the element tag is unknown to us.
try:
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:
## 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)
# get the member, value pairs for the object, filtering out
# the types we don't support.
## print "marshal: elementString: \n", xmlString
# get the member, value pairs for the object, filtering out the types we don't support
if (elementAdd != None):
prefix += increment*' '
indent += increment
xmlMemberString = ''
xmlMemberString = []
if hasattr(obj, '__xmlbody__'):
xmlMemberString = getattr(obj, obj.__xmlbody__)
xmlbody = getattr(obj, obj.__xmlbody__)
if xmlbody != None:
xmlMemberString.append(xmlbody)
else:
entryList = obj.__dict__.items()
## # Add in properties
## for key in obj.__class__.__dict__.iterkeys():
## 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)
## entryList.append((key, value))
entryList.sort()
@@ -719,7 +664,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
if (eName != '__nogroup__'):
prefix += 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:
value = obj.__dict__[name]
## print " ", name, " = ", value
@@ -754,91 +699,38 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr
xmlname = name
## xmlname = name.lower()
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:
if (hasattr(obj, "__xmlrename__") and name in obj.__xmlrename__):
xmlname = obj.__xmlrename__[name]
else:
xmlname = name
## xmlname = name.lower()
## # skip
## if xmlname.startswith('_') and not xmlname.startswith('__'):
## xmlname = xmlname[1:]
## if (indent > 30):
## print "getting pretty deep, xmlname = ", xmlname
## print "marshal: marshalling ", xmlname
xmlMemberString += marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)
## print "marshal: back with new xmlMemberString: \n", xmlMemberString
xmlMemberString.extend(_marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes))
if (eName != '__nogroup__'):
## print "marshal: Completing attrGroup ", eName
xmlMemberString += '%s</%s>%s' % (prefix, eName, newline)
xmlMemberString.append('%s</%s>%s' % (prefix, eName, newline))
prefix = prefix[:-increment]
indent -= increment
# if we have nested elements, add them here, otherwise close the element tag immediately.
if xmlMemberString:
xmlString += '>'
xmlMemberString = filter(lambda x: len(x)>0, xmlMemberString)
if len(xmlMemberString) > 0:
xmlString.append('>')
if hasattr(obj, '__xmlbody__'):
xmlString += xmlMemberString
xmlString += '</%s>%s' % (elementName, newline)
xmlString.extend(xmlMemberString)
xmlString.append('</%s>%s' % (elementName, newline))
else:
xmlString += newline
xmlString.append(newline)
if (elementAdd != None):
xmlString += '%s<%s>%s' % (prefix, elementAdd, newline)
xmlString += xmlMemberString
xmlString.append('%s<%s>%s' % (prefix, elementAdd, newline))
xmlString.extend(xmlMemberString)
if (elementAdd != None):
xmlString += '%s</%s>%s' % (prefix, elementAdd, newline)
xmlString.append('%s</%s>%s' % (prefix, elementAdd, newline))
prefix = prefix[:-increment]
indent -= increment
xmlString += '%s</%s>%s' % (prefix, elementName, newline)
xmlString.append('%s</%s>%s' % (prefix, elementName, newline))
else:
xmlString = xmlString + '/>%s' % newline
xmlString.append('/>%s' % newline)
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
textService = self.InstallService(TextEditor.TextService())
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())
filePropertiesService = self.InstallService(pydocview.FilePropertiesService())
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))
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
templates = wx.GetApp().GetDocumentManager().GetTemplates()
iconList = wx.ImageList(16, 16, initialCount = len(templates))
@@ -825,6 +826,17 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
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):
"""
Handles right clicks for the notebook, enabling users to either close
@@ -842,6 +854,15 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
doc.DeleteAllViews()
wx.EVT_MENU(self, id, OnRightMenuSelect)
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()
tabsMenu = wx.Menu()
menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu)
@@ -899,6 +920,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
"""
index = self.GetNotebookPageIndex(panel)
if index > -1:
self._notebook.SetFocus()
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
general options pane that is included with the options service by setting
@@ -1273,7 +1295,7 @@ class DocOptionsService(DocService):
"""
DocService.__init__(self)
self.ClearOptionsPanels()
self._allowModeChanges = allowModeChanges
self._supportedModes = supportedModes
self._toolOptionsID = wx.NewId()
if showGeneralOptions:
self.AddOptionsPanel(GeneralOptionsPanel)
@@ -1310,20 +1332,20 @@ class DocOptionsService(DocService):
return False
def GetAllowModeChanges(self):
def GetSupportedModes(self):
"""
Return true if the default general options pane should allow users to
change the document interface mode between SDI and MDI modes.
Return the modes supported by the application. Use docview.DOC_SDI and
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
change the document interface mode between SDI and MDI modes.
Sets the modes supported by the application. Use docview.DOC_SDI and
docview.DOC_MDI flags to set if SDI and/or MDI modes are supported.
"""
self._allowModeChanges = allowModeChanges
self._supportedModes = supportedModes
def ClearOptionsPanels(self):
@@ -1430,20 +1452,27 @@ class GeneralOptionsPanel(wx.Panel):
config = wx.ConfigBase_Get()
self._showTipsCheckBox = wx.CheckBox(self, -1, _("Show tips at start up"))
self._showTipsCheckBox.SetValue(config.ReadInt("ShowTipAtStartup", True))
if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges():
choices = [_("Show each document in its own window"), _("Show all documents in a single window with tabs")]
if self._AllowModeChanges():
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__":
choices.append(_("Show all documents in a single window with child windows"))
choices.append(self._winMdiChoice)
self._documentRadioBox = wx.RadioBox(self, -1, _("Document Interface"),
choices = choices,
majorDimension=1,
)
if config.ReadInt("UseWinMDI", False):
self._documentRadioBox.SetSelection(2)
self._documentRadioBox.SetStringSelection(self._winMdiChoice)
elif config.ReadInt("UseMDI", True):
self._documentRadioBox.SetSelection(1)
self._documentRadioBox.SetStringSelection(self._mdiChoice)
else:
self._documentRadioBox.SetSelection(0)
self._documentRadioBox.SetStringSelection(self._sdiChoice)
def OnDocumentInterfaceSelect(event):
if not self._documentInterfaceMessageShown:
msgTitle = wx.GetApp().GetAppName()
@@ -1457,7 +1486,7 @@ class GeneralOptionsPanel(wx.Panel):
wx.EVT_RADIOBOX(self, self._documentRadioBox.GetId(), OnDocumentInterfaceSelect)
optionsBorderSizer = 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._showTipsCheckBox, 0, wx.ALL, HALF_SPACE)
optionsBorderSizer.Add(optionsSizer, 0, wx.ALL, SPACE)
@@ -1467,15 +1496,20 @@ class GeneralOptionsPanel(wx.Panel):
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):
"""
Updates the config based on the selections in the options panel.
"""
config = wx.ConfigBase_Get()
config.WriteInt("ShowTipAtStartup", self._showTipsCheckBox.GetValue())
if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges():
config.WriteInt("UseMDI", (self._documentRadioBox.GetSelection() == 1))
config.WriteInt("UseWinMDI", (self._documentRadioBox.GetSelection() == 2))
if self._AllowModeChanges():
config.WriteInt("UseMDI", (self._documentRadioBox.GetStringSelection() == self._mdiChoice))
config.WriteInt("UseWinMDI", (self._documentRadioBox.GetStringSelection() == self._winMdiChoice))
class DocApp(wx.PySimpleApp):