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:
@@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -84,6 +84,7 @@ class OutlineView(Service.ServiceView):
|
||||
item = self.GetControl().GetSelection()
|
||||
if item:
|
||||
self.GetControl().CallDoSelectCallback(item)
|
||||
event.Skip()
|
||||
|
||||
|
||||
def ResumeActionOnSelect(self):
|
||||
|
@@ -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")
|
||||
|
@@ -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):
|
||||
|
@@ -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):
|
||||
|
736
wxPython/samples/ide/activegrid/tool/SVNService.py
Normal file
736
wxPython/samples/ide/activegrid/tool/SVNService.py
Normal 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())
|
||||
|
@@ -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()
|
||||
|
||||
|
93
wxPython/samples/ide/activegrid/util/objutils.py
Normal file
93
wxPython/samples/ide/activegrid/util/objutils.py
Normal 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
|
@@ -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)
|
||||
|
@@ -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()
|
@@ -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
@@ -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):
|
||||
|
Reference in New Issue
Block a user