DocView patches from Morgen Hua: bug fixes, and additional SVN

commands, also added a default template that uses the text editor for
any unknown file type.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34473 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2005-05-31 21:41:11 +00:00
parent b81383bbd9
commit 26ee3a06e2
22 changed files with 1191 additions and 316 deletions

View File

@@ -59,7 +59,7 @@ class AboutDialog(wx.Dialog):
splash_bmp = getSplashBitmap() splash_bmp = getSplashBitmap()
image = wx.StaticBitmap(aboutPage, -1, splash_bmp, (0,0), (splash_bmp.GetWidth(), splash_bmp.GetHeight())) image = wx.StaticBitmap(aboutPage, -1, splash_bmp, (0,0), (splash_bmp.GetWidth(), splash_bmp.GetHeight()))
sizer.Add(image, 0, wx.ALIGN_CENTER|wx.ALL, 0) sizer.Add(image, 0, wx.ALIGN_CENTER|wx.ALL, 0)
sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\nVersion 0.6 Early Access\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors. All rights reserved.")), 0, wx.ALIGN_LEFT|wx.ALL, 10) sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\nVersion 0.7 Early Access\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors. All rights reserved.")), 0, wx.ALIGN_LEFT|wx.ALL, 10)
sizer.Add(wx.StaticText(aboutPage, -1, _("http://www.activegrid.com")), 0, wx.ALIGN_LEFT|wx.LEFT|wx.BOTTOM, 10) sizer.Add(wx.StaticText(aboutPage, -1, _("http://www.activegrid.com")), 0, wx.ALIGN_LEFT|wx.LEFT|wx.BOTTOM, 10)
aboutPage.SetSizer(sizer) aboutPage.SetSizer(sizer)
nb.AddPage(aboutPage, _("Copyright")) nb.AddPage(aboutPage, _("Copyright"))

View File

@@ -48,8 +48,17 @@ class CanvasView(wx.lib.docview.View):
self._pt2 = None self._pt2 = None
self._needEraseLasso = False self._needEraseLasso = False
self._propShape = None self._propShape = None
self._maxWidth = 2000
self._maxHeight = 16000
def OnDraw(self, dc):
""" for Print Preview and Print """
dc.BeginDrawing()
self._canvas.Redraw(dc)
dc.EndDrawing()
def OnCreate(self, doc, flags): def OnCreate(self, doc, flags):
frame = wx.GetApp().CreateDocumentFrame(self, doc, flags) frame = wx.GetApp().CreateDocumentFrame(self, doc, flags)
frame.Show() frame.Show()
@@ -130,9 +139,7 @@ class CanvasView(wx.lib.docview.View):
wx.EVT_KILL_FOCUS(self._canvas, self.OnKillFocus) wx.EVT_KILL_FOCUS(self._canvas, self.OnKillFocus)
wx.EVT_SET_FOCUS(self._canvas, self.OnFocus) wx.EVT_SET_FOCUS(self._canvas, self.OnFocus)
maxWidth = 2000 self._canvas.SetScrollbars(20, 20, self._maxWidth / 20, self._maxHeight / 20)
maxHeight = 16000
self._canvas.SetScrollbars(20, 20, maxWidth / 20, maxHeight / 20)
self._canvas.SetBackgroundColour(wx.WHITE) self._canvas.SetBackgroundColour(wx.WHITE)
self._diagram = ogl.Diagram() self._diagram = ogl.Diagram()
@@ -654,7 +661,16 @@ class EditorCanvasShapeEvtHandler(ogl.ShapeEvtHandler):
self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY) self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY)
def OnMovePre(self, dc, x, y, oldX, oldY, display):
""" Prevent objects from being dragged outside of viewable area """
if (x > self._view._maxWidth) or (y > self._view._maxHeight):
return False
return ogl.ShapeEvtHandler.OnMovePre(self, dc, x, y, oldX, oldY, display)
def OnMovePost(self, dc, x, y, oldX, oldY, display): def OnMovePost(self, dc, x, y, oldX, oldY, display):
""" Update the model's record of where the shape should be. Also enable redo/undo. """
if x == oldX and y == oldY: if x == oldX and y == oldY:
return return
if not self._view.GetDocument(): if not self._view.GetDocument():

View File

@@ -633,10 +633,8 @@ class CodeCtrl(STCTextEditor.TextCtrl):
BREAKPOINT_MARKER_MASK = 0x2 BREAKPOINT_MARKER_MASK = 0x2
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style = wx.NO_FULL_REPAINT_ON_RESIZE):
if ID == -1: STCTextEditor.TextCtrl.__init__(self, parent, id, style)
ID = wx.NewId()
STCTextEditor.TextCtrl.__init__(self, parent, ID, style)
self.UsePopUp(False) self.UsePopUp(False)
self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
@@ -672,10 +670,10 @@ class CodeCtrl(STCTextEditor.TextCtrl):
if _WINDOWS: # should test to see if menu item exists, if it does, add this workaround if _WINDOWS: # should test to see if menu item exists, if it does, add this workaround
self.CmdKeyClear(wx.stc.STC_KEY_TAB, 0) # menu item "Indent Lines" from CodeService.InstallControls() generates another INDENT_LINES_ID event, so we'll explicitly disable the tab processing in the editor self.CmdKeyClear(wx.stc.STC_KEY_TAB, 0) # menu item "Indent Lines" from CodeService.InstallControls() generates another INDENT_LINES_ID event, so we'll explicitly disable the tab processing in the editor
wx.stc.EVT_STC_MARGINCLICK(self, ID, self.OnMarginClick) wx.stc.EVT_STC_MARGINCLICK(self, self.GetId(), self.OnMarginClick)
wx.EVT_KEY_DOWN(self, self.OnKeyPressed) wx.EVT_KEY_DOWN(self, self.OnKeyPressed)
if self.GetMatchingBraces(): if self.GetMatchingBraces():
wx.stc.EVT_STC_UPDATEUI(self, ID, self.OnUpdateUI) wx.stc.EVT_STC_UPDATEUI(self, self.GetId(), self.OnUpdateUI)
self.StyleClearAll() self.StyleClearAll()
self.UpdateStyles() self.UpdateStyles()
@@ -720,7 +718,8 @@ class CodeCtrl(STCTextEditor.TextCtrl):
item = menuBar.FindItemById(itemID) item = menuBar.FindItemById(itemID)
if item: if item:
menu.Append(itemID, item.GetLabel()) menu.Append(itemID, item.GetLabel())
wx.EVT_MENU(self, itemID, self.DSProcessEvent) # wxHack: for customized right mouse menu doesn't work with new DynamicSashWindow
wx.EVT_UPDATE_UI(self, itemID, self.DSProcessUpdateUIEvent) # wxHack: for customized right mouse menu doesn't work with new DynamicSashWindow
return menu return menu
@@ -834,6 +833,7 @@ class CodeCtrl(STCTextEditor.TextCtrl):
def DoIndent(self): def DoIndent(self):
self.AddText('\n') self.AddText('\n')
self.EnsureCaretVisible()
# Need to do a default one for all languges # Need to do a default one for all languges

View File

@@ -22,6 +22,8 @@ import inspect
from xml.dom.minidom import getDOMImplementation from xml.dom.minidom import getDOMImplementation
import atexit import atexit
import pickle import pickle
import cStringIO
import bz2
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
import win32api import win32api
@@ -107,7 +109,7 @@ class Adb(bdb.Bdb):
exc_type_name = exc_type exc_type_name = exc_type
else: else:
exc_type_name = exc_type.__name__ exc_type_name = exc_type.__name__
message = "Exception occurred: " + repr(exc_type_name) + " See locals.__exception__ for details." message = "Exception occured: " + repr(exc_type_name) + " See locals.__exception__ for details."
traceback.print_exception(exc_type, exc_value, exc_traceback) traceback.print_exception(exc_type, exc_value, exc_traceback)
self._harness.interaction(message, frame, message) self._harness.interaction(message, frame, message)
@@ -189,8 +191,7 @@ class Adb(bdb.Bdb):
return "" return ""
def stop_here(self, frame): def stop_here(self, frame):
if( self._userBreak ): if self._userBreak:
self._userBreak = False
return True return True
@@ -270,6 +271,7 @@ class BreakListenerThread(threading.Thread):
if _VERBOSE: print "Before calling server close on breakpoint server" if _VERBOSE: print "Before calling server close on breakpoint server"
self._server.server_close() self._server.server_close()
if _VERBOSE: print "Calling server close on breakpoint server" if _VERBOSE: print "Calling server close on breakpoint server"
self._server = None
class DebuggerHarness(object): class DebuggerHarness(object):
@@ -312,8 +314,11 @@ class DebuggerHarness(object):
self._server.register_function(self.clear_breakpoint) self._server.register_function(self.clear_breakpoint)
self._server.register_function(self.set_all_breakpoints) self._server.register_function(self.set_all_breakpoints)
self._server.register_function(self.attempt_introspection) self._server.register_function(self.attempt_introspection)
self._server.register_function(self.execute_in_frame)
self._server.register_function(self.add_watch) self._server.register_function(self.add_watch)
self._server.register_function(self.request_frame_document)
self.frame_stack = []
self.message_frame_dict = {} self.message_frame_dict = {}
self.introspection_list = [] self.introspection_list = []
atexit.register(self.do_exit) atexit.register(self.do_exit)
@@ -364,7 +369,28 @@ class DebuggerHarness(object):
tp, val, tb = sys.exc_info() tp, val, tb = sys.exc_info()
return self.get_exception_document(tp, val, tb) return self.get_exception_document(tp, val, tb)
return "" return ""
def execute_in_frame(self, frame_message, command):
frame = self.message_frame_dict[frame_message]
output = cStringIO.StringIO()
out = sys.stdout
err = sys.stderr
sys.stdout = output
sys.stderr = output
try:
exec command in frame.f_globals, frame.f_locals
return output.getvalue()
sys.stdout = out
sys.stderr = err
except:
sys.stdout = out
sys.stderr = err
tp, val, tb = sys.exc_info()
output = cStringIO.StringIO()
traceback.print_exception(tp, val, tb, file=output)
return output.getvalue()
def attempt_introspection(self, frame_message, chain): def attempt_introspection(self, frame_message, chain):
try: try:
frame = self.message_frame_dict[frame_message] frame = self.message_frame_dict[frame_message]
@@ -608,22 +634,27 @@ class DebuggerHarness(object):
def getFrameXML(self, base_frame): def getFrameXML(self, base_frame):
doc = getDOMImplementation().createDocument(None, "stack", None)
top_element = doc.documentElement
stack = [] self.frame_stack = []
frame = base_frame frame = base_frame
while frame is not None: while frame is not None:
if((frame.f_code.co_filename.count('DebuggerHarness.py') == 0) or _DEBUG_DEBUGGER): if((frame.f_code.co_filename.count('DebuggerHarness.py') == 0) or _DEBUG_DEBUGGER):
stack.append(frame) self.frame_stack.append(frame)
frame = frame.f_back frame = frame.f_back
stack.reverse() self.frame_stack.reverse()
self.message_frame_dict = {} self.message_frame_dict = {}
for f in stack: doc = getDOMImplementation().createDocument(None, "stack", None)
self.addFrame(f,top_element, doc) top_element = doc.documentElement
numberFrames = len(self.frame_stack)
for index in range(numberFrames):
frame = self.frame_stack[index]
message = self._adb.frame2message(frame)
# We include globals and locals only for the last frame as an optimization for cases
# where there are a lot of frames.
self.addFrame(frame, top_element, doc, includeContent=(index == numberFrames - 1))
return doc.toxml() return doc.toxml()
def addFrame(self, frame, root_element, document): def addFrame(self, frame, root_element, document, includeContent=False):
frameNode = document.createElement('frame') frameNode = document.createElement('frame')
root_element.appendChild(frameNode) root_element.appendChild(frameNode)
@@ -633,11 +664,19 @@ class DebuggerHarness(object):
frameNode.setAttribute('line', str(frame.f_lineno)) frameNode.setAttribute('line', str(frame.f_lineno))
message = self._adb.frame2message(frame) message = self._adb.frame2message(frame)
frameNode.setAttribute('message', message) frameNode.setAttribute('message', message)
#print "Frame: %s %s %s" %(message, frame.f_lineno, filename)
self.message_frame_dict[message] = frame self.message_frame_dict[message] = frame
self.addDict(frameNode, "locals", frame.f_locals, document, 2) if includeContent:
self.addNode(frameNode, "globals", frame.f_globals, document) self.addDict(frameNode, "locals", frame.f_locals, document, 2)
self.addNode(frameNode, "globals", frame.f_globals, document)
def request_frame_document(self, message):
frame = self.message_frame_dict[message]
doc = getDOMImplementation().createDocument(None, "stack", None)
top_element = doc.documentElement
if frame:
self.addFrame(frame, top_element, doc, includeContent=True)
return xmlrpclib.Binary(bz2.compress(doc.toxml()))
def getRepr(self, varName, globals, locals): def getRepr(self, varName, globals, locals):
try: try:
return repr(eval(varName, globals, locals)) return repr(eval(varName, globals, locals))
@@ -647,23 +686,25 @@ class DebuggerHarness(object):
def saferepr(self, thing): def saferepr(self, thing):
try: try:
return repr(thing) try:
return repr(thing)
except:
return str(type(thing))
except: except:
tp, val, tb = sys.exc_info() tp, val, tb = sys.exc_info()
traceback.print_exception(tp, val, tb) #traceback.print_exception(tp, val, tb)
return repr(val) return repr(val)
# The debugger calls this method when it reaches a breakpoint. # The debugger calls this method when it reaches a breakpoint.
def interaction(self, message, frame, info): def interaction(self, message, frame, info):
if _VERBOSE: if _VERBOSE:
print 'hit debug side interaction' print 'hit debug side interaction'
self._userBreak = False self._adb._userBreak = False
self._currentFrame = frame self._currentFrame = frame
done = False done = False
while not done: while not done:
try: try:
import bz2
xml = self.getFrameXML(frame) xml = self.getFrameXML(frame)
arg = xmlrpclib.Binary(bz2.compress(xml)) arg = xmlrpclib.Binary(bz2.compress(xml))
if _VERBOSE: if _VERBOSE:

View File

@@ -41,6 +41,7 @@ import pickle
import DebuggerHarness import DebuggerHarness
import traceback import traceback
import StringIO import StringIO
if wx.Platform == '__WXMSW__': if wx.Platform == '__WXMSW__':
try: try:
import win32api import win32api
@@ -72,7 +73,12 @@ class OutputReaderThread(threading.Thread):
self._lineCount = 0 self._lineCount = 0
self._accumulate = accumulate self._accumulate = accumulate
self._callbackOnExit = callbackOnExit self._callbackOnExit = callbackOnExit
self.setDaemon(True)
def __del__(self):
# See comment on DebugCommandUI.StopExecution
self._keepGoing = False
def run(self): def run(self):
file = self._file file = self._file
start = time.time() start = time.time()
@@ -83,7 +89,7 @@ class OutputReaderThread(threading.Thread):
text = file.readline() text = file.readline()
if text == '' or text == None: if text == '' or text == None:
self._keepGoing = False self._keepGoing = False
elif not self._accumulate: elif not self._accumulate and self._keepGoing:
self._callback_function(text) self._callback_function(text)
else: else:
# Should use a buffer? StringIO? # Should use a buffer? StringIO?
@@ -91,11 +97,11 @@ class OutputReaderThread(threading.Thread):
# Seems as though the read blocks if we got an error, so, to be # Seems as though the read blocks if we got an error, so, to be
# sure that at least some of the exception gets printed, always # sure that at least some of the exception gets printed, always
# send the first hundred lines back as they come in. # send the first hundred lines back as they come in.
if self._lineCount < 100: if self._lineCount < 100 and self._keepGoing:
self._callback_function(output) self._callback_function(output)
self._lineCount += 1 self._lineCount += 1
output = "" output = ""
elif time.time() - start > 0.25: elif time.time() - start > 0.25 and self._keepGoing:
try: try:
self._callback_function(output) self._callback_function(output)
except wx._core.PyDeadObjectError: except wx._core.PyDeadObjectError:
@@ -103,8 +109,8 @@ class OutputReaderThread(threading.Thread):
self._keepGoing = False self._keepGoing = False
start = time.time() start = time.time()
output = "" output = ""
except TypeError: #except TypeError:
pass # pass
except: except:
tp, val, tb = sys.exc_info() tp, val, tb = sys.exc_info()
print "Exception in OutputReaderThread.run():", tp, val print "Exception in OutputReaderThread.run():", tp, val
@@ -118,7 +124,7 @@ class OutputReaderThread(threading.Thread):
def AskToStop(self): def AskToStop(self):
self._keepGoing = False self._keepGoing = False
import wx.lib.newevent import wx.lib.newevent
(UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent() (UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent()
(UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent() (UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent()
@@ -165,7 +171,6 @@ class Executor:
self._stdOutReader = None self._stdOutReader = None
self._stdErrReader = None self._stdErrReader = None
self._process = None self._process = None
DebuggerService.executors.append(self)
def OutCall(self, text): def OutCall(self, text):
evt = UpdateTextEvent(value = text) evt = UpdateTextEvent(value = text)
@@ -180,8 +185,6 @@ class Executor:
startIn = str(os.getcwd()) startIn = str(os.getcwd())
startIn = os.path.abspath(startIn) startIn = os.path.abspath(startIn)
command = self._cmd + ' ' + arguments command = self._cmd + ' ' + arguments
#stdinput = process.IOBuffer()
#self._process = process.ProcessProxy(command, mode='b', cwd=startIn, stdin=stdinput)
self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment) self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment)
# Kick off threads to read stdout and stderr and write them # Kick off threads to read stdout and stderr and write them
# to our text control. # to our text control.
@@ -189,35 +192,46 @@ class Executor:
self._stdOutReader.start() self._stdOutReader.start()
self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False) self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False)
self._stdErrReader.start() self._stdErrReader.start()
def DoStopExecution(self): def DoStopExecution(self):
# See comment on DebugCommandUI.StopExecution
if(self._process != None): if(self._process != None):
self._process.kill()
self._process.close()
self._process = None
if(self._stdOutReader != None):
self._stdOutReader.AskToStop() self._stdOutReader.AskToStop()
if(self._stdErrReader != None):
self._stdErrReader.AskToStop() self._stdErrReader.AskToStop()
DebuggerService.executors.remove(self) try:
self._process.kill(gracePeriod=2.0)
except:
pass
self._process = None
class RunCommandUI(wx.Panel): class RunCommandUI(wx.Panel):
runners = []
def ShutdownAllRunners():
# See comment on DebugCommandUI.StopExecution
for runner in RunCommandUI.runners:
try:
runner.StopExecution(None)
except wx._core.PyDeadObjectError:
pass
RunCommandUI.runners = []
ShutdownAllRunners = staticmethod(ShutdownAllRunners)
def __init__(self, parent, id, fileName): def __init__(self, parent, id, fileName):
wx.Panel.__init__(self, parent, id) wx.Panel.__init__(self, parent, id)
self._noteBook = parent self._noteBook = parent
threading._VERBOSE = _VERBOSE
self.KILL_PROCESS_ID = wx.NewId() self.KILL_PROCESS_ID = wx.NewId()
self.CLOSE_TAB_ID = wx.NewId() self.CLOSE_TAB_ID = wx.NewId()
self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded)
# GUI Initialization follows # GUI Initialization follows
sizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL)
self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" ) self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" )
tb.SetToolBitmapSize((16,16)) tb.SetToolBitmapSize((16,16))
sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1) sizer.Add(tb, 0, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL, 1)
close_bmp = getCloseBitmap() close_bmp = getCloseBitmap()
tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window')) tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window'))
@@ -245,12 +259,16 @@ class RunCommandUI(wx.Panel):
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self) sizer.Fit(self)
self._stopped = False
# Executor initialization # Executor initialization
self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished) self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished)
self.Bind(EVT_UPDATE_STDTEXT, self.AppendText) self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText) self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
RunCommandUI.runners.append(self)
def __del__(self): def __del__(self):
# See comment on DebugCommandUI.StopExecution
self._executor.DoStopExecution() self._executor.DoStopExecution()
def Execute(self, initialArgs, startIn, environment): def Execute(self, initialArgs, startIn, environment):
@@ -267,9 +285,11 @@ class RunCommandUI(wx.Panel):
break break
def StopExecution(self): def StopExecution(self):
self.Unbind(EVT_UPDATE_STDTEXT) if not self._stopped:
self.Unbind(EVT_UPDATE_ERRTEXT) self._stopped = True
self._executor.DoStopExecution() self.Unbind(EVT_UPDATE_STDTEXT)
self.Unbind(EVT_UPDATE_ERRTEXT)
self._executor.DoStopExecution()
def AppendText(self, event): def AppendText(self, event):
self._textCtrl.SetReadOnly(False) self._textCtrl.SetReadOnly(False)
@@ -295,10 +315,10 @@ class RunCommandUI(wx.Panel):
id = event.GetId() id = event.GetId()
if id == self.KILL_PROCESS_ID: if id == self.KILL_PROCESS_ID:
self._executor.DoStopExecution() self.StopExecution()
elif id == self.CLOSE_TAB_ID: elif id == self.CLOSE_TAB_ID:
self._executor.DoStopExecution() self.StopExecution()
index = self._noteBook.GetSelection() index = self._noteBook.GetSelection()
self._noteBook.GetPage(index).Show(False) self._noteBook.GetPage(index).Show(False)
self._noteBook.RemovePage(index) self._noteBook.RemovePage(index)
@@ -349,8 +369,6 @@ class RunCommandUI(wx.Panel):
foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM) foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
def OnProcessEnded(self, evt):
self._executor.DoStopExecution()
DEFAULT_PORT = 32032 DEFAULT_PORT = 32032
DEFAULT_HOST = 'localhost' DEFAULT_HOST = 'localhost'
@@ -374,9 +392,13 @@ class DebugCommandUI(wx.Panel):
DebuggerRunning = staticmethod(DebuggerRunning) DebuggerRunning = staticmethod(DebuggerRunning)
def ShutdownAllDebuggers(): def ShutdownAllDebuggers():
# See comment on DebugCommandUI.StopExecution
for debugger in DebugCommandUI.debuggers: for debugger in DebugCommandUI.debuggers:
debugger.StopExecution(None) try:
debugger.StopExecution(None)
except wx._core.PyDeadObjectError:
pass
DebugCommandUI.debuggers = []
ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers) ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
def GetAvailablePort(): def GetAvailablePort():
@@ -549,9 +571,8 @@ class DebugCommandUI(wx.Panel):
self.framesTab.PopulateBPList() self.framesTab.PopulateBPList()
def __del__(self): def __del__(self):
if self in DebugCommandUI.debuggers: # See comment on DebugCommandUI.StopExecution
DebugCommandUI.debuggers.remove(self) self.StopExecution(None)
def DisableWhileDebuggerRunning(self): def DisableWhileDebuggerRunning(self):
self._tb.EnableTool(self.STEP_ID, False) self._tb.EnableTool(self.STEP_ID, False)
@@ -655,23 +676,42 @@ class DebugCommandUI(wx.Panel):
def StopExecution(self, event): def StopExecution(self, event):
self._stopped = True # This is a general comment on shutdown for the running and debugged processes. Basically, the
self.DisableAfterStop() # current state of this is the result of trial and error coding. The common problems were memory
try: # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
self._callback.ServerClose() # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
except: # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
pass # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
try: # it on to mfryer@activegrid.com.
if self._executor: if not self._stopped:
self._executor.DoStopExecution() self._stopped = True
self._executor = None try:
except: self.DisableAfterStop()
pass except wx._core.PyDeadObjectError:
self.DeleteCurrentLineMarkers() pass
DebugCommandUI.ReturnPortToPool(self._debuggerPort) try:
DebugCommandUI.ReturnPortToPool(self._guiPort) self._callback.ShutdownServer()
DebugCommandUI.ReturnPortToPool(self._debuggerBreakPort) except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
try:
self.DeleteCurrentLineMarkers()
except:
pass
try:
DebugCommandUI.ReturnPortToPool(self._debuggerPort)
DebugCommandUI.ReturnPortToPool(self._guiPort)
DebugCommandUI.ReturnPortToPool(self._debuggerBreakPort)
except:
pass
try:
if self._executor:
self._executor.DoStopExecution()
self._executor = None
except:
tp,val,tb = sys.exc_info()
traceback.print_exception(tp, val, tb)
def StopAndRemoveUI(self, event): def StopAndRemoveUI(self, event):
self.StopExecution(None) self.StopExecution(None)
if self in DebugCommandUI.debuggers: if self in DebugCommandUI.debuggers:
@@ -695,7 +735,7 @@ class DebugCommandUI(wx.Panel):
self.framesTab.AppendErrorText(event.value) self.framesTab.AppendErrorText(event.value)
def OnClearOutput(self, event): def OnClearOutput(self, event):
self.framesTab.ClearOutput() self.framesTab.ClearOutput(None)
def SwitchToOutputTab(self): def SwitchToOutputTab(self):
self.framesTab.SwitchToOutputTab() self.framesTab.SwitchToOutputTab()
@@ -899,10 +939,10 @@ class FramesUI(wx.SplitterWindow):
self._notebook.Hide() self._notebook.Hide()
sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1) sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId()) self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId())
#self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId()) self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId()) self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
self._notebook.AddPage(self.consoleTab, "Output") self._notebook.AddPage(self.consoleTab, "Output")
#self._notebook.AddPage(self.inspectConsoleTab, "Interact") self._notebook.AddPage(self.inspectConsoleTab, "Interact")
self._notebook.AddPage(self.breakPointsTab, "Break Points") self._notebook.AddPage(self.breakPointsTab, "Break Points")
self.SetMinimumPaneSize(20) self.SetMinimumPaneSize(20)
@@ -936,23 +976,74 @@ class FramesUI(wx.SplitterWindow):
return panel return panel
def MakeInspectConsoleTab(self, parent, id): def MakeInspectConsoleTab(self, parent, id):
def OnEnterPressed(event): self.command_list = []
print "Enter text was %s" % event.GetString() self.command_index = 0
def OnText(event): def ExecuteCommand(command):
print "Command was %s" % event.GetString() if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]:
self.command_list.append(command)
self.command_index = len(self.command_list) - 1
retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command)
self._interCtrl.AddText("\n" + str(retval))
self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount())
# Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection())
def ReplaceLastLine(command):
line = self._interCtrl.GetLineCount() - 1
self._interCtrl.GotoLine(line)
start = self._interCtrl.GetCurrentPos()
self._interCtrl.SetTargetStart(start)
end = self._interCtrl.GetLineEndPosition(line)
self._interCtrl.SetTargetEnd(end)
self._interCtrl.ReplaceTarget(">>> " + command)
self._interCtrl.GotoLine(line)
self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line))
panel = wx.Panel(parent, id) def OnKeyPressed(event):
try: key = event.KeyCode()
if key == wx.WXK_DELETE or key == wx.WXK_BACK:
if self._interCtrl.GetLine(self._interCtrl.GetCurrentLine()) == ">>> ":
return
elif key == wx.WXK_RETURN:
command = self._interCtrl.GetLine(self._interCtrl.GetCurrentLine())[4:]
ExecuteCommand(command)
self._interCtrl.AddText("\n>>> ")
return
elif key == wx.WXK_UP:
if not len(self.command_list):
return
ReplaceLastLine(self.command_list[self.command_index])
if self.command_index == 0:
self.command_index = len(self.command_list) - 1
else:
self.command_index = self.command_index - 1
return
elif key == wx.WXK_DOWN:
if not len(self.command_list):
return
if self.command_index < len(self.command_list) - 1:
self.command_index = self.command_index + 1
else:
self.command_index = 0
ReplaceLastLine(self.command_list[self.command_index])
return
event.Skip()
try:
panel = wx.Panel(parent, id)
sizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL)
self._ictextCtrl = wx.TextCtrl(panel, wx.NewId(), style=wx.TE_MULTILINE|wx.TE_RICH|wx.HSCROLL) self._interCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
sizer.Add(self._ictextCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2) sizer.Add(self._interCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
self._ictextCtrl.Bind(wx.EVT_TEXT_ENTER, OnEnterPressed) self._interCtrl.SetViewLineNumbers(False)
self._ictextCtrl.Bind(wx.EVT_TEXT, OnText)
if wx.Platform == '__WXMSW__': if wx.Platform == '__WXMSW__':
font = "Courier New" font = "Courier New"
else: else:
font = "Courier" font = "Courier"
self._ictextCtrl.SetDefaultStyle(wx.TextAttr(font=wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))) self._interCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
self._interCtrl.SetFontColor(wx.BLACK)
self._interCtrl.StyleClearAll()
wx.EVT_KEY_DOWN(self._interCtrl, OnKeyPressed)
self._interCtrl.AddText(">>> ")
panel.SetSizer(sizer) panel.SetSizer(sizer)
except: except:
tp, val, tb = sys.exc_info() tp, val, tb = sys.exc_info()
@@ -1066,6 +1157,7 @@ class FramesUI(wx.SplitterWindow):
tree = self._treeCtrl tree = self._treeCtrl
root = self._root root = self._root
tree.DeleteChildren(root) tree.DeleteChildren(root)
self._interCtrl.Enable(False)
#tree.Hide() #tree.Hide()
@@ -1088,6 +1180,8 @@ class FramesUI(wx.SplitterWindow):
def LoadFramesListXML(self, framesXML): def LoadFramesListXML(self, framesXML):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
self._interCtrl.Enable(True)
try: try:
domDoc = parseString(framesXML) domDoc = parseString(framesXML)
list = self._framesChoiceCtrl list = self._framesChoiceCtrl
@@ -1103,6 +1197,7 @@ class FramesUI(wx.SplitterWindow):
frame_count += 1 frame_count += 1
index = len(self._stack) - 1 index = len(self._stack) - 1
list.SetSelection(index) list.SetSelection(index)
node = self._stack[index] node = self._stack[index]
self.currentItem = index self.currentItem = index
self.PopulateTreeFromFrameNode(node) self.PopulateTreeFromFrameNode(node)
@@ -1121,13 +1216,20 @@ class FramesUI(wx.SplitterWindow):
def ListItemSelected(self, event): def ListItemSelected(self, event):
message = event.GetString() self.PopulateTreeFromFrameMessage(event.GetString())
self.OnSyncFrame(None)
def PopulateTreeFromFrameMessage(self, message):
index = 0 index = 0
for node in self._stack: for node in self._stack:
if node.getAttribute("message") == message: if node.getAttribute("message") == message:
binType = self._ui._callback._debuggerServer.request_frame_document(message)
xmldoc = bz2.decompress(binType.data)
domDoc = parseString(xmldoc)
nodeList = domDoc.getElementsByTagName('frame')
self.currentItem = index self.currentItem = index
self.PopulateTreeFromFrameNode(node) if len(nodeList):
self.OnSyncFrame(None) self.PopulateTreeFromFrameNode(nodeList[0])
return return
index = index + 1 index = index + 1
@@ -1146,7 +1248,8 @@ class FramesUI(wx.SplitterWindow):
if not firstChild: if not firstChild:
firstChild = treeNode firstChild = treeNode
tree.Expand(root) tree.Expand(root)
tree.Expand(firstChild) if firstChild:
tree.Expand(firstChild)
self._p2.FitInside() self._p2.FitInside()
def IntrospectCallback(self, event): def IntrospectCallback(self, event):
@@ -1252,7 +1355,13 @@ class DebuggerView(Service.ServiceView):
def OnToolClicked(self, event): def OnToolClicked(self, event):
self.GetFrame().ProcessEvent(event) self.GetFrame().ProcessEvent(event)
def ProcessUpdateUIEvent(self, event):
return False
def ProcessEvent(self, event):
return False
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Class methods # Class methods
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -1396,9 +1505,9 @@ class DebuggerCallback:
def start(self): def start(self):
self._serverHandlerThread.start() self._serverHandlerThread.start()
def ServerClose(self): def ShutdownServer(self):
rbt = RequestBreakThread(self._breakServer, kill=True) #rbt = RequestBreakThread(self._breakServer, kill=True)
rbt.start() #rbt.start()
self.setWaiting(False) self.setWaiting(False)
if self._serverHandlerThread: if self._serverHandlerThread:
self._serverHandlerThread.AskToStop() self._serverHandlerThread.AskToStop()
@@ -1410,29 +1519,21 @@ class DebuggerCallback:
def SingleStep(self): def SingleStep(self):
self._debuggerUI.DisableWhileDebuggerRunning() self._debuggerUI.DisableWhileDebuggerRunning()
#dot = DebuggerOperationThread(self._debuggerServer.set_step)
#dot.start()
self._debuggerServer.set_step() # Figure out where to set allowNone self._debuggerServer.set_step() # Figure out where to set allowNone
self.waitForRPC() self.waitForRPC()
def Next(self): def Next(self):
self._debuggerUI.DisableWhileDebuggerRunning() self._debuggerUI.DisableWhileDebuggerRunning()
#dot = DebuggerOperationThread(self._debuggerServer.set_next)
#dot.start()
self._debuggerServer.set_next() self._debuggerServer.set_next()
self.waitForRPC() self.waitForRPC()
def Continue(self): def Continue(self):
self._debuggerUI.DisableWhileDebuggerRunning() self._debuggerUI.DisableWhileDebuggerRunning()
#dot = DebuggerOperationThread(self._debuggerServer.set_continue)
#dot.start()
self._debuggerServer.set_continue() self._debuggerServer.set_continue()
self.waitForRPC() self.waitForRPC()
def Return(self): def Return(self):
self._debuggerUI.DisableWhileDebuggerRunning() self._debuggerUI.DisableWhileDebuggerRunning()
#dot = DebuggerOperationThread(self._debuggerServer.set_return)
#dot.start()
self._debuggerServer.set_return() self._debuggerServer.set_return()
self.waitForRPC() self.waitForRPC()
@@ -1498,7 +1599,6 @@ class DebuggerCallback:
if _VERBOSE: print "+"*40 if _VERBOSE: print "+"*40
class DebuggerService(Service.Service): class DebuggerService(Service.Service):
executors = []
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Constants # Constants
@@ -1509,11 +1609,6 @@ class DebuggerService(Service.Service):
DEBUG_ID = wx.NewId() DEBUG_ID = wx.NewId()
DEBUG_WEBSERVER_ID = wx.NewId() DEBUG_WEBSERVER_ID = wx.NewId()
def KillAllRunningProcesses():
execs = DebuggerService.executors
for executor in execs:
executor.DoStopExecution()
KillAllRunningProcesses = staticmethod(KillAllRunningProcesses)
def ComparePaths(first, second): def ComparePaths(first, second):
one = DebuggerService.ExpandPath(first) one = DebuggerService.ExpandPath(first)
@@ -1530,7 +1625,8 @@ class DebuggerService(Service.Service):
try: try:
return win32api.GetLongPathName(path) return win32api.GetLongPathName(path)
except: except:
print "Cannot get long path for %s" % path if _VERBOSE:
print "Cannot get long path for %s" % path
return path return path
@@ -1755,6 +1851,7 @@ class DebuggerService(Service.Service):
def OnExit(self): def OnExit(self):
DebugCommandUI.ShutdownAllDebuggers() DebugCommandUI.ShutdownAllDebuggers()
RunCommandUI.ShutdownAllRunners()
def OnRunProject(self, event): def OnRunProject(self, event):
if _WINDOWS and not _PYWIN32_INSTALLED: if _WINDOWS and not _PYWIN32_INSTALLED:
@@ -2010,9 +2107,6 @@ class CommandPropertiesDialog(wx.Dialog):
self._lastStartIn = str(os.getcwd()) self._lastStartIn = str(os.getcwd())
self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn) self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn)
self._startEntry.SetToolTipString(self._lastStartIn) self._startEntry.SetToolTipString(self._lastStartIn)
def TextChanged2(event):
self._startEntry.SetToolTipString(event.GetString())
self.Bind(wx.EVT_TEXT, TextChanged2, self._startEntry)
flexGridSizer.Add(self._startEntry, 1, wx.EXPAND) flexGridSizer.Add(self._startEntry, 1, wx.EXPAND)
self._findDir = wx.Button(self, -1, _("Browse...")) self._findDir = wx.Button(self, -1, _("Browse..."))
@@ -2240,19 +2334,20 @@ def getBreakIcon():
return wx.IconFromBitmap(getBreakBitmap()) return wx.IconFromBitmap(getBreakBitmap())
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getClearOutputData(): def getClearOutputData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\xb4IDAT8\x8d\xa5\x92\xdd\r\x03!\x0c\x83\xbf\xa0n\xd4\x9d\xda5\xb81\ \x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\
\xbaS\xbb\x12\xee\x03?\xe5\x08\xe5N\xba\xbc Db\xec\xd8p\xb1l\xb8\xa7\x83\xfe\ \xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\
\xb0\x02H\x92F\xc0_\xa3\x99$\x99\x99\xedznc\xe36\x81\x88\x98"\xb2\x02\xa2\ \x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\
\x1e\xc4Q\x9aUD\x161\xcd\xde\x1c\x83\x15\x084)\x8d\xc5)\x06\xab\xaaZ\x92\xee\ \x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\
\xce\x11W\xdbGD\x0cIT\x06\xe7\x00\xdeY\xfe\xcc\x89\x06\xf0\xf2\x99\x00\xe0\ \x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\
\x91\x7f\xab\x83\xed\xa4\xc8\xafK\x0c\xcf\x92\x83\x99\x8d\xe3p\xef\xe4\xa1\ \xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\
\x0b\xe57j\xc8:\x06\t\x08\x87.H\xb2n\xa8\xc9\xa9\x12vQ\xfeG"\xe3\xacw\x00\ \xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\
\x10$M\xd3\x86_\xf0\xe5\xfc\xb4\xfa\x02\xcb\x13j\x10\xc5\xd7\x92D\x00\x00\ \x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\
\x00\x00IEND\xaeB`\x82' \x00IEND\xaeB`\x82'
def getClearOutputBitmap(): def getClearOutputBitmap():
return BitmapFromImage(getClearOutputImage()) return BitmapFromImage(getClearOutputImage())
@@ -2295,13 +2390,15 @@ def getContinueData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00\x9eIDAT8\x8d\xbd\x92\xd1\r\x83@\x0cC\xed\x8a\x11X\xac\x1b\xddF,\xd6\ \x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\
\x11\x90\xdc\x0f\x9a\x93s)\x14Z\xa9\x91\x10\n\x97\xbc\xd89\x80?\x84\x1a\xa4\ \x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\
\x83\xfc\x1c$\x1e)7\xdf<Y0\xaf\x0b\xe6\xf5\x1d\xa1\xb5\x13C\x03 !\xaa\xfd\ !P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\
\xed\n:mr\xc0\x1d\x8f\xc9\x9a!\t$\xe5\xd3I\xe2\xe5B$\x99\x00[\x01\xe8\xc5\ \xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\
\xd9G\xfaN`\xd8\x81I\xed\x8c\xb19\x94\x8d\xcbL\x00;t\xcf\x9fwPh\xdb\x0e\xe8\ \x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\
\xd3,\x17\x8b\xc7\x9d\xbb>\x8a \xec5\x94\tc\xc4\x12\xab\x94\xeb\x7fkWr\xc9B%\ \x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\
\xfc\xd2\xfcM<\x01\xf6tn\x12O3c\xe6\x00\x00\x00\x00IEND\xaeB`\x82' \xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\
\x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\
\x00\x00\x00\x00IEND\xaeB`\x82'
def getContinueBitmap(): def getContinueBitmap():
return BitmapFromImage(getContinueImage()) return BitmapFromImage(getContinueImage())
@@ -2361,12 +2458,12 @@ def getStepInIcon():
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getStopData(): def getStopData():
return \ return \
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
\x00\x00FIDAT8\x8d\xed\x91\xc1\t\xc00\x0c\x03O!\x0b\xa9\xfb\xef\xa6\xfcB\xa1\ \x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\
N\t\xf4Wr\xa0\x8f\xb1\x0f\x81\xe1\x97\xe4-\xb6}_V%\xc8\xc2, \t\x92\xe6]\xfbZ\ \xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\
\xf7\x08\xa0W\xc3\xea5\xdb\rl_IX\xe5\xf0d\x00\xfa\x8d#\x7f\xc4\xf7'\xab\x00\ \x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\
\x00\x00\x00IEND\xaeB`\x82" \x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
def getStopBitmap(): def getStopBitmap():
return BitmapFromImage(getStopImage()) return BitmapFromImage(getStopImage())

View File

@@ -105,14 +105,16 @@ class HtmlService(CodeEditor.CodeService):
class HtmlCtrl(CodeEditor.CodeCtrl): class HtmlCtrl(CodeEditor.CodeCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
CodeEditor.CodeCtrl.__init__(self, parent, ID, style) CodeEditor.CodeCtrl.__init__(self, parent, id, style)
self.SetLexer(wx.stc.STC_LEX_HTML) self.SetLexer(wx.stc.STC_LEX_HTML)
self.SetProperty("fold.html", "1") self.SetProperty("fold.html", "1")
def GetMatchingBraces(self): def GetMatchingBraces(self):
return "<>[]{}()" return "<>[]{}()"
def CanWordWrap(self): def CanWordWrap(self):
return True return True

View File

@@ -79,8 +79,6 @@ class IDEApplication(wx.lib.pydocview.DocApp):
import PHPEditor import PHPEditor
import wx.lib.ogl as ogl import wx.lib.ogl as ogl
import DebuggerService import DebuggerService
import atexit
atexit.register(DebuggerService.DebuggerService.KillAllRunningProcesses)
import AboutDialog import AboutDialog
import SVNService import SVNService
@@ -109,6 +107,19 @@ class IDEApplication(wx.lib.pydocview.DocApp):
docManager = wx.lib.docview.DocManager(flags = self.GetDefaultDocManagerFlags()) docManager = wx.lib.docview.DocManager(flags = self.GetDefaultDocManagerFlags())
self.SetDocumentManager(docManager) self.SetDocumentManager(docManager)
defaultTemplate = wx.lib.docview.DocTemplate(docManager,
_("Any"),
"*.*",
_("Any"),
_(".txt"),
_("Text Document"),
_("Text View"),
STCTextEditor.TextDocument,
STCTextEditor.TextView,
wx.lib.docview.TEMPLATE_INVISIBLE,
icon = STCTextEditor.getTextIcon())
docManager.AssociateTemplate(defaultTemplate)
if not ACTIVEGRID_BASE_IDE: if not ACTIVEGRID_BASE_IDE:
dplTemplate = DeploymentService.DeploymentTemplate(docManager, dplTemplate = DeploymentService.DeploymentTemplate(docManager,
_("Deployment"), _("Deployment"),

View File

@@ -39,15 +39,15 @@ class ImageView(wx.lib.docview.View):
frame = wx.GetApp().CreateDocumentFrame(self, doc, flags) frame = wx.GetApp().CreateDocumentFrame(self, doc, flags)
panel = wx.Panel(frame, -1) panel = wx.Panel(frame, -1)
bitmap = wx.Image(doc.GetFilename()).ConvertToBitmap() self._bitmap = wx.Image(doc.GetFilename()).ConvertToBitmap()
self._ctrl = wx.StaticBitmap(panel, -1, bitmap, (0,0), (bitmap.GetWidth(), bitmap.GetHeight())) self._ctrl = wx.StaticBitmap(panel, -1, self._bitmap, (0,0), (self._bitmap.GetWidth(), self._bitmap.GetHeight()))
wx.EVT_LEFT_DOWN(self._ctrl, self.OnFocus) wx.EVT_LEFT_DOWN(self._ctrl, self.OnFocus)
wx.EVT_LEFT_DCLICK(self._ctrl, self.OnFocus) wx.EVT_LEFT_DCLICK(self._ctrl, self.OnFocus)
wx.EVT_RIGHT_DOWN(self._ctrl, self.OnFocus) wx.EVT_RIGHT_DOWN(self._ctrl, self.OnFocus)
wx.EVT_RIGHT_DCLICK(self._ctrl, self.OnFocus) wx.EVT_RIGHT_DCLICK(self._ctrl, self.OnFocus)
wx.EVT_MIDDLE_DOWN(self._ctrl, self.OnFocus) wx.EVT_MIDDLE_DOWN(self._ctrl, self.OnFocus)
wx.EVT_MIDDLE_DCLICK(self._ctrl, self.OnFocus) wx.EVT_MIDDLE_DCLICK(self._ctrl, self.OnFocus)
panel.SetClientSize(bitmap.GetSize()) panel.SetClientSize(self._bitmap.GetSize())
frame.SetClientSize(panel.GetSize()) frame.SetClientSize(panel.GetSize())
self.Activate() self.Activate()
return True return True
@@ -69,6 +69,13 @@ class ImageView(wx.lib.docview.View):
return True return True
def OnDraw(self, dc):
""" for Print Preview and Print """
dc.BeginDrawing()
dc.DrawBitmap(self._bitmap, 10, 10, True)
dc.EndDrawing()
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Icon Bitmaps - generated by encode_bitmaps.py # Icon Bitmaps - generated by encode_bitmaps.py
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------

View File

@@ -151,8 +151,8 @@ class PHPService(CodeEditor.CodeService):
class PHPCtrl(CodeEditor.CodeCtrl): class PHPCtrl(CodeEditor.CodeCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
CodeEditor.CodeCtrl.__init__(self, parent, ID, style) CodeEditor.CodeCtrl.__init__(self, parent, id, style)
self.SetLexer(wx.stc.STC_LEX_PHP) self.SetLexer(wx.stc.STC_LEX_PHP)
self.SetStyleBits(7) self.SetStyleBits(7)
self.SetKeyWords(4, string.join(PHPKEYWORDS)) self.SetKeyWords(4, string.join(PHPKEYWORDS))

View File

@@ -62,8 +62,8 @@ class PerlService(CodeEditor.CodeService):
class PerlCtrl(CodeEditor.CodeCtrl): class PerlCtrl(CodeEditor.CodeCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
CodeEditor.CodeCtrl.__init__(self, parent, ID, style) CodeEditor.CodeCtrl.__init__(self, parent, id, style)
self.SetLexer(wx.stc.STC_LEX_PERL) self.SetLexer(wx.stc.STC_LEX_PERL)
self.SetKeyWords(0, string.join(PERLKEYWORDS)) self.SetKeyWords(0, string.join(PERLKEYWORDS))

View File

@@ -20,7 +20,7 @@ from wxPython.lib.rcsizer import RowColSizer
import time import time
import Service import Service
import sys import sys
import activegrid.util.xmlmarshaller import activegrid.util.objutils
import UICommon import UICommon
import Wizard import Wizard
import SVNService import SVNService
@@ -47,18 +47,12 @@ HALF_SPACE = 5
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# XML Marshalling Methods # XML Marshalling Methods
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
LOCAL_TYPE_MAPPING = { "projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel", }
def load(fileObject): def load(fileObject):
xml = fileObject.read() return activegrid.util.objutils.defaultLoad(fileObject)
projectModel = activegrid.util.xmlmarshaller.unmarshal(xml, knownTypes=LOCAL_TYPE_MAPPING)
return projectModel
def save(fileObject, projectModel): def save(fileObject, projectModel):
xml = activegrid.util.xmlmarshaller.marshal(projectModel, prettyPrint=True, knownTypes=LOCAL_TYPE_MAPPING) activegrid.util.objutils.defaultSave(fileObject, projectModel, prettyPrint=True)
fileObject.write(xml)
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
@@ -72,6 +66,9 @@ class ProjectModel:
def __init__(self): def __init__(self):
self._files = [] self._files = []
def initialize(self):
pass
class ProjectDocument(wx.lib.docview.Document): class ProjectDocument(wx.lib.docview.Document):
@@ -143,8 +140,6 @@ class ProjectDocument(wx.lib.docview.Document):
if path.startswith("."): # relative to project file if path.startswith("."): # relative to project file
curPath = os.path.dirname(self.GetFilename()) curPath = os.path.dirname(self.GetFilename())
path = os.path.normpath(os.path.join(curPath, path)) path = os.path.normpath(os.path.join(curPath, path))
elif not ACTIVEGRID_BASE_IDE:
print "Warning: absolute path '%s' found in project file, this may affect deployment" % path
newFilePaths.append(path) newFilePaths.append(path)
return newFilePaths return newFilePaths
@@ -229,7 +224,7 @@ class ProjectDocument(wx.lib.docview.Document):
if isProject: if isProject:
documents = self.GetDocumentManager().GetDocuments() documents = self.GetDocumentManager().GetDocuments()
for document in documents: for document in documents:
if document.GetFilename() == oldFile: # If the renamed document is open, update it if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFile): # If the renamed document is open, update it
document.SetFilename(newFile) document.SetFilename(newFile)
document.SetTitle(wx.lib.docview.FileNameFromPath(newFile)) document.SetTitle(wx.lib.docview.FileNameFromPath(newFile))
document.UpdateAllViews(hint = ("rename", document, newFile)) document.UpdateAllViews(hint = ("rename", document, newFile))
@@ -238,7 +233,7 @@ class ProjectDocument(wx.lib.docview.Document):
self.AddFile(newFile) self.AddFile(newFile)
documents = self.GetDocumentManager().GetDocuments() documents = self.GetDocumentManager().GetDocuments()
for document in documents: for document in documents:
if document.GetFilename() == oldFile: # If the renamed document is open, update it if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFile): # If the renamed document is open, update it
document.SetFilename(newFile, notifyViews = True) document.SetFilename(newFile, notifyViews = True)
document.UpdateAllViews(hint = ("rename", document, newFile)) document.UpdateAllViews(hint = ("rename", document, newFile))
return True return True
@@ -293,7 +288,7 @@ class NewProjectWizard(Wizard.BaseWizard):
# What if the document is already open and we're overwriting it? # What if the document is already open and we're overwriting it?
documents = docManager.GetDocuments() documents = docManager.GetDocuments()
for document in documents: for document in documents:
if document.GetFilename() == self._fullProjectPath: # If the renamed document is open, update it if os.path.normcase(document.GetFilename()) == os.path.normcase(self._fullProjectPath): # If the renamed document is open, update it
document.DeleteAllViews() document.DeleteAllViews()
break break
os.remove(self._fullProjectPath) os.remove(self._fullProjectPath)
@@ -848,10 +843,12 @@ class ProjectView(wx.lib.docview.View):
or id == ProjectService.RENAME_ID or id == ProjectService.RENAME_ID
or id == ProjectService.ADD_FILES_TO_PROJECT_ID or id == ProjectService.ADD_FILES_TO_PROJECT_ID
or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID
or id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID or id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID):
or id == ProjectService.DELETE_FILE_ID):
event.Enable(self._HasSelection()) event.Enable(self._HasSelection())
return True return True
elif id == ProjectService.DELETE_FILE_ID:
event.Enable(len(self.GetSelectedFiles()) > 0)
return True
elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
event.Enable(False) event.Enable(False)
return True return True
@@ -866,6 +863,10 @@ class ProjectView(wx.lib.docview.View):
or id == ProjectService.OPEN_SELECTION_ID): or id == ProjectService.OPEN_SELECTION_ID):
event.Enable(self._HasFilesSelected()) event.Enable(self._HasFilesSelected())
return True return True
elif (id == wx.ID_PREVIEW
or id == wx.ID_PRINT):
event.Enable(False)
return True
else: else:
return False return False
@@ -924,6 +925,16 @@ class ProjectView(wx.lib.docview.View):
return filenames return filenames
def GetSelectedProjects(self):
filenames = []
for item in self._treeCtrl.GetSelections():
if self._IsItemProject(item):
filename = self._treeCtrl.GetLongFilename(item)
if filename and filename not in filenames:
filenames.append(filename)
return filenames
def AddProjectToView(self, document): def AddProjectToView(self, document):
rootItem = self._treeCtrl.GetRootItem() rootItem = self._treeCtrl.GetRootItem()
projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document)) projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document))
@@ -981,8 +992,7 @@ class ProjectView(wx.lib.docview.View):
allfilter = allfilter + _(';') allfilter = allfilter + _(';')
descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
allfilter = allfilter + temp.GetFileFilter() allfilter = allfilter + temp.GetFileFilter()
descr = _("All") + _(" (") + allfilter + _(") |") + allfilter + _('|') + descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk descr = _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter, allfilter, descr) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
descr = descr + _("|") + _("Any (*.*) | *.*")
else: else:
descr = _("*.*") descr = _("*.*")
@@ -1203,8 +1213,10 @@ class ProjectView(wx.lib.docview.View):
itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None] itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None]
menuBar = self._GetParentFrame().GetMenuBar() menuBar = self._GetParentFrame().GetMenuBar()
itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT] itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT]
svnIDs = [SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID]
if SVN_INSTALLED: if SVN_INSTALLED:
itemIDs = itemIDs + [None, SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID] itemIDs = itemIDs + [None, SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID]
globalIDs = [wx.ID_UNDO, wx.ID_REDO, wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS]
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] itemIDs = itemIDs + [None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, ProjectService.RENAME_ID, ProjectService.DELETE_FILE_ID, None, wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID]
for itemID in itemIDs: for itemID in itemIDs:
if not itemID: if not itemID:
@@ -1218,8 +1230,16 @@ class ProjectView(wx.lib.docview.View):
wx.EVT_MENU(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self.OnClear) wx.EVT_MENU(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self.OnClear)
wx.EVT_UPDATE_UI(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self._GetParentFrame().ProcessUpdateUIEvent) wx.EVT_UPDATE_UI(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self._GetParentFrame().ProcessUpdateUIEvent)
else: else:
svnService = wx.GetApp().GetService(SVNService.SVNService)
item = menuBar.FindItemById(itemID) item = menuBar.FindItemById(itemID)
if item: if item:
if itemID in svnIDs:
if SVN_INSTALLED and svnService:
wx.EVT_MENU(self._GetParentFrame(), itemID, svnService.ProcessEvent)
elif itemID in globalIDs:
pass
else:
wx.EVT_MENU(self._treeCtrl, itemID, self.ProcessEvent)
menu.Append(itemID, item.GetLabel()) menu.Append(itemID, item.GetLabel())
self._treeCtrl.PopupMenu(menu, wx.Point(event.GetX(), event.GetY())) self._treeCtrl.PopupMenu(menu, wx.Point(event.GetX(), event.GetY()))
menu.Destroy() menu.Destroy()
@@ -1824,9 +1844,43 @@ class ProjectService(Service.Service):
def ProcessEventBeforeWindows(self, event): def ProcessEventBeforeWindows(self, event):
id = event.GetId() id = event.GetId()
if id == wx.ID_CLOSE_ALL: if id == wx.ID_CLOSE_ALL:
self.OnFileCloseAll(event) self.OnFileCloseAll(event)
return True return True
elif id == wx.ID_CLOSE:
document = self.GetDocumentManager().GetCurrentDocument()
if document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
self.OnProjectClose(event)
return True
else:
return False
return False
def ProcessUpdateUIEventBeforeWindows(self, event):
id = event.GetId()
if id == wx.ID_CLOSE_ALL:
for document in self.GetDocumentManager().GetDocuments():
if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:
event.Enable(True)
return True
event.Enable(False)
return True
elif id == wx.ID_CLOSE:
document = self.GetDocumentManager().GetCurrentDocument()
if document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
projectFilenames = self.GetView().GetSelectedProjects()
if projectFilenames and len(projectFilenames):
event.Enable(True)
else:
event.Enable(False)
return True
return False return False
@@ -2055,6 +2109,14 @@ class ProjectService(Service.Service):
self.GetView().Activate(True) # after add, should put focus on project editor self.GetView().Activate(True) # after add, should put focus on project editor
def OnProjectClose(self, event):
projectFilenames = self.GetView().GetSelectedProjects()
for filename in projectFilenames:
doc = self.FindProjectByFile(filename)
if doc:
self.GetDocumentManager().CloseDocument(doc, False)
def OnFileCloseAll(self, event): def OnFileCloseAll(self, event):
for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument: if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:

View File

@@ -49,6 +49,11 @@ class PythonDocument(CodeEditor.CodeDocument):
class PythonView(CodeEditor.CodeView): class PythonView(CodeEditor.CodeView):
def GetCtrlClass(self):
""" Used in split window to instantiate new instances """
return PythonCtrl
def ProcessUpdateUIEvent(self, event): def ProcessUpdateUIEvent(self, event):
if not self.GetCtrl(): if not self.GetCtrl():
return False return False
@@ -62,11 +67,6 @@ class PythonView(CodeEditor.CodeView):
return CodeEditor.CodeView.ProcessUpdateUIEvent(self, event) return CodeEditor.CodeView.ProcessUpdateUIEvent(self, event)
def GetCtrlClass(self):
""" Used in split window to instantiate new instances """
return PythonCtrl
def OnActivateView(self, activate, activeView, deactiveView): def OnActivateView(self, activate, activeView, deactiveView):
STCTextEditor.TextView.OnActivateView(self, activate, activeView, deactiveView) STCTextEditor.TextView.OnActivateView(self, activate, activeView, deactiveView)
if activate: if activate:
@@ -345,8 +345,8 @@ class PythonService(CodeEditor.CodeService):
class PythonCtrl(CodeEditor.CodeCtrl): class PythonCtrl(CodeEditor.CodeCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
CodeEditor.CodeCtrl.__init__(self, parent, ID, style) CodeEditor.CodeCtrl.__init__(self, parent, id, style)
self.SetProperty("tab.timmy.whinge.level", "1") self.SetProperty("tab.timmy.whinge.level", "1")
self.SetProperty("fold.comment.python", "1") self.SetProperty("fold.comment.python", "1")
self.SetProperty("fold.quotes.python", "1") self.SetProperty("fold.quotes.python", "1")
@@ -516,6 +516,7 @@ class PythonCtrl(CodeEditor.CodeCtrl):
if doExtraIndent or len(textNoTrailingSpaces) and textNoTrailingSpaces[-1] == ':': if doExtraIndent or len(textNoTrailingSpaces) and textNoTrailingSpaces[-1] == ':':
spaces = spaces + ' ' * self.GetIndent() spaces = spaces + ' ' * self.GetIndent()
self.AddText('\n' + spaces) self.AddText('\n' + spaces)
self.EnsureCaretVisible()
# Callback for tokenizer in self.DoIndent # Callback for tokenizer in self.DoIndent

View File

@@ -47,27 +47,16 @@ TEXT_STATUS_BAR_ID = wx.NewId()
class TextDocument(wx.lib.docview.Document): class TextDocument(wx.lib.docview.Document):
def OnSaveDocument(self, filename): def SaveObject(self, fileObject):
view = self.GetFirstView() view = self.GetFirstView()
docFile = file(self._documentFile, "w") fileObject.write(view.GetValue())
docFile.write(view.GetValue())
docFile.close()
self.Modify(False)
self.SetDocumentModificationDate()
self.SetDocumentSaved(True)
return True return True
def LoadObject(self, fileObject):
def OnOpenDocument(self, filename):
view = self.GetFirstView() view = self.GetFirstView()
docFile = file(self._documentFile, 'r') data = fileObject.read()
data = docFile.read()
view.SetValue(data) view.SetValue(data)
self.SetFilename(filename, True)
self.Modify(False)
self.SetDocumentModificationDate()
self.UpdateAllViews()
self._savedYet = True
return True return True
@@ -90,12 +79,6 @@ class TextDocument(wx.lib.docview.Document):
# Don't create a command processor, it has its own # Don't create a command processor, it has its own
pass pass
# Use this to override MultiClient.Select to prevent yellow background.
def MultiClientSelectBGNotYellow(a):
a.GetParent().multiView.UnSelect()
a.selected = True
#a.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow
a.Refresh()
class TextView(wx.lib.docview.View): class TextView(wx.lib.docview.View):
MARKER_NUM = 0 MARKER_NUM = 0
@@ -110,39 +93,32 @@ class TextView(wx.lib.docview.View):
self._textEditor = None self._textEditor = None
self._markerCount = 0 self._markerCount = 0
self._commandProcessor = None self._commandProcessor = None
self._multiSash = None self._dynSash = None
def GetCtrlClass(self): def GetCtrlClass(self):
""" Used in split window to instantiate new instances """
return TextCtrl return TextCtrl
def GetCtrl(self):
# look for active one first
self._textEditor = self._GetActiveCtrl(self._multiSash)
if self._textEditor == None: # it is possible none are active
# look for any existing one
self._textEditor = self._FindCtrl(self._multiSash)
return self._textEditor
## def GetCtrls(self, parent = None): def GetCtrl(self):
## """ Walk through the MultiSash windows and find all Ctrls """ return self._textEditor
## controls = []
## if isinstance(parent, self.GetCtrlClass()):
## return [parent] def SetCtrl(self, ctrl):
## if hasattr(parent, "GetChildren"): self._textEditor = ctrl
## for child in parent.GetChildren():
## controls = controls + self.GetCtrls(child)
## return controls def OnCreatePrintout(self):
""" for Print Preview and Print """
return TextPrintout(self, self.GetDocument().GetPrintableName())
def OnCreate(self, doc, flags): def OnCreate(self, doc, flags):
frame = wx.GetApp().CreateDocumentFrame(self, doc, flags, style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE) frame = wx.GetApp().CreateDocumentFrame(self, doc, flags, style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
wx.lib.multisash.MultiClient.Select = MultiClientSelectBGNotYellow self._dynSash = wx.gizmos.DynamicSashWindow(frame, -1, style=wx.CLIP_CHILDREN)
self._multiSash = wx.lib.multisash.MultiSash(frame, -1) self._dynSash._view = self
self._multiSash.SetDefaultChildClass(self.GetCtrlClass()) # wxBug: MultiSash instantiates the first TextCtrl with this call self._textEditor = self.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER)
self._textEditor = self.GetCtrl() # wxBug: grab the TextCtrl from the MultiSash datastructure
self._CreateSizer(frame) self._CreateSizer(frame)
self.Activate() self.Activate()
frame.Show(True) frame.Show(True)
@@ -150,33 +126,9 @@ class TextView(wx.lib.docview.View):
return True return True
def _GetActiveCtrl(self, parent):
""" Walk through the MultiSash windows and find the active Control """
if isinstance(parent, wx.lib.multisash.MultiClient) and parent.selected:
return parent.child
if hasattr(parent, "GetChildren"):
for child in parent.GetChildren():
found = self._GetActiveCtrl(child)
if found:
return found
return None
def _FindCtrl(self, parent):
""" Walk through the MultiSash windows and find the first TextCtrl """
if isinstance(parent, self.GetCtrlClass()):
return parent
if hasattr(parent, "GetChildren"):
for child in parent.GetChildren():
found = self._FindCtrl(child)
if found:
return found
return None
def _CreateSizer(self, frame): def _CreateSizer(self, frame):
sizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self._multiSash, 1, wx.EXPAND) sizer.Add(self._dynSash, 1, wx.EXPAND)
frame.SetSizer(sizer) frame.SetSizer(sizer)
frame.SetAutoLayout(True) frame.SetAutoLayout(True)
@@ -300,12 +252,12 @@ class TextView(wx.lib.docview.View):
id = event.GetId() id = event.GetId()
if id == wx.ID_UNDO: if id == wx.ID_UNDO:
event.Enable(self.GetCtrl().CanUndo()) event.Enable(self.GetCtrl().CanUndo())
event.SetText(_("Undo") + '\t' + _('Ctrl+Z')) event.SetText(_("&Undo\tCtrl+Z")) # replace menu string
return True return True
elif id == wx.ID_REDO: elif id == wx.ID_REDO:
event.Enable(self.GetCtrl().CanRedo()) event.Enable(self.GetCtrl().CanRedo())
event.SetText(_("Redo") + '\t' + _('Ctrl+Y')) event.SetText(_("&Redo\tCtrl+Y")) # replace menu string
return True return True
elif (id == wx.ID_CUT elif (id == wx.ID_CUT
or id == wx.ID_COPY or id == wx.ID_COPY
@@ -586,6 +538,7 @@ class TextView(wx.lib.docview.View):
def GetLine(self, lineNum): def GetLine(self, lineNum):
return self.GetCtrl().GetLine(lineNum-1) # line numbering for editor is 0 based, we are 1 based. return self.GetCtrl().GetLine(lineNum-1) # line numbering for editor is 0 based, we are 1 based.
def MarkerDefine(self): def MarkerDefine(self):
""" This must be called after the texteditor is instantiated """ """ This must be called after the texteditor is instantiated """
self.GetCtrl().MarkerDefine(TextView.MARKER_NUM, wx.stc.STC_MARK_CIRCLE, wx.BLACK, wx.BLUE) self.GetCtrl().MarkerDefine(TextView.MARKER_NUM, wx.stc.STC_MARK_CIRCLE, wx.BLACK, wx.BLUE)
@@ -601,6 +554,7 @@ class TextView(wx.lib.docview.View):
self.GetCtrl().MarkerAdd(lineNum, marker_index) self.GetCtrl().MarkerAdd(lineNum, marker_index)
self._markerCount += 1 self._markerCount += 1
def MarkerAdd(self, lineNum = -1, marker_index=MARKER_NUM, mask=MARKER_MASK): def MarkerAdd(self, lineNum = -1, marker_index=MARKER_NUM, mask=MARKER_MASK):
if lineNum == -1: if lineNum == -1:
lineNum = self.GetCtrl().GetCurrentLine() lineNum = self.GetCtrl().GetCurrentLine()
@@ -959,10 +913,14 @@ class TextOptionsPanel(wx.Panel):
class TextCtrl(wx.stc.StyledTextCtrl): class TextCtrl(wx.stc.StyledTextCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
if ID == -1: wx.stc.StyledTextCtrl.__init__(self, parent, id, style=style)
ID = wx.NewId()
wx.stc.StyledTextCtrl.__init__(self, parent, ID, style = style) if isinstance(parent, wx.gizmos.DynamicSashWindow):
self._dynSash = parent
self.SetupDSScrollBars()
self.Bind(wx.gizmos.EVT_DYNAMIC_SASH_SPLIT, self.OnDSSplit)
self.Bind(wx.gizmos.EVT_DYNAMIC_SASH_UNIFY, self.OnDSUnify)
self._font = None self._font = None
self._fontColor = None self._fontColor = None
@@ -975,6 +933,8 @@ class TextCtrl(wx.stc.StyledTextCtrl):
self.CmdKeyAssign(wx.stc.STC_KEY_NEXT, wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT) self.CmdKeyAssign(wx.stc.STC_KEY_NEXT, wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT)
self.Bind(wx.stc.EVT_STC_ZOOM, self.OnUpdateLineNumberMarginWidth) # auto update line num width on zoom self.Bind(wx.stc.EVT_STC_ZOOM, self.OnUpdateLineNumberMarginWidth) # auto update line num width on zoom
wx.EVT_KEY_DOWN(self, self.OnKeyPressed) wx.EVT_KEY_DOWN(self, self.OnKeyPressed)
wx.EVT_KILL_FOCUS(self, self.OnKillFocus)
wx.EVT_SET_FOCUS(self, self.OnFocus)
self.SetMargins(0,0) self.SetMargins(0,0)
self.SetUseTabs(0) self.SetUseTabs(0)
@@ -998,21 +958,23 @@ class TextCtrl(wx.stc.StyledTextCtrl):
self.SetFontColor(color) self.SetFontColor(color)
self.MarkerDefineDefault() self.MarkerDefineDefault()
# for multisash initialization
if isinstance(parent, wx.lib.multisash.MultiClient): def OnFocus(self, event):
while parent.GetParent(): self.SetSelBackground(1, "BLUE")
parent = parent.GetParent() self.SetSelForeground(1, "WHITE")
if hasattr(parent, "GetView"): if hasattr(self, "_dynSash"):
break self._dynSash._view.SetCtrl(self)
if hasattr(parent, "GetView"): event.Skip()
textEditor = parent.GetView()._textEditor
if textEditor:
doc = textEditor.GetDocPointer()
if doc:
self.SetDocPointer(doc)
def OnKillFocus(self, event):
self.SetSelBackground(0, "BLUE")
self.SetSelForeground(0, "WHITE")
self.SetSelBackground(1, "#C0C0C0")
# Don't set foreground color, use syntax highlighted default colors.
event.Skip()
def SetViewDefaults(self, configPrefix = "Text", hasWordWrap = True, hasTabs = False): def SetViewDefaults(self, configPrefix = "Text", hasWordWrap = True, hasTabs = False):
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
self.SetViewWhiteSpace(config.ReadInt(configPrefix + "EditorViewWhitespace", False)) self.SetViewWhiteSpace(config.ReadInt(configPrefix + "EditorViewWhitespace", False))
@@ -1031,7 +993,6 @@ class TextCtrl(wx.stc.StyledTextCtrl):
self.SetIndent(4) self.SetIndent(4)
self.SetTabWidth(4) self.SetTabWidth(4)
def GetDefaultFont(self): def GetDefaultFont(self):
""" Subclasses should override this """ """ Subclasses should override this """
@@ -1064,6 +1025,7 @@ class TextCtrl(wx.stc.StyledTextCtrl):
def GetFont(self): def GetFont(self):
return self._font return self._font
def SetFont(self, font): def SetFont(self, font):
self._font = font self._font = font
self.StyleSetFont(wx.stc.STC_STYLE_DEFAULT, self._font) self.StyleSetFont(wx.stc.STC_STYLE_DEFAULT, self._font)
@@ -1202,6 +1164,160 @@ class TextCtrl(wx.stc.StyledTextCtrl):
else: else:
self.SetWrapMode(wx.stc.STC_WRAP_NONE) self.SetWrapMode(wx.stc.STC_WRAP_NONE)
#----------------------------------------------------------------------------
# DynamicSashWindow methods
#----------------------------------------------------------------------------
def SetupDSScrollBars(self):
# hook the scrollbars provided by the wxDynamicSashWindow
# to this view
v_bar = self._dynSash.GetVScrollBar(self)
h_bar = self._dynSash.GetHScrollBar(self)
v_bar.Bind(wx.EVT_SCROLL, self.OnDSSBScroll)
h_bar.Bind(wx.EVT_SCROLL, self.OnDSSBScroll)
v_bar.Bind(wx.EVT_SET_FOCUS, self.OnDSSBFocus)
h_bar.Bind(wx.EVT_SET_FOCUS, self.OnDSSBFocus)
# And set the wxStyledText to use these scrollbars instead
# of its built-in ones.
self.SetVScrollBar(v_bar)
self.SetHScrollBar(h_bar)
def OnDSSplit(self, evt):
newCtrl = self._dynSash._view.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER)
newCtrl.SetDocPointer(self.GetDocPointer()) # use the same document
self.SetupDSScrollBars()
if self == self._dynSash._view.GetCtrl(): # originally had focus
wx.CallAfter(self.SetFocus) # do this to set colors correctly. wxBug: for some reason, if we don't do a CallAfter, it immediately calls OnKillFocus right after our SetFocus.
def OnDSUnify(self, evt):
self.SetupDSScrollBars()
self.SetFocus() # do this to set colors correctly
def OnDSSBScroll(self, evt):
# redirect the scroll events from the _dynSash's scrollbars to the STC
self.GetEventHandler().ProcessEvent(evt)
def OnDSSBFocus(self, evt):
# when the scrollbar gets the focus move it back to the STC
self.SetFocus()
def DSProcessEvent(self, event):
# wxHack: Needed for customized right mouse click menu items.
if hasattr(self, "_dynSash"):
if event.GetId() == wx.ID_SELECTALL:
# force focus so that select all occurs in the window user right clicked on.
self.SetFocus()
return self._dynSash._view.ProcessEvent(event)
return False
def DSProcessUpdateUIEvent(self, event):
# wxHack: Needed for customized right mouse click menu items.
if hasattr(self, "_dynSash"):
id = event.GetId()
if (id == wx.ID_SELECTALL # allow select all even in non-active window, then force focus to it, see above ProcessEvent
or id == wx.ID_UNDO
or id == wx.ID_REDO):
pass # allow these actions even in non-active window
else: # disallow events in non-active windows. Cut/Copy/Paste/Delete is too confusing user experience.
if self._dynSash._view.GetCtrl() != self:
event.Enable(False)
return True
return self._dynSash._view.ProcessUpdateUIEvent(event)
return False
class TextPrintout(wx.lib.docview.DocPrintout):
""" for Print Preview and Print """
def OnPreparePrinting(self):
""" initialization """
dc = self.GetDC()
ppiScreenX, ppiScreenY = self.GetPPIScreen()
ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
scaleX = float(ppiPrinterX)/ppiScreenX
scaleY = float(ppiPrinterY)/ppiScreenY
pageWidth, pageHeight = self.GetPageSizePixels()
self._scaleFactorX = scaleX/pageWidth
self._scaleFactorY = scaleY/pageHeight
w, h = dc.GetSize()
overallScaleX = self._scaleFactorX * w
overallScaleY = self._scaleFactorY * h
txtCtrl = self._printoutView.GetCtrl()
font, color = txtCtrl.GetFontAndColorFromConfig()
self._margin = 40
self._fontHeight = font.GetPointSize() + 1
self._pageLines = int((h/overallScaleY - (2 * self._margin))/self._fontHeight)
self._maxLines = txtCtrl.GetLineCount()
self._numPages, remainder = divmod(self._maxLines, self._pageLines)
if remainder != 0:
self._numPages += 1
spaces = 1
lineNum = self._maxLines
while lineNum >= 10:
lineNum = lineNum/10
spaces += 1
self._printFormat = "%%0%sd: %%s" % spaces
def OnPrintPage(self, page):
""" Prints the given page of the view """
dc = self.GetDC()
txtCtrl = self._printoutView.GetCtrl()
font, color = txtCtrl.GetFontAndColorFromConfig()
dc.SetFont(font)
w, h = dc.GetSize()
dc.SetUserScale(self._scaleFactorX * w, self._scaleFactorY * h)
dc.BeginDrawing()
dc.DrawText("%s - page %s" % (self.GetTitle(), page), self._margin, self._margin/2)
startY = self._margin
startLine = (page - 1) * self._pageLines
endLine = min((startLine + self._pageLines), self._maxLines)
for i in range(startLine, endLine):
text = txtCtrl.GetLine(i).rstrip()
startY += self._fontHeight
if txtCtrl.GetViewLineNumbers():
dc.DrawText(self._printFormat % (i+1, text), self._margin, startY)
else:
dc.DrawText(text, self._margin, startY)
dc.EndDrawing()
return True
def HasPage(self, pageNum):
return pageNum <= self._numPages
def GetPageInfo(self):
minPage = 1
maxPage = self._numPages
selPageFrom = 1
selPageTo = self._numPages
return (minPage, maxPage, selPageFrom, selPageTo)
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Icon Bitmaps - generated by encode_bitmaps.py # Icon Bitmaps - generated by encode_bitmaps.py

View File

@@ -11,6 +11,7 @@
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
import wx import wx
import os
import os.path import os.path
import ProjectEditor import ProjectEditor
import MessageService import MessageService
@@ -31,7 +32,7 @@ _ = wx.GetTranslation
# Constants # Constants
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
SVN_CONFIG_DIR = "SVNConfigDir" SVN_CONFIG_DIR = "SVNConfigDir"
SVN_REPOSITORY_URL = "SVNRepositoryURL" SVN_REPOSITORY_URL = "SVNRepositoryURLs"
SPACE = 10 SPACE = 10
HALF_SPACE = 5 HALF_SPACE = 5
@@ -42,13 +43,15 @@ HALF_SPACE = 5
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
class SVNService(wx.lib.pydocview.DocService): class SVNService(wx.lib.pydocview.DocService):
SVN_UPDATE_ALL_ID = wx.NewId()
SVN_UPDATE_ID = wx.NewId() SVN_UPDATE_ID = wx.NewId()
SVN_CHECKIN_ID = wx.NewId() SVN_CHECKIN_ID = wx.NewId()
SVN_CHECKIN_ALL_ID = wx.NewId()
SVN_CHECKOUT_ID = wx.NewId() SVN_CHECKOUT_ID = wx.NewId()
SVN_REVERT_ID = wx.NewId() SVN_REVERT_ID = wx.NewId()
SVN_ADD_ID = wx.NewId() SVN_ADD_ID = wx.NewId()
SVN_DELETE_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] SVN_COMMAND_LIST = [SVN_UPDATE_ALL_ID, SVN_CHECKIN_ALL_ID, SVN_UPDATE_ID, SVN_CHECKIN_ID, SVN_CHECKOUT_ID, SVN_REVERT_ID, SVN_ADD_ID, SVN_DELETE_ID]
def __init__(self): def __init__(self):
@@ -57,13 +60,14 @@ class SVNService(wx.lib.pydocview.DocService):
global SVN_INSTALLED global SVN_INSTALLED
if SVN_INSTALLED: if SVN_INSTALLED:
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
configDir = config.Read(SVN_CONFIG_DIR, "") configDir = config.Read(SVN_CONFIG_DIR, "")
self._client = pysvn.Client(configDir) self._client = pysvn.Client(configDir)
try: try:
self._defaultURL = self._client.info('.').url self._defaultURL = self._client.info('.').url
except: except:
pass pass
self._client.callback_cancel = self.IfCancel self._client.callback_cancel = self.IfCancel
self._client.callback_notify = self.UpdateStatus self._client.callback_notify = self.UpdateStatus
self._client.callback_get_log_message = self.GetLogMessage self._client.callback_get_log_message = self.GetLogMessage
@@ -274,6 +278,12 @@ class SVNService(wx.lib.pydocview.DocService):
menu.AppendSeparator() menu.AppendSeparator()
wx.EVT_MENU(frame, SVNService.SVN_UPDATE_ALL_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_UPDATE_ALL_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_UPDATE_ALL_ID, _("SVN Update All in Project"), _("Update all files in a project from Subversion"))
wx.EVT_MENU(frame, SVNService.SVN_CHECKIN_ALL_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_CHECKIN_ALL_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_CHECKIN_ALL_ID, _("SVN Commit All in Project..."), _("Commit all files changes in a project to Subversion"))
wx.EVT_MENU(frame, SVNService.SVN_UPDATE_ID, self.ProcessEvent) wx.EVT_MENU(frame, SVNService.SVN_UPDATE_ID, self.ProcessEvent)
wx.EVT_UPDATE_UI(frame, SVNService.SVN_UPDATE_ID, self.ProcessUpdateUIEvent) wx.EVT_UPDATE_UI(frame, SVNService.SVN_UPDATE_ID, self.ProcessUpdateUIEvent)
menu.Append(SVNService.SVN_UPDATE_ID, _("SVN Update"), _("Update file from Subversion")) menu.Append(SVNService.SVN_UPDATE_ID, _("SVN Update"), _("Update file from Subversion"))
@@ -309,9 +319,10 @@ class SVNService(wx.lib.pydocview.DocService):
if id == SVNService.SVN_UPDATE_ID: if id == SVNService.SVN_UPDATE_ID:
filenames = self.GetCurrentDocuments()
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
filenames = self.GetCurrentDocuments()[:]
filenames.sort(self.BasenameCaseInsensitiveCompare)
messageService = wx.GetApp().GetService(MessageService.MessageService) messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow() messageService.ShowWindow()
@@ -355,9 +366,174 @@ class SVNService(wx.lib.pydocview.DocService):
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
return True return True
elif id == SVNService.SVN_UPDATE_ALL_ID:
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"))
projects = self.GetCurrentProjects()
for project in projects:
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for doc in openDocs:
if doc.GetFilename() == project:
filenames = doc.GetFiles()[:] # make a copy and sort it.
filenames.sort(self.BasenameCaseInsensitiveCompare)
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.CANCEL|wx.ICON_QUESTION)
status = yesNoMsg.ShowModal()
if status == wx.ID_YES:
doc.DeleteAllViews()
elif status == wx.ID_NO:
pass
else: # elif status == wx.CANCEL:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
return True
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_ALL_ID:
filenames = []
projects = self.GetCurrentProjects()
for project in projects:
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for doc in openDocs:
if doc.GetFilename() == project:
for filename in doc.GetFiles():
if filename not in filenames:
filenames.append(filename)
filenames.sort(self.BasenameCaseInsensitiveCompare)
# 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_CHECKIN_ID: elif id == SVNService.SVN_CHECKIN_ID:
filenames = self.GetCurrentDocuments() filenames = self.GetCurrentDocuments()[:]
filenames.sort(self.BasenameCaseInsensitiveCompare)
# ask user if dirty files should be saved first # ask user if dirty files should be saved first
openDocs = wx.GetApp().GetDocumentManager().GetDocuments() openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
@@ -459,9 +635,14 @@ class SVNService(wx.lib.pydocview.DocService):
gridSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) 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) 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)) svnUrlList = ReadSvnUrlList()
svnURLText.SetToolTipString(svnUrl) svnURLCombobox = wx.ComboBox(dlg, -1, size=(200, -1), choices=svnUrlList, style=wx.CB_DROPDOWN)
gridSizer.Add(svnURLText, 0) if len(svnUrlList):
svnURLCombobox.SetToolTipString(svnUrlList[0])
svnURLCombobox.SetStringSelection(svnUrlList[0])
else:
svnURLCombobox.SetToolTipString(_("Set Repository URL"))
gridSizer.Add(svnURLCombobox, 0)
gridSizer.Add(wx.StaticText(dlg, -1, _("Checkout to dir:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, HALF_SPACE) 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 = wx.TextCtrl(dlg, -1, size = (200, -1))
@@ -502,6 +683,8 @@ class SVNService(wx.lib.pydocview.DocService):
if dlg.ShowModal() == wx.ID_OK: if dlg.ShowModal() == wx.ID_OK:
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
WriteSvnUrlList(svnURLCombobox)
messageService = wx.GetApp().GetService(MessageService.MessageService) messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow() messageService.ShowWindow()
@@ -510,7 +693,7 @@ class SVNService(wx.lib.pydocview.DocService):
view.ClearLines() view.ClearLines()
view.AddLines(_("SVN Checkout:\n")) view.AddLines(_("SVN Checkout:\n"))
svnUrl = svnURLText.GetValue() svnUrl = svnURLCombobox.GetValue()
toLocation = localPath.GetValue() toLocation = localPath.GetValue()
try: try:
self._client.checkout(svnUrl, toLocation) self._client.checkout(svnUrl, toLocation)
@@ -651,9 +834,31 @@ class SVNService(wx.lib.pydocview.DocService):
event.Enable(True) event.Enable(True)
return True return True
elif (id == SVNService.SVN_UPDATE_ALL_ID
or id == SVNService.SVN_CHECKIN_ALL_ID):
if self.GetCurrentProjects():
event.Enable(True)
else:
event.Enable(False)
return True
return False return False
def GetCurrentProjects(self):
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
if projectService:
projView = projectService.GetView()
if projView.HasFocus():
filenames = projView.GetSelectedProjects()
if len(filenames):
return filenames
else:
return None
return None
def GetCurrentDocuments(self): def GetCurrentDocuments(self):
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
@@ -676,6 +881,17 @@ class SVNService(wx.lib.pydocview.DocService):
return filenames return filenames
def BasenameCaseInsensitiveCompare(self, s1, s2):
s1L = os.path.basename(s1).lower()
s2L = os.path.basename(s2).lower()
if s1L == s2L:
return 0
elif s1L < s2L:
return -1
else:
return 1
class SVNOptionsPanel(wx.Panel): class SVNOptionsPanel(wx.Panel):
@@ -683,8 +899,6 @@ class SVNOptionsPanel(wx.Panel):
wx.Panel.__init__(self, parent, id) wx.Panel.__init__(self, parent, id)
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
svnService = wx.GetApp().GetService(SVNService)
svnUrl = config.Read(SVN_REPOSITORY_URL, svnService._defaultURL)
configDir = config.Read(SVN_CONFIG_DIR, "") configDir = config.Read(SVN_CONFIG_DIR, "")
borderSizer = wx.BoxSizer(wx.VERTICAL) borderSizer = wx.BoxSizer(wx.VERTICAL)
@@ -718,10 +932,42 @@ class SVNOptionsPanel(wx.Panel):
hsizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) hsizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE)
sizer.Add(hsizer, 0) sizer.Add(hsizer, 0)
svnUrlList = ReadSvnUrlList()
sizer.Add(wx.StaticText(self, -1, _("SVN URL:")), 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(wx.StaticText(self, -1, _("SVN URL:")), 0, wx.ALIGN_CENTER_VERTICAL)
self._svnURLText = wx.TextCtrl(self, -1, svnUrl, size = (200, -1)) self._svnURLCombobox = wx.ComboBox(self, -1, size=(200, -1), choices=svnUrlList, style=wx.CB_DROPDOWN)
self._svnURLText.SetToolTipString(svnUrl) if len(svnUrlList):
sizer.Add(self._svnURLText, 0) self._svnURLCombobox.SetToolTipString(svnUrlList[0])
self._svnURLCombobox.SetStringSelection(svnUrlList[0])
else:
self._svnURLCombobox.SetToolTipString(_("Set Repository URL"))
sizer.Add(self._svnURLCombobox, 0)
sizer.Add(wx.StaticText(self, -1, _("SVN_SSH:")), 0, wx.ALIGN_CENTER_VERTICAL)
svnSSH = os.getenv("SVN_SSH")
if not svnSSH or svnSSH == "":
self._svnSSH = wx.TextCtrl(self, -1, size = (200, -1))
else:
self._svnSSH = wx.TextCtrl(self, -1, svnSSH, size = (200, -1))
self._svnSSH.SetToolTipString(_("Override SVN_SSH environment variable temporarily."))
findSSHButton = wx.Button(self, -1, _("Browse..."))
def OnBrowseFileButton(event):
dirDlg = wx.FileDialog(self, _("Choose a file:"), style=wx.OPEN|wx.CHANGE_DIR)
if dirDlg.ShowModal() == wx.ID_OK:
self._svnSSH.SetValue(dirDlg.GetPath())
self._svnSSH.SetToolTipString(self._svnSSH.GetValue())
self._svnSSH.SetInsertionPointEnd()
dirDlg.Destroy()
wx.EVT_BUTTON(findSSHButton, -1, OnBrowseFileButton)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer.Add(self._svnSSH, 1, wx.EXPAND)
hsizer.Add(findSSHButton, 0, wx.LEFT, HALF_SPACE)
sizer.Add(hsizer, 0)
borderSizer.Add(sizer, 0, wx.ALL, SPACE) borderSizer.Add(sizer, 0, wx.ALL, SPACE)
self.SetSizer(borderSizer) self.SetSizer(borderSizer)
@@ -731,6 +977,43 @@ class SVNOptionsPanel(wx.Panel):
def OnOK(self, optionsDialog): def OnOK(self, optionsDialog):
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
config.Write(SVN_CONFIG_DIR, self._svnConfigDir.GetValue()) config.Write(SVN_CONFIG_DIR, self._svnConfigDir.GetValue())
config.Write(SVN_REPOSITORY_URL, self._svnURLText.GetValue())
WriteSvnUrlList(self._svnURLCombobox)
os.environ["SVN_SSH"] = self._svnSSH.GetValue()
def ReadSvnUrlList():
""" Read in list of SNV repository URLs. First in list is the last one path used. """
config = wx.ConfigBase_Get()
urlStringList = config.Read(SVN_REPOSITORY_URL)
if len(urlStringList):
urlList = eval(urlStringList)
else:
urlList = []
if len(urlList) == 0:
svnService = wx.GetApp().GetService(SVNService)
if svnService and hasattr(svnService, "_defaultURL"):
urlList.append(svnService._defaultURL)
return urlList
def WriteSvnUrlList(comboBox):
""" Save out list of SVN repository URLs from combobox. Put on top the current selection. Only save out first 10 from the list """
urlList = []
url = comboBox.GetValue()
if len(url):
urlList.append(url)
for i in range(min(comboBox.GetCount(), 10)):
url = comboBox.GetString(i)
if url not in urlList:
urlList.append(url)
config = wx.ConfigBase_Get()
config.Write(SVN_REPOSITORY_URL, urlList.__repr__())

View File

@@ -56,6 +56,10 @@ def CreateDirectoryControl( parent, fileLabel, dirLabel, fileExtension, starting
if nameControl.GetValue().find(' ') != -1: if nameControl.GetValue().find(' ') != -1:
wx.MessageBox(_("Please provide a filename that does not contains spaces."), _("Spaces in Filename")) wx.MessageBox(_("Please provide a filename that does not contains spaces."), _("Spaces in Filename"))
return False return False
if not os.path.exists(dirControl.GetValue()):
wx.MessageBox(_("That directory does not exist. Please choose an existing directory."), _("Provide a Valid Directory"))
return False
filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(nameControl.GetValue(), "." + fileExtension)) filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(nameControl.GetValue(), "." + fileExtension))
if os.path.exists(filePath): if os.path.exists(filePath):
if allowOverwriteOnPrompt: if allowOverwriteOnPrompt:

View File

@@ -63,8 +63,8 @@ class XmlService(CodeEditor.CodeService):
class XmlCtrl(CodeEditor.CodeCtrl): class XmlCtrl(CodeEditor.CodeCtrl):
def __init__(self, parent, ID = -1, style = wx.NO_FULL_REPAINT_ON_RESIZE): def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
CodeEditor.CodeCtrl.__init__(self, parent, ID, style) CodeEditor.CodeCtrl.__init__(self, parent, id, style)
self.SetLexer(wx.stc.STC_LEX_XML) self.SetLexer(wx.stc.STC_LEX_XML)
self.SetProperty("fold.html", "1") self.SetProperty("fold.html", "1")

View File

@@ -1924,7 +1924,7 @@ class IOBuffer:
self.__buf = '' self.__buf = ''
# A state change is defined as the buffer being closed or a # A state change is defined as the buffer being closed or a
# write occurring. # write occuring.
if mutex is not None: if mutex is not None:
self._mutex = mutex self._mutex = mutex
else: else:

View File

@@ -21,8 +21,9 @@ def _registerMainModuleDir():
if not os.path.isabs(utilModuleDir): if not os.path.isabs(utilModuleDir):
utilModuleDir = os.path.join(os.getcwd(), 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))) mainModuleDir = os.path.normpath(os.path.join(utilModuleDir, os.path.join(os.path.pardir, os.path.pardir)))
if mainModuleDir.endswith('.zip'):
mainModuleDir = os.path.dirname(mainModuleDir) # Get rid of library.zip
else: else:
mainModuleDir = os.path.dirname(sys.executable) mainModuleDir = os.path.dirname(sys.executable)
_registerMainModuleDir() _registerMainModuleDir()

View File

@@ -14,23 +14,89 @@ import logging
import traceback import traceback
import sys import sys
import os import os
import xmlmarshaller import xmlmarshaller
AG_TYPE_MAPPING = { "ag:append" : "activegrid.model.processmodel.AppendOperation",
"ag:body" : "activegrid.model.processmodel.Body",
"ag:copy" : "activegrid.model.processmodel.CopyOperation",
"ag:cssRule" : "activegrid.model.processmodel.CssRule",
"ag:datasource" : "activegrid.data.dataservice.DataSource",
"ag:debug" : "activegrid.model.processmodel.DebugOperation",
"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:schemaOptions" : "activegrid.model.schema.SchemaOptions",
"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:catch" : "activegrid.model.processmodel.BPELCatch",
"bpws:faultHandlers" : "activegrid.model.processmodel.BPELFaultHandlers",
"bpws:invoke" : "activegrid.model.processmodel.BPELInvoke",
"bpws:onMessage" : "activegrid.model.processmodel.BPELOnMessage",
"bpws:otherwise" : "activegrid.model.processmodel.BPELOtherwise",
"bpws:pick" : "activegrid.model.processmodel.BPELPick",
"bpws:process" : "activegrid.model.processmodel.BPELProcess",
"bpws:receive" : "activegrid.model.processmodel.BPELReceive",
"bpws:reply" : "activegrid.model.processmodel.BPELReply",
"bpws:scope" : "activegrid.model.processmodel.BPELScope",
"bpws:sequence" : "activegrid.model.processmodel.BPELSequence",
"bpws:switch" : "activegrid.model.processmodel.BPELSwitch",
"bpws:terminate" : "activegrid.model.processmodel.BPELTerminate",
"bpws:variable" : "activegrid.model.processmodel.BPELVariable",
"bpws:variables" : "activegrid.model.processmodel.BPELVariables",
"bpws:while" : "activegrid.model.processmodel.BPELWhile",
"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",
"xs:all" : "activegrid.model.schema.XsdSequence",
"xs:complexType" : "activegrid.model.schema.XsdComplexType",
"xs:element" : "activegrid.model.schema.XsdElement",
"xs:field" : "activegrid.model.schema.XsdKeyField",
"xs:key" : "activegrid.model.schema.XsdKey",
"xs:keyref" : "activegrid.model.schema.XsdKeyRef",
"xs:schema" : "activegrid.model.schema.Schema",
"xs:selector" : "activegrid.model.schema.XsdKeySelector",
"xs:sequence" : "activegrid.model.schema.XsdSequence",
"projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel",
}
def defaultLoad(fileObject, knownTypes=None): def defaultLoad(fileObject, knownTypes=None):
xml = fileObject.read() xml = fileObject.read()
loadedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes) loadedObject = defaultUnmarshal(xml, knownTypes=knownTypes)
if hasattr(fileObject, 'name'): if hasattr(fileObject, 'name'):
loadedObject.fileName = os.path.abspath(fileObject.name) loadedObject.fileName = os.path.abspath(fileObject.name)
loadedObject.initialize() loadedObject.initialize()
return loadedObject return loadedObject
def defaultSave(fileObject, objectToSave, knownTypes=None, withEncoding=1, encoding='utf-8'): def defaultUnmarshal(xml, knownTypes=None):
xml = xmlmarshaller.marshal(objectToSave, prettyPrint=True, knownTypes=knownTypes, withEncoding=withEncoding, encoding=encoding) if not knownTypes: knownTypes = AG_TYPE_MAPPING
return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
def defaultSave(fileObject, objectToSave, prettyPrint=True, knownTypes=None, withEncoding=1, encoding='utf-8'):
xml = defaultMarshal(objectToSave, prettyPrint=prettyPrint, knownTypes=knownTypes, withEncoding=withEncoding, encoding=encoding)
fileObject.write(xml) fileObject.write(xml)
fileObject.flush() fileObject.flush()
def defaultMarshal(objectToSave, prettyPrint=True, knownTypes=None, withEncoding=1, encoding='utf-8'):
if not knownTypes: knownTypes = AG_TYPE_MAPPING
return xmlmarshaller.marshal(objectToSave, prettyPrint=prettyPrint, knownTypes=knownTypes, withEncoding=withEncoding, encoding=encoding)
def clone(objectToClone, knownTypes=None, encoding='utf-8'): def clone(objectToClone, knownTypes=None, encoding='utf-8'):
if not knownTypes: knownTypes = AG_TYPE_MAPPING
xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, knownTypes=knownTypes, encoding=encoding) xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, knownTypes=knownTypes, encoding=encoding)
clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes) clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
if hasattr(objectToClone, 'fileName'): if hasattr(objectToClone, 'fileName'):
@@ -91,3 +157,116 @@ def hasPropertyValue(obj, attr):
except KeyError: except KeyError:
pass pass
return hasProp return hasProp
def toDiffableString(value):
s = repr(value)
ds = ""
i = s.find(" at 0x")
start = 0
while (i >= 0):
j = s.find(">", i)
if (j < i):
break
ds += s[start:i]
start = j
i = s.find(" at 0x", start)
return ds + s[start:]
PRINT_OBJ_GETATTR = 1
PRINT_OBJ_HIDE_INTERNAL = 2
PRINT_OBJ_COMPACT = 4
PRINT_OBJ_NONONE = 8
PRINT_OBJ_INTERNAL = 512
def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent=30):
if ((maxIndent != None) and (indent > maxIndent)):
print >> out, " "*indent, name, str(object)
return True
finalNewLine = False
printed = True
if ((flags & PRINT_OBJ_COMPACT) > 0):
if (exclude and object in exclude):
return
indent = 0
if ((flags & PRINT_OBJ_INTERNAL) == 0):
finalNewLine = True
flags |= PRINT_OBJ_INTERNAL
if (object == None):
if (flags & PRINT_OBJ_NONONE) == 0:
print >> out, " "*indent, name, " = None",
else:
finalNewLine = False
printed = False
elif (name.startswith("_") and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)):
finalNewLine = False
printed = False
elif (isinstance(object, (list, tuple))):
if (exclude and object in exclude):
print >> out, " "*indent, name, " : ", type(object), " of length = ", len(object), " (already printed)",
elif (exclude and name in exclude):
print >> out, " "*indent, name, " : ", type(object), " of length = ", len(object), " (excluded)",
else:
if (exclude != None): exclude.append(object)
print >> out, " "*indent, name, " : ", type(object), " of length = %i" % len(object),
for i, o in enumerate(object):
print >> out
printObject(out, o, name="[%i]" % i, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent)
elif (isinstance(object, dict)):
if (exclude and object in exclude):
print >> out, " "*indent, name, " : ", type(object), " (already printed)",
else:
if (exclude != None): exclude.append(object)
if (len(name) > 0):
print >> out, " "*indent, name,
if ((flags & PRINT_OBJ_COMPACT) == 0):
print >> out
indent += 2
print >> out, " "*indent, "{",
if ((flags & PRINT_OBJ_COMPACT) == 0):
print >> out
keys = object.keys()
keys.sort()
for n in keys:
if ((n != None) and (not n.startswith("_") or ((flags & PRINT_OBJ_HIDE_INTERNAL) == 0))):
if printObject(out, object[n], name=n, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent):
if ((flags & PRINT_OBJ_COMPACT) == 0):
print >> out
else:
print >> out, ",",
print >> out, " "*indent, "}",
elif (hasattr(object, "__dict__")):
if (exclude and object in exclude):
print >> out, " "*indent, name, " : ", type(object), " (already printed) = ", toDiffableString(object),
else:
if (exclude != None): exclude.append(object)
if (name.startswith("_")):
print >> out, " "*indent, name, " : ", type(object),
elif (exclude and object.__dict__ in exclude):
print >> out, " "*indent, name, " : ", type(object), " (already printed)",
else:
print >> out, " "*indent, name, " : ", type(object),
if ((flags & PRINT_OBJ_GETATTR) == 0):
if ((flags & PRINT_OBJ_COMPACT) == 0):
print >> out
printObject(out, object.__dict__, indent=indent, flags=flags, exclude=exclude, maxIndent=maxIndent)
else:
keys = object.__dict__.keys()
keys.sort()
for n in keys:
if ((flags & PRINT_OBJ_COMPACT) == 0):
print >> out
printObject(out, getattr(object, n), name=n, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent)
elif (indent < 0):
print >> out, object,
elif isinstance(object, basestring):
if (exclude and name in exclude):
print >> out, " "*indent, name, " : ", type(object), " of length = ", len(object), " (excluded)",
elif (len(object) > 100):
print >> out, " "*indent, name, ":", type(object), "[%i] = %s...%s" % (len(object), object[:50], object[-50:]),
else:
print >> out, " "*indent, name, ":", type(object), "=", str(object),
else:
print >> out, " "*indent, name, ":", type(object), "=", str(object),
if (finalNewLine):
print >> out
return printed

View File

@@ -195,6 +195,8 @@ def _objectfactory(objname, objargs=None, xsname=None):
try: try:
if __builtin__.__dict__.has_key(objname): if __builtin__.__dict__.has_key(objname):
module = __builtin__ module = __builtin__
elif knownGlobalModule:
module = knownGlobalModule
else: else:
if modulename: if modulename:
module = __import__(modulename) module = __import__(modulename)
@@ -431,12 +433,13 @@ def _getXmlValue(pythonValue):
else: else:
return str(pythonValue) return str(pythonValue)
def unmarshal(xmlstr, knownTypes=None): def unmarshal(xmlstr, knownTypes=None, knownModule=None):
global knownGlobalTypes global knownGlobalTypes, knownGlobalModule
if (knownTypes == None): if (knownTypes == None):
knownGlobalTypes = {} knownGlobalTypes = {}
else: else:
knownGlobalTypes = knownTypes knownGlobalTypes = knownTypes
knownGlobalModule = knownModule
objectfactory = XMLObjectFactory() objectfactory = XMLObjectFactory()
xml.sax.parseString(xmlstr, objectfactory) xml.sax.parseString(xmlstr, objectfactory)
return objectfactory.getRootObject() return objectfactory.getRootObject()

View File

@@ -435,6 +435,7 @@ class Document(wx.EvtHandler):
msgTitle = _("File Error") msgTitle = _("File Error")
backupFilename = None backupFilename = None
fileObject = None
try: try:
# if current file exists, move it to a safe place temporarily # if current file exists, move it to a safe place temporarily
if os.path.exists(filename): if os.path.exists(filename):
@@ -457,10 +458,18 @@ class Document(wx.EvtHandler):
fileObject = file(filename, 'w') fileObject = file(filename, 'w')
self.SaveObject(fileObject) self.SaveObject(fileObject)
fileObject.close() fileObject.close()
fileObject = None
if backupFilename: if backupFilename:
os.remove(backupFilename) os.remove(backupFilename)
except: except:
# for debugging purposes
import traceback
traceback.print_exc()
if fileObject:
fileObject.close() # file is still open, close it, need to do this before removal
# save failed, restore old file # save failed, restore old file
if backupFilename: if backupFilename:
os.remove(filename) os.remove(filename)
@@ -501,7 +510,16 @@ class Document(wx.EvtHandler):
fileObject = file(filename, 'r') fileObject = file(filename, 'r')
try: try:
self.LoadObject(fileObject) self.LoadObject(fileObject)
fileObject.close()
fileObject = None
except: except:
# for debugging purposes
import traceback
traceback.print_exc()
if fileObject:
fileObject.close() # file is still open, close it
wx.MessageBox("Could not open '%s'. %s" % (FileNameFromPath(filename), sys.exc_value), wx.MessageBox("Could not open '%s'. %s" % (FileNameFromPath(filename), sys.exc_value),
msgTitle, msgTitle,
wx.OK | wx.ICON_EXCLAMATION, wx.OK | wx.ICON_EXCLAMATION,
@@ -945,7 +963,7 @@ class View(wx.EvtHandler):
Override to return an instance of a class other than wxDocPrintout. Override to return an instance of a class other than wxDocPrintout.
""" """
return DocPrintout(self) return DocPrintout(self, self.GetDocument().GetPrintableName())
def GetFrame(self): def GetFrame(self):
@@ -1229,6 +1247,10 @@ class DocTemplate(wx.Object):
Returns True if the path's extension matches one of this template's Returns True if the path's extension matches one of this template's
file filter extensions. file filter extensions.
""" """
## print "*** path", path
## if "*.*" in self.GetFileFilter():
## return True
##
ext = FindExtension(path) ext = FindExtension(path)
if not ext: return False if not ext: return False
return ext in self.GetFileFilter() return ext in self.GetFileFilter()
@@ -1450,9 +1472,14 @@ class DocManager(wx.EvtHandler):
printout = view.OnCreatePrintout() printout = view.OnCreatePrintout()
if printout: if printout:
pdd = wx.PrintDialogData() if not hasattr(self, "printData"):
self.printData = wx.PrintData()
self.printData.SetPaperId(wx.PAPER_LETTER)
self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
pdd = wx.PrintDialogData(self.printData)
printer = wx.Printer(pdd) printer = wx.Printer(pdd)
printer.Print(view.GetFrame(), printout) # , True) printer.Print(view.GetFrame(), printout)
def OnPrintSetup(self, event): def OnPrintSetup(self, event):
@@ -1465,11 +1492,21 @@ class DocManager(wx.EvtHandler):
else: else:
parentWin = wx.GetApp().GetTopWindow() parentWin = wx.GetApp().GetTopWindow()
data = wx.PrintDialogData() if not hasattr(self, "printData"):
self.printData = wx.PrintData()
self.printData.SetPaperId(wx.PAPER_LETTER)
data = wx.PrintDialogData(self.printData)
printDialog = wx.PrintDialog(parentWin, data) printDialog = wx.PrintDialog(parentWin, data)
printDialog.GetPrintDialogData().SetSetupDialog(True) printDialog.GetPrintDialogData().SetSetupDialog(True)
printDialog.ShowModal() printDialog.ShowModal()
# TODO: Confirm that we don't have to remember PrintDialogData
# this makes a copy of the wx.PrintData instead of just saving
# a reference to the one inside the PrintDialogData that will
# be destroyed when the dialog is destroyed
self.printData = wx.PrintData(printDialog.GetPrintDialogData().GetPrintData())
printDialog.Destroy()
def OnPreview(self, event): def OnPreview(self, event):
@@ -1483,13 +1520,22 @@ class DocManager(wx.EvtHandler):
printout = view.OnCreatePrintout() printout = view.OnCreatePrintout()
if printout: if printout:
if not hasattr(self, "printData"):
self.printData = wx.PrintData()
self.printData.SetPaperId(wx.PAPER_LETTER)
self.printData.SetPrintMode(wx.PRINT_MODE_PREVIEW)
data = wx.PrintDialogData(self.printData)
# Pass two printout objects: for preview, and possible printing. # Pass two printout objects: for preview, and possible printing.
preview = wx.PrintPreview(printout, view.OnCreatePrintout()) preview = wx.PrintPreview(printout, view.OnCreatePrintout(), data)
if not preview.Ok():
wx.MessageBox(_("Unable to display print preview."))
return
# wxWindows source doesn't use base frame's pos, size, and icon, but did it this way so it would work like MS Office etc. # wxWindows source doesn't use base frame's pos, size, and icon, but did it this way so it would work like MS Office etc.
mimicFrame = wx.GetApp().GetTopWindow() mimicFrame = wx.GetApp().GetTopWindow()
frame = wx.PreviewFrame(preview, mimicFrame, _("Print Preview"), mimicFrame.GetPosition(), mimicFrame.GetSize()) frame = wx.PreviewFrame(preview, mimicFrame, _("Print Preview"), mimicFrame.GetPosition(), mimicFrame.GetSize())
frame.SetIcon(mimicFrame.GetIcon()) frame.SetIcon(mimicFrame.GetIcon())
frame.SetTitle(mimicFrame.GetTitle() + _(" - Preview")) frame.SetTitle(_("%s - %s - Preview") % (mimicFrame.GetTitle(), view.GetDocument().GetPrintableName()))
frame.Initialize() frame.Initialize()
frame.Show(True) frame.Show(True)
@@ -1575,7 +1621,7 @@ class DocManager(wx.EvtHandler):
if doc and doc.GetCommandProcessor(): if doc and doc.GetCommandProcessor():
doc.GetCommandProcessor().SetMenuStrings() doc.GetCommandProcessor().SetMenuStrings()
else: else:
event.SetText(_("Undo") + '\t' + _('Ctrl+Z')) event.SetText(_("&Undo\tCtrl+Z"))
def OnUpdateRedo(self, event): def OnUpdateRedo(self, event):
@@ -1587,7 +1633,7 @@ class DocManager(wx.EvtHandler):
if doc and doc.GetCommandProcessor(): if doc and doc.GetCommandProcessor():
doc.GetCommandProcessor().SetMenuStrings() doc.GetCommandProcessor().SetMenuStrings()
else: else:
event.SetText(_("Redo") + '\t' + _('Ctrl+Y')) event.SetText(_("&Redo\tCtrl+Y"))
def OnUpdatePrint(self, event): def OnUpdatePrint(self, event):
@@ -1800,9 +1846,9 @@ class DocManager(wx.EvtHandler):
temp, path = self.SelectDocumentPath(templates, path, flags) temp, path = self.SelectDocumentPath(templates, path, flags)
# Existing document # Existing document
if self.GetFlags() & DOC_OPEN_ONCE: if path and self.GetFlags() & DOC_OPEN_ONCE:
for document in self._docs: for document in self._docs:
if document.GetFilename() == path: if document.GetFilename() and os.path.normcase(document.GetFilename()) == os.path.normcase(path):
""" check for file modification outside of application """ """ check for file modification outside of application """
if os.path.exists(path) and os.path.getmtime(path) != document.GetDocumentModificationDate(): if os.path.exists(path) and os.path.getmtime(path) != document.GetDocumentModificationDate():
msgTitle = wx.GetApp().GetAppName() msgTitle = wx.GetApp().GetAppName()
@@ -2034,11 +2080,17 @@ class DocManager(wx.EvtHandler):
Given a path, try to find template that matches the extension. This is Given a path, try to find template that matches the extension. This is
only an approximate method of finding a template for creating a only an approximate method of finding a template for creating a
document. document.
Note this wxPython verson looks for and returns a default template if no specific template is found.
""" """
default = None
for temp in self._templates: for temp in self._templates:
if temp.FileMatchesTemplate(path): if temp.FileMatchesTemplate(path):
return temp return temp
return None
if "*.*" in temp.GetFileFilter():
default = temp
return default
def FindSuitableParent(self): def FindSuitableParent(self):
@@ -2077,7 +2129,7 @@ class DocManager(wx.EvtHandler):
allfilter = allfilter + _(';') allfilter = allfilter + _(';')
descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
allfilter = allfilter + temp.GetFileFilter() allfilter = allfilter + temp.GetFileFilter()
descr = _("All") + _(" (") + allfilter + _(") |") + allfilter + _('|') + descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk descr = _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter, allfilter, descr) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
else: else:
descr = _("*.*") descr = _("*.*")
@@ -2790,7 +2842,7 @@ class DocPrintout(wx.Printout):
""" """
Constructor. Constructor.
""" """
wx.Printout.__init__(self) wx.Printout.__init__(self, title)
self._printoutView = view self._printoutView = view
@@ -3058,15 +3110,15 @@ class CommandProcessor(wx.Object):
else: else:
redoAccel = '' redoAccel = ''
if undoCommand and undoItem and undoCommand.CanUndo(): if undoCommand and undoItem and undoCommand.CanUndo():
undoItem.SetText(_("Undo ") + undoCommand.GetName() + undoAccel) undoItem.SetText(_("&Undo ") + undoCommand.GetName() + undoAccel)
#elif undoCommand and not undoCommand.CanUndo(): #elif undoCommand and not undoCommand.CanUndo():
# undoItem.SetText(_("Can't Undo") + undoAccel) # undoItem.SetText(_("Can't Undo") + undoAccel)
else: else:
undoItem.SetText(_("Undo" + undoAccel)) undoItem.SetText(_("&Undo" + undoAccel))
if redoCommand and redoItem: if redoCommand and redoItem:
redoItem.SetText(_("Redo ") + redoCommand.GetName() + redoAccel) redoItem.SetText(_("&Redo ") + redoCommand.GetName() + redoAccel)
else: else:
redoItem.SetText(_("Redo") + redoAccel) redoItem.SetText(_("&Redo") + redoAccel)
def CanUndo(self): def CanUndo(self):

View File

@@ -295,7 +295,7 @@ class DocMDIParentFrameMixIn:
config = wx.ConfigBase_Get() config = wx.ConfigBase_Get()
if config.ReadInt("MDIFrameMaximized", False): if config.ReadInt("MDIFrameMaximized", False):
# wxBug: On maximize, statusbar leaves a residual that needs to be refreshed, happens even when user does it # wxBug: On maximize, statusbar leaves a residual that needs to be refereshed, happens even when user does it
self.Maximize() self.Maximize()
self.CreateEmbeddedWindows(embeddedWindows) self.CreateEmbeddedWindows(embeddedWindows)
@@ -1603,7 +1603,7 @@ class DocApp(wx.PySimpleApp):
args = pickle.loads(data) args = pickle.loads(data)
for arg in args: for arg in args:
if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg): if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg):
self.GetDocumentManager().CreateDocument(arg, wx.lib.docview.DOC_SILENT) self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
# force display of running app # force display of running app
topWindow = wx.GetApp().GetTopWindow() topWindow = wx.GetApp().GetTopWindow()
@@ -1624,7 +1624,7 @@ class DocApp(wx.PySimpleApp):
args = sys.argv[1:] args = sys.argv[1:]
for arg in args: for arg in args:
if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg): if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg):
self.GetDocumentManager().CreateDocument(arg, wx.lib.docview.DOC_SILENT) self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
def GetDocumentManager(self): def GetDocumentManager(self):