X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/74b8945829b602ebeae29f0237fbb8ff3f041f87..0a5bb138a71dfc1c706fc0858fb2801500e2c2e8:/wxPython/wx/lib/docview.py diff --git a/wxPython/wx/lib/docview.py b/wxPython/wx/lib/docview.py index aad8359e14..8f85b4be2f 100644 --- a/wxPython/wx/lib/docview.py +++ b/wxPython/wx/lib/docview.py @@ -6,13 +6,14 @@ # # Created: 5/15/03 # CVS-ID: $Id$ -# Copyright: (c) 2003-2004 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al) +# Copyright: (c) 2003-2006 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al) # License: wxWindows license #---------------------------------------------------------------------------- import os import os.path +import shutil import wx import sys _ = wx.GetTranslation @@ -27,10 +28,12 @@ DOC_MDI = 2 DOC_NEW = 4 DOC_SILENT = 8 DOC_OPEN_ONCE = 16 +DOC_NO_VIEW = 32 DEFAULT_DOCMAN_FLAGS = DOC_SDI & DOC_OPEN_ONCE TEMPLATE_VISIBLE = 1 TEMPLATE_INVISIBLE = 2 +TEMPLATE_NO_CREATE = (4 | TEMPLATE_VISIBLE) DEFAULT_TEMPLATE_FLAGS = TEMPLATE_VISIBLE MAX_FILE_HISTORY = 9 @@ -76,26 +79,31 @@ class Document(wx.EvtHandler): The document class can be used to model an application's file-based data. It is part of the document/view framework supported by wxWindows, and cooperates with the wxView, wxDocTemplate and wxDocManager classes. + + Note this wxPython version also keeps track of the modification date of the + document and if it changes on disk outside of the application, we will warn the + user before saving to avoid clobbering the file. """ - def __init__(self, parent = None): + def __init__(self, parent=None): """ Constructor. Define your own default constructor to initialize application-specific data. """ wx.EvtHandler.__init__(self) - self._documentModified = False self._documentParent = parent self._documentTemplate = None self._commandProcessor = None self._savedYet = False + self._writeable = True self._documentTitle = None self._documentFile = None self._documentTypeName = None self._documentModified = False + self._documentModificationDate = None self._documentViews = [] @@ -166,7 +174,7 @@ class Document(wx.EvtHandler): return self._savedYet - def SetDocumentSaved(self, saved = True): + def SetDocumentSaved(self, saved=True): """ Sets whether the document has been saved. This method has been added to wxPython and is not in wxWindows. @@ -206,8 +214,38 @@ class Document(wx.EvtHandler): false otherwise. You may need to override this if your document view maintains its own record of being modified (for example if using xTextWindow to view and edit the document). + This method has been extended to notify its views that the dirty flag has changed. """ self._documentModified = modify + self.UpdateAllViews(hint=("modify", self, self._documentModified)) + + + def SetDocumentModificationDate(self): + """ + Saves the file's last modification date. + This is used to check if the file has been modified outside of the application. + This method has been added to wxPython and is not in wxWindows. + """ + self._documentModificationDate = os.path.getmtime(self.GetFilename()) + + + def GetDocumentModificationDate(self): + """ + Returns the file's modification date when it was loaded from disk. + This is used to check if the file has been modified outside of the application. + This method has been added to wxPython and is not in wxWindows. + """ + return self._documentModificationDate + + + def IsDocumentModificationDateCorrect(self): + """ + Returns False if the file has been modified outside of the application. + This method has been added to wxPython and is not in wxWindows. + """ + if not os.path.exists(self.GetFilename()): # document must be in memory only and can't be out of date + return True + return self._documentModificationDate == os.path.getmtime(self.GetFilename()) def GetViews(self): @@ -245,6 +283,7 @@ class Document(wx.EvtHandler): Destructor. Removes itself from the document manager. """ self.DeleteContents() + self._documentModificationDate = None if self.GetDocumentManager(): self.GetDocumentManager().RemoveDocument(self) wx.EvtHandler.Destroy(self) @@ -334,9 +373,26 @@ class Document(wx.EvtHandler): Saves the document by calling OnSaveDocument if there is an associated filename, or SaveAs if there is no filename. """ - if not self.IsModified() and self._savedYet: + if not self.IsModified(): # and self._savedYet: This was here, but if it is not modified who cares if it hasn't been saved yet? return True + """ check for file modification outside of application """ + if not self.IsDocumentModificationDateCorrect(): + msgTitle = wx.GetApp().GetAppName() + if not msgTitle: + msgTitle = _("Application") + res = wx.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()), + msgTitle, + wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION, + self.GetDocumentWindow()) + + if res == wx.NO: + return True + elif res == wx.YES: + pass + else: # elif res == wx.CANCEL: + return False + if not self._documentFile or not self._savedYet: return self.SaveAs() return self.OnSaveDocument(self._documentFile) @@ -395,6 +451,8 @@ class Document(wx.EvtHandler): msgTitle = _("File Error") backupFilename = None + fileObject = None + copied = False try: # if current file exists, move it to a safe place temporarily if os.path.exists(filename): @@ -412,18 +470,27 @@ class Document(wx.EvtHandler): while os.path.exists(backupFilename): i += 1 backupFilename = "%s.bak%s" % (filename, i) - os.rename(filename, backupFilename) + shutil.copy(filename, backupFilename) + copied = True fileObject = file(filename, 'w') self.SaveObject(fileObject) - + fileObject.close() + fileObject = None + if backupFilename: os.remove(backupFilename) except: - # save failed, restore old file - if backupFilename: - os.remove(filename) - os.rename(backupFilename, filename) + # 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, remove copied file + if backupFilename and copied: + os.remove(backupFilename) wx.MessageBox("Could not save '%s'. %s" % (FileNameFromPath(filename), sys.exc_value), msgTitle, @@ -431,6 +498,7 @@ class Document(wx.EvtHandler): self.GetDocumentWindow()) return False + self.SetDocumentModificationDate() self.SetFilename(filename, True) self.Modify(False) self.SetDocumentSaved(True) @@ -458,13 +526,23 @@ class Document(wx.EvtHandler): fileObject = file(filename, 'r') try: self.LoadObject(fileObject) + fileObject.close() + fileObject = None 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), msgTitle, wx.OK | wx.ICON_EXCLAMATION, self.GetDocumentWindow()) return False + self.SetDocumentModificationDate() self.SetFilename(filename, True) self.Modify(False) self.SetDocumentSaved(True) @@ -548,6 +626,24 @@ class Document(wx.EvtHandler): if not self.IsModified(): return True + """ check for file modification outside of application """ + if not self.IsDocumentModificationDateCorrect(): + msgTitle = wx.GetApp().GetAppName() + if not msgTitle: + msgTitle = _("Warning") + res = wx.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()), + msgTitle, + wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION, + self.GetDocumentWindow()) + + if res == wx.NO: + self.Modify(False) + return True + elif res == wx.YES: + return wx.lib.docview.Document.Save(self) + else: # elif res == wx.CANCEL: + return False + msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("Warning") @@ -599,8 +695,10 @@ class Document(wx.EvtHandler): """ The default implementation calls DeleteContents (an empty implementation) sets the modified flag to false. Override this to - supply additional behaviour when the document is closed with Close. + supply additional behaviour when the document is opened with Open. """ + if flags & DOC_NO_VIEW: + return True return self.GetDocumentTemplate().CreateView(self, flags) @@ -646,6 +744,29 @@ class Document(wx.EvtHandler): view.OnChangeFilename() + def GetWriteable(self): + """ + Returns true if the document can be written to its accociated file path. + This method has been added to wxPython and is not in wxWindows. + """ + if not self._writeable: + return False + if not self._documentFile: # Doesn't exist, do a save as + return True + else: + return os.access(self._documentFile, os.W_OK) + + + def SetWriteable(self, writeable): + """ + Set to False if the document can not be saved. This will disable the ID_SAVE_AS + event and is useful for custom documents that should not be saveable. The ID_SAVE + event can be disabled by never Modifying the document. This method has been added + to wxPython and is not in wxWindows. + """ + self._writeable = writeable + + class View(wx.EvtHandler): """ The view class can be used to model the viewing and editing component of @@ -736,8 +857,14 @@ class View(wx.EvtHandler): unused but may in future contain application-specific information for making updating more efficient. """ - pass - + if hint: + if hint[0] == "modify": # if dirty flag changed, update the view's displayed title + frame = self.GetFrame() + if frame and hasattr(frame, "OnTitleIsModified"): + frame.OnTitleIsModified() + return True + return False + def OnChangeFilename(self): """ @@ -753,7 +880,7 @@ class View(wx.EvtHandler): else: return else: - if appName and not isinstance(self.GetFrame(), DocMDIChildFrame): # Don't need appname in title for MDI + if appName and isinstance(self.GetFrame(), DocChildFrame): # Only need app name in title for SDI title = appName + _(" - ") else: title = '' @@ -792,7 +919,7 @@ class View(wx.EvtHandler): self._viewTypeName = name - def Close(self, deleteWindow = True): + def Close(self, deleteWindow=True): """ Closes the view by calling OnClose. If deleteWindow is true, this function should delete the window associated with the view. @@ -803,7 +930,7 @@ class View(wx.EvtHandler): return False - def Activate(self, activate = True): + def Activate(self, activate=True): """ Call this from your view frame's OnActivate member to tell the framework which view is currently active. If your windowing system @@ -819,7 +946,7 @@ class View(wx.EvtHandler): self.GetDocumentManager().ActivateView(self, activate) - def OnClose(self, deleteWindow = True): + def OnClose(self, deleteWindow=True): """ Implements closing behaviour. The default implementation calls wxDocument.Close to close the associated document. Does not delete the @@ -860,7 +987,7 @@ class View(wx.EvtHandler): Override to return an instance of a class other than wxDocPrintout. """ - return DocPrintout(self) + return DocPrintout(self, self.GetDocument().GetPrintableName()) def GetFrame(self): @@ -900,7 +1027,7 @@ class DocTemplate(wx.Object): """ - def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags = DEFAULT_TEMPLATE_FLAGS, icon = None): + def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=DEFAULT_TEMPLATE_FLAGS, icon=None): """ Constructor. Create instances dynamically near the start of your application after creating a wxDocManager instance, and before doing @@ -912,7 +1039,7 @@ class DocTemplate(wx.Object): string will be displayed in the file filter list of Windows file selectors. - filter is an appropriate file filter such as *.txt. + filter is an appropriate file filter such as \*.txt. dir is the default directory to use for file selectors. @@ -1089,6 +1216,16 @@ class DocTemplate(wx.Object): return (self._flags & TEMPLATE_VISIBLE) == TEMPLATE_VISIBLE + def IsNewable(self): + """ + Returns true if the document template can be shown in "New" dialogs, + false otherwise. + + This method has been added to wxPython and is not in wxWindows. + """ + return (self._flags & TEMPLATE_NO_CREATE) != TEMPLATE_NO_CREATE + + def GetDocumentName(self): """ Returns the document type name, as passed to the document template @@ -1146,8 +1283,9 @@ class DocTemplate(wx.Object): """ ext = FindExtension(path) if not ext: return False - return ext in self.GetFileFilter() - # return self.GetDefaultExtension() == FindExtension(path) + + extList = self.GetFileFilter().replace('*','').split(';') + return ext in extList class DocManager(wx.EvtHandler): @@ -1157,7 +1295,7 @@ class DocManager(wx.EvtHandler): classes. """ - def __init__(self, flags = DEFAULT_DOCMAN_FLAGS, initialize = True): + def __init__(self, flags=DEFAULT_DOCMAN_FLAGS, initialize=True): """ Constructor. Create a document manager instance dynamically near the start of your application before doing any document or view operations. @@ -1230,7 +1368,7 @@ class DocManager(wx.EvtHandler): return self._flags - def CloseDocument(self, doc, force = True): + def CloseDocument(self, doc, force=True): """ Closes the specified document. """ @@ -1242,7 +1380,7 @@ class DocManager(wx.EvtHandler): return False - def CloseDocuments(self, force = True): + def CloseDocuments(self, force=True): """ Closes all currently opened documents. """ @@ -1253,7 +1391,7 @@ class DocManager(wx.EvtHandler): return True - def Clear(self, force = True): + def Clear(self, force=True): """ Closes all currently opened document by callling CloseDocuments and clears the document manager's templates. @@ -1306,7 +1444,7 @@ class DocManager(wx.EvtHandler): """ return self.CloseDocuments(force = False) - + def OnFileNew(self, event): """ Creates a new document and reads in the selected file. @@ -1365,9 +1503,14 @@ class DocManager(wx.EvtHandler): printout = view.OnCreatePrintout() 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.Print(view.GetFrame(), printout) # , True) + printer.Print(view.GetFrame(), printout) def OnPrintSetup(self, event): @@ -1380,11 +1523,21 @@ class DocManager(wx.EvtHandler): else: 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.GetPrintDialogData().SetSetupDialog(True) 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): @@ -1398,13 +1551,22 @@ class DocManager(wx.EvtHandler): printout = view.OnCreatePrintout() 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. - 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. mimicFrame = wx.GetApp().GetTopWindow() frame = wx.PreviewFrame(preview, mimicFrame, _("Print Preview"), mimicFrame.GetPosition(), mimicFrame.GetSize()) frame.SetIcon(mimicFrame.GetIcon()) - frame.SetTitle(mimicFrame.GetTitle() + _(" - Preview")) + frame.SetTitle(_("%s - %s - Preview") % (mimicFrame.GetTitle(), view.GetDocument().GetPrintableName())) frame.Initialize() frame.Show(True) @@ -1478,7 +1640,7 @@ class DocManager(wx.EvtHandler): """ Updates the user interface for the File Save As command. """ - event.Enable(self.GetCurrentDocument() != None) + event.Enable(self.GetCurrentDocument() != None and self.GetCurrentDocument().GetWriteable()) def OnUpdateUndo(self, event): @@ -1490,7 +1652,7 @@ class DocManager(wx.EvtHandler): if doc and doc.GetCommandProcessor(): doc.GetCommandProcessor().SetMenuStrings() else: - event.SetText(_("Undo") + '\t' + _('Ctrl+Z')) + event.SetText(_("&Undo\tCtrl+Z")) def OnUpdateRedo(self, event): @@ -1502,7 +1664,7 @@ class DocManager(wx.EvtHandler): if doc and doc.GetCommandProcessor(): doc.GetCommandProcessor().SetMenuStrings() else: - event.SetText(_("Redo") + '\t' + _('Ctrl+Y')) + event.SetText(_("&Redo\tCtrl+Y")) def OnUpdatePrint(self, event): @@ -1653,7 +1815,7 @@ class DocManager(wx.EvtHandler): return False - def CreateDocument(self, path, flags = 0): + def CreateDocument(self, path, flags=0): """ Creates a new document in a manner determined by the flags parameter, which can be: @@ -1674,7 +1836,13 @@ class DocManager(wx.EvtHandler): will delete the oldest currently loaded document before creating a new one. - wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE flag. + wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE + and wx.lib.docview.DOC_NO_VIEW flag. + + if wx.lib.docview.DOC_OPEN_ONCE is present, trying to open the same file multiple + times will just return the same document. + if wx.lib.docview.DOC_NO_VIEW is present, opening a file will generate the document, + but not generate a corresponding view. """ templates = [] for temp in self._templates: @@ -1689,16 +1857,13 @@ class DocManager(wx.EvtHandler): return None if flags & DOC_NEW: + for temp in templates[:]: + if not temp.IsNewable(): + templates.remove(temp) if len(templates) == 1: temp = templates[0] - newDoc = temp.CreateDocument(path, flags) - if newDoc: - newDoc.SetDocumentName(temp.GetDocumentName()) - newDoc.SetDocumentTemplate(temp) - newDoc.OnNewDocument() - return newDoc - - temp = self.SelectDocumentType(templates) + else: + temp = self.SelectDocumentType(templates) if temp: newDoc = temp.CreateDocument(path, flags) if newDoc: @@ -1715,11 +1880,34 @@ class DocManager(wx.EvtHandler): temp, path = self.SelectDocumentPath(templates, path, flags) # Existing document - if self.GetFlags() & DOC_OPEN_ONCE: + if path and self.GetFlags() & DOC_OPEN_ONCE: 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 """ + if not document.IsDocumentModificationDateCorrect(): + msgTitle = wx.GetApp().GetAppName() + if not msgTitle: + msgTitle = _("Warning") + shortName = document.GetPrintableName() + res = wx.MessageBox(_("'%s' has been modified outside of %s. Reload '%s' from file system?") % (shortName, msgTitle, shortName), + msgTitle, + wx.YES_NO | wx.ICON_QUESTION, + self.FindSuitableParent()) + if res == wx.YES: + if not self.CloseDocument(document, False): + wx.MessageBox(_("Couldn't reload '%s'. Unable to close current '%s'.") % (shortName, shortName)) + return None + return self.CreateDocument(path, flags) + elif res == wx.NO: # don't ask again + document.SetDocumentModificationDate() + firstView = document.GetFirstView() - if firstView and firstView.GetFrame(): + if not firstView and not (flags & DOC_NO_VIEW): + document.GetDocumentTemplate().CreateView(document, flags) + document.UpdateAllViews() + firstView = document.GetFirstView() + + if firstView and firstView.GetFrame() and not (flags & DOC_NO_VIEW): firstView.GetFrame().SetFocus() # Not in wxWindows code but useful nonetheless if hasattr(firstView.GetFrame(), "IsIconized") and firstView.GetFrame().IsIconized(): # Not in wxWindows code but useful nonetheless firstView.GetFrame().Iconize(False) @@ -1732,7 +1920,9 @@ class DocManager(wx.EvtHandler): newDoc.SetDocumentTemplate(temp) if not newDoc.OnOpenDocument(path): newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews - newDoc.GetFirstView().GetFrame().Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it. + frame = newDoc.GetFirstView().GetFrame() + if frame: + frame.Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it. return None self.AddFileToHistory(path) return newDoc @@ -1740,7 +1930,7 @@ class DocManager(wx.EvtHandler): return None - def CreateView(self, document, flags = 0): + def CreateView(self, doc, flags=0): """ Creates a new view for the given document. If more than one view is allowed for the document (by virtue of multiple templates mentioning @@ -1901,7 +2091,7 @@ class DocManager(wx.EvtHandler): self._fileHistory.Save(config) - def FileHistoryAddFilesToMenu(self, menu = None): + def FileHistoryAddFilesToMenu(self, menu=None): """ Appends the files in the history list, to all menus managed by the file history object. @@ -1931,11 +2121,17 @@ class DocManager(wx.EvtHandler): Given a path, try to find template that matches the extension. This is only an approximate method of finding a template for creating a 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: if temp.FileMatchesTemplate(path): return temp - return None + + if "*.*" in temp.GetFileFilter(): + default = temp + return default def FindSuitableParent(self): @@ -1965,41 +2161,32 @@ class DocManager(wx.EvtHandler): This function is used in wxDocManager.CreateDocument. """ if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__": - allfilter = '' descr = '' for temp in templates: if temp.IsVisible(): if len(descr) > 0: descr = descr + _('|') - 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 - 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") % descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk else: descr = _("*.*") - path = wx.FileSelector(_("Select a File"), - self._lastDirectory, - _(""), - wildcard = descr, - flags = wx.HIDE_READONLY, - parent = self.FindSuitableParent()) - if path: - if not FileExists(path): - msgTitle = wx.GetApp().GetAppName() - if not msgTitle: - msgTitle = _("File Error") - wx.MessageBox("Could not open '%s'." % FileNameFromPath(path), - msgTitle, - wx.OK | wx.ICON_EXCLAMATION, - parent) - return (None, None) - self._lastDirectory = PathOnly(path) - + dlg = wx.FileDialog(self.FindSuitableParent(), + _("Select a File"), + wildcard=descr, + style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR) + # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog + if dlg.ShowModal() == wx.ID_OK: + path = dlg.GetPath() + else: + path = None + dlg.Destroy() + + if path: theTemplate = self.FindTemplateForPath(path) return (theTemplate, path) - - return (None, None) + + return (None, None) def OnOpenFileFailure(self): @@ -2009,7 +2196,7 @@ class DocManager(wx.EvtHandler): pass - def SelectDocumentType(self, temps, sort = False): + def SelectDocumentType(self, temps, sort=False): """ Returns a document template by asking the user (if there is more than one template). This function is used in wxDocManager.CreateDocument. @@ -2057,7 +2244,7 @@ class DocManager(wx.EvtHandler): return templates[res] - def SelectViewType(self, temps, sort = False): + def SelectViewType(self, temps, sort=False): """ Returns a document template by asking the user (if there is more than one template), displaying a list of valid views. This function is used in wxDocManager::CreateView. The dialog normally will not appear because the array of templates only contains those relevant to the document in question, and often there will only be one such. """ @@ -2127,7 +2314,7 @@ class DocManager(wx.EvtHandler): self._docs.remove(doc) - def ActivateView(self, view, activate = True, deleting = False): + def ActivateView(self, view, activate=True, deleting=False): """ Sets the current view. """ @@ -2174,7 +2361,7 @@ class DocParentFrame(wx.Frame): classes. """ - def __init__(self, manager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"): + def __init__(self, manager, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"): """ Constructor. Note that the event table must be rebuilt for the frame since the EvtHandler is not virtual. @@ -2284,7 +2471,7 @@ class DocChildFrame(wx.Frame): """ - def __init__(self, doc, view, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"): + def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"): """ Constructor. Note that the event table must be rebuilt for the frame since the EvtHandler is not virtual. @@ -2430,7 +2617,7 @@ class DocMDIParentFrame(wx.MDIParentFrame): """ - def __init__(self, manager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"): + def __init__(self, manager, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"): """ Constructor. Note that the event table must be rebuilt for the frame since the EvtHandler is not virtual. @@ -2540,7 +2727,7 @@ class DocMDIChildFrame(wx.MDIChildFrame): """ - def __init__(self, doc, view, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"): + def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"): """ Constructor. Note that the event table must be rebuilt for the frame since the EvtHandler is not virtual. @@ -2623,6 +2810,7 @@ class DocMDIChildFrame(wx.MDIChildFrame): self._childView.Activate(event.GetActive()) self._activated = 0 + def OnCloseWindow(self, event): """ Closes and deletes the current view and document. @@ -2638,8 +2826,10 @@ class DocMDIChildFrame(wx.MDIChildFrame): self._childView.Activate(False) self._childView.Destroy() self._childView = None - if self._childDocument: - self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow + if self._childDocument: # This isn't in the wxWindows codebase but the document needs to be disposed of somehow + self._childDocument.DeleteContents() + if self._childDocument.GetDocumentManager(): + self._childDocument.GetDocumentManager().RemoveDocument(self._childDocument) self._childDocument = None self.Destroy() else: @@ -2676,6 +2866,28 @@ class DocMDIChildFrame(wx.MDIChildFrame): self._childView = view + def OnTitleIsModified(self): + """ + Add/remove to the frame's title an indication that the document is dirty. + If the document is dirty, an '*' is appended to the title + This method has been added to wxPython and is not in wxWindows. + """ + title = self.GetTitle() + if title: + if self.GetDocument().IsModified(): + if title.endswith("*"): + return + else: + title = title + "*" + self.SetTitle(title) + else: + if title.endswith("*"): + title = title[:-1] + self.SetTitle(title) + else: + return + + class DocPrintout(wx.Printout): """ DocPrintout is a default Printout that prints the first page of a document @@ -2683,11 +2895,11 @@ class DocPrintout(wx.Printout): """ - def __init__(self, view, title = "Printout"): + def __init__(self, view, title="Printout"): """ Constructor. """ - wx.Printout.__init__(self) + wx.Printout.__init__(self, title) self._printoutView = view @@ -2722,15 +2934,6 @@ class DocPrintout(wx.Printout): return pageNum == 1 - def OnBeginDocument(self, startPage, endPage): - """ - Not quite sure why this was overridden, but it was in wxWindows! :) - """ - if not wx.Printout.base_OnBeginDocument(self, startPage, endPage): - return False - return True - - def GetPageInfo(self): """ Indicates that the DocPrintout only has a single page. @@ -2829,7 +3032,7 @@ class CommandProcessor(wx.Object): """ - def __init__(self, maxCommands = -1): + def __init__(self, maxCommands=-1): """ Constructor. maxCommands may be set to a positive integer to limit the number of commands stored to it, otherwise (and by default) the @@ -2955,15 +3158,15 @@ class CommandProcessor(wx.Object): else: redoAccel = '' 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(): # undoItem.SetText(_("Can't Undo") + undoAccel) else: - undoItem.SetText(_("Undo" + undoAccel)) + undoItem.SetText(_("&Undo" + undoAccel)) if redoCommand and redoItem: - redoItem.SetText(_("Redo ") + redoCommand.GetName() + redoAccel) + redoItem.SetText(_("&Redo ") + redoCommand.GetName() + redoAccel) else: - redoItem.SetText(_("Redo") + redoAccel) + redoItem.SetText(_("&Redo") + redoAccel) def CanUndo(self): @@ -2984,7 +3187,7 @@ class CommandProcessor(wx.Object): return self._GetCurrentRedoCommand() != None - def Submit(self, command, storeIt = True): + def Submit(self, command, storeIt=True): """ Submits a new command to the command processor. The command processor calls wxCommand::Do to execute the command; if it succeeds, the @@ -2997,8 +3200,10 @@ class CommandProcessor(wx.Object): the history list. """ done = command.Do() - if done and storeIt: - self._commands.append(command) + if done: + del self._redoCommands[:] + if storeIt: + self._commands.append(command) if self._maxCommands > -1: if len(self._commands) > self._maxCommands: del self._commands[0]