def DoConfigChange(self): # Bit of a hack I dont kow what to do about - these should be "editor options" from pywin.framework.editor import GetEditorOption self.bAutoCompleteAttributes = GetEditorOption("Autocomplete Attributes", 1) self.bShowCallTips = GetEditorOption("Show Call Tips", 1) # Update the key map and extension data. configManager.configure(self, self._GetSubConfigNames()) if configManager.last_error: win32ui.MessageBox(configManager.last_error, "Configuration Error") self.bMatchBraces = GetEditorOption("Match Braces", 1) self.ApplyFormattingStyles(1)
def OnInitDialog(self): for name, val in self.autooptions: self[name] = GetEditorOption(name, val) # Note that these MUST be in the same order as the BAK constants. cbo = self.GetDlgItem(win32ui.IDC_COMBO1) cbo.AddString("None") cbo.AddString(".BAK File") cbo.AddString("TEMP dir") cbo.AddString("Own dir") # Source Safe bVSS = (GetEditorOption("Source Control Module", "") == "pywin.framework.editor.vss") self["bVSS"] = bVSS edit = self.GetDlgItem(win32ui.IDC_RIGHTEDGE_SAMPLE) edit.SetWindowText("Sample Color") rc = dialog.PropertyPage.OnInitDialog(self) try: self.GetDlgItem(win32ui.IDC_KEYBOARD_CONFIG).SelectString( -1, GetEditorOption("Keyboard Config", "default")) except win32ui.error: import traceback traceback.print_exc() pass self.HookCommand(self.OnButSimple, win32ui.IDC_FOLD_ENABLE) self.HookCommand(self.OnButSimple, win32ui.IDC_RADIO1) self.HookCommand(self.OnButSimple, win32ui.IDC_RADIO2) self.HookCommand(self.OnButSimple, win32ui.IDC_RIGHTEDGE_ENABLE) self.HookCommand(self.OnButEdgeColor, win32ui.IDC_RIGHTEDGE_DEFINE) butMarginEnabled = self["Marker Margin Width"] > 0 self.GetDlgItem(win32ui.IDC_RADIO1).SetCheck(butMarginEnabled) self.GetDlgItem(win32ui.IDC_RADIO2).SetCheck(not butMarginEnabled) self.edgeColor = self.initialEdgeColor = GetEditorOption( "Right Edge Color", win32api.RGB(0xEF, 0xEF, 0xEF)) for spinner_id in (win32ui.IDC_SPIN1, win32ui.IDC_SPIN2, win32ui.IDC_SPIN3): spinner = self.GetDlgItem(spinner_id) spinner.SetRange(0, 100) self.UpdateUIForState() return rc
def __init__(self): dialog.PropertyPage.__init__(self, win32ui.IDD_PP_EDITOR) self.autooptions = [] self._AddEditorOption(win32ui.IDC_AUTO_RELOAD, "i", "Auto Reload", 1) self._AddEditorOption(win32ui.IDC_COMBO1, "i", "Backup Type", document.BAK_DOT_BAK_BAK_DIR) self._AddEditorOption(win32ui.IDC_AUTOCOMPLETE, "i", "Autocomplete Attributes", 1) self._AddEditorOption(win32ui.IDC_CALLTIPS, "i", "Show Call Tips", 1) self._AddEditorOption(win32ui.IDC_MARGIN_LINENUMBER, "i", "Line Number Margin Width", 0) self._AddEditorOption(win32ui.IDC_RADIO1, "i", "MarkersInMargin", None) self._AddEditorOption(win32ui.IDC_MARGIN_MARKER, "i", "Marker Margin Width", None) self["Marker Margin Width"] = GetEditorOption("Marker Margin Width", 16) # Folding self._AddEditorOption(win32ui.IDC_MARGIN_FOLD, "i", "Fold Margin Width", 12) self._AddEditorOption(win32ui.IDC_FOLD_ENABLE, "i", "Enable Folding", 1) self._AddEditorOption(win32ui.IDC_FOLD_ON_OPEN, "i", "Fold On Open", 0) self._AddEditorOption(win32ui.IDC_FOLD_SHOW_LINES, "i", "Fold Lines", 1) # Right edge. self._AddEditorOption(win32ui.IDC_RIGHTEDGE_ENABLE, "i", "Right Edge Enabled", 0) self._AddEditorOption(win32ui.IDC_RIGHTEDGE_COLUMN, "i", "Right Edge Column", 75) # Source control, etc self.AddDDX(win32ui.IDC_VSS_INTEGRATE, "bVSS") self.AddDDX(win32ui.IDC_KEYBOARD_CONFIG, "Configs", "l") self["Configs"] = pywin.scintilla.config.find_config_files()
def OnOK(self): for name, defVal in self.autooptions: SetEditorOption(name, self[name]) # Margin width gets handled differently. if self['MarkersInMargin'] == 0: SetEditorOption("Marker Margin Width", self["Marker Margin Width"]) else: SetEditorOption("Marker Margin Width", 0) if self.edgeColor != self.initialEdgeColor: SetEditorOption("Right Edge Color", self.edgeColor) if self['bVSS']: SetEditorOption("Source Control Module", "pywin.framework.editor.vss") else: if GetEditorOption("Source Control Module", "")=='pywin.framework.editor.vss': SetEditorOption("Source Control Module", "") # Keyboard config configname = self.GetDlgItem(win32ui.IDC_KEYBOARD_CONFIG).GetWindowText() if configname: if configname == "default": DeleteEditorOption("Keyboard Config") else: SetEditorOption("Keyboard Config", configname) import pywin.scintilla.view pywin.scintilla.view.LoadConfiguration() # Now tell all views we have changed. ## for doc in editorTemplate.GetDocumentList(): ## for view in doc.GetAllViews(): ## try: ## fn = view.OnConfigChange ## except AttributeError: ## continue ## fn() return 1
def __init__(self, template): self.bAutoReload = GetEditorOption("Auto Reload", 1) self.bDeclinedReload = 0 # Has the user declined to reload. self.fileStat = None self.bReportedFileNotFound = 0 # what sort of bak file should I create. # default to write to %temp%/bak/filename.ext self.bakFileType=GetEditorOption("Backup Type", BAK_DOT_BAK_BAK_DIR) self.watcherThread = FileWatchingThread(self) self.watcherThread.CreateThread() # Should I try and use VSS integration? self.scModuleName=GetEditorOption("Source Control Module", "") self.scModule = None # Loaded when first used. ParentEditorDocument.__init__(self, template, template.CreateWin32uiDocument())
def _AddEditorOption(self, idd, typ, optionName, defaultVal): self.AddDDX(idd, optionName, typ) # some options are "derived" - ie, can be implied from others # (eg, "view markers in background" is implied from "markerMarginWidth==0" # So we don't actually store these values, but they do still get DDX support. if defaultVal is not None: self[optionName] = GetEditorOption(optionName, defaultVal) self.autooptions.append((optionName, defaultVal))
def __init__(self, doc): ParentEditorView.__init__(self, doc) if isRichText: self.SetWordWrap(win32ui.CRichEditView_WrapNone) self.addToMRU = 1 self.HookHandlers() self.bCheckingFile = 0 self.defCharFormat = GetEditorFontOption("Default Font", defaultCharacterFormat) # Smart tabs override everything else if context can be worked out. self.bSmartTabs = GetEditorOption("Smart Tabs", 1) self.tabSize = GetEditorOption("Tab Size", 8) self.indentSize = GetEditorOption("Indent Size", 8) # If next indent is at a tab position, and useTabs is set, a tab will be inserted. self.bUseTabs = GetEditorOption("Use Tabs", 1)
def OnInitDialog(self): for name, val in self.autooptions: self[name] = GetEditorOption(name, val) rc = dialog.PropertyPage.OnInitDialog(self) idc = win32ui.IDC_TABTIMMY_NONE if GetEditorOption("Use Tab Timmy", 1): idc = win32ui.IDC_TABTIMMY_IND self.GetDlgItem(idc).SetCheck(1) idc = win32ui.IDC_RADIO1 if GetEditorOption("Use Tabs", 0): idc = win32ui.IDC_USE_TABS self.GetDlgItem(idc).SetCheck(1) tt_color = GetEditorOption("Tab Timmy Color", win32api.RGB(0xff, 0, 0)) self.cbo = self.GetDlgItem(win32ui.IDC_COMBO1) for c in paletteVGA: self.cbo.AddString(c[0]) sel = 0 for c in paletteVGA: if tt_color == win32api.RGB(c[1], c[2], c[3]): break sel = sel + 1 else: sel = -1 self.cbo.SetCurSel(sel) self.HookCommand(self.OnButSimple, win32ui.IDC_TABTIMMY_NONE) self.HookCommand(self.OnButSimple, win32ui.IDC_TABTIMMY_IND) self.HookCommand(self.OnButSimple, win32ui.IDC_TABTIMMY_BG) # Set ranges for the spinners. for spinner_id in [win32ui.IDC_SPIN1, win32ui.IDC_SPIN2]: spinner = self.GetDlgItem(spinner_id) spinner.SetRange(1, 16) return rc
def DoConfigChange(self): SyntEditViewParent.DoConfigChange(self) tabSize = GetEditorOption("Tab Size", 4, 2) indentSize = GetEditorOption("Indent Size", 4, 2) bUseTabs = GetEditorOption("Use Tabs", 0) bSmartTabs = GetEditorOption("Smart Tabs", 1) ext = self.idle.IDLEExtension("AutoIndent") # Required extension. self.SCISetViewWS( GetEditorOption("View Whitespace", 0) ) self.SCISetViewEOL( GetEditorOption("View EOL", 0) ) self.SCISetIndentationGuides( GetEditorOption("View Indentation Guides", 0) ) if GetEditorOption("Right Edge Enabled", 0): mode = EDGE_BACKGROUND else: mode = EDGE_NONE self.SCISetEdgeMode(mode) self.SCISetEdgeColumn( GetEditorOption("Right Edge Column", 75) ) self.SCISetEdgeColor( GetEditorOption("Right Edge Color", win32api.RGB(0xef, 0xef, 0xef))) width = GetEditorOption("Marker Margin Width", 16) self.SCISetMarginWidthN(1, width) width = GetEditorOption("Folding Margin Width", 12) self.SCISetMarginWidthN(2, width) width = GetEditorOption("Line Number Margin Width", 0) self.SCISetMarginWidthN(0, width) self.bFolding = GetEditorOption("Enable Folding", 1) fold_flags = 0 self.SendScintilla(SCI_SETMODEVENTMASK, SC_MOD_CHANGEFOLD); if self.bFolding: if GetEditorOption("Fold Lines", 1): fold_flags = 16 self.SCISetProperty("fold", self.bFolding) self.SCISetFoldFlags(fold_flags) tt_color = GetEditorOption("Tab Timmy Color", win32api.RGB(0xff, 0, 0)) self.SendScintilla(SCI_INDICSETFORE, 1, tt_color) tt_use = GetEditorOption("Use Tab Timmy", 1) if tt_use: self.SCISetProperty("tab.timmy.whinge.level", "1") # Auto-indent has very complicated behaviour. In a nutshell, the only # way to get sensible behaviour from it is to ensure tabwidth != indentsize. # Further, usetabs will only ever go from 1->0, never 0->1. # This is _not_ the behaviour Pythonwin wants: # * Tab width is arbitary, so should have no impact on smarts. # * bUseTabs setting should reflect how new files are created, and # if Smart Tabs disabled, existing files are edited # * If "Smart Tabs" is enabled, bUseTabs should have no bearing # for existing files (unless of course no context can be determined) # # So for smart tabs we configure the widget with completely dummy # values (ensuring tabwidth != indentwidth), ask it to guess, then # look at the values it has guessed, and re-configure if bSmartTabs: ext.config(usetabs=1, tabwidth=5, indentwidth=4) ext.set_indentation_params(1) if ext.indentwidth==5: # Either 5 literal spaces, or a single tab character. Assume a tab usetabs = 1 indentwidth = tabSize else: # Either Indented with spaces, and indent size has been guessed or # an empty file (or no context found - tough!) if self.GetTextLength()==0: # emtpy usetabs = bUseTabs indentwidth = indentSize else: # guessed. indentwidth = ext.indentwidth usetabs = 0 # Tab size can never be guessed - set at user preference. ext.config(usetabs=usetabs, indentwidth=indentwidth, tabwidth=tabSize) else: # Dont want smart-tabs - just set the options! ext.config(usetabs=bUseTabs, tabwidth=tabSize, indentwidth=indentSize) self.SCISetIndent(indentSize) self.SCISetTabWidth(tabSize)
def _AddEditorOption(self, idd, typ, optionName, defaultVal): self.AddDDX(idd, optionName, typ) self[optionName] = GetEditorOption(optionName, defaultVal) self.autooptions.append((optionName, defaultVal))
def FinalizeViewCreation(self, view): ParentEditorDocument.FinalizeViewCreation(self, view) if view == self.GetFirstView(): self._DocumentStateChanged() if view.bFolding and GetEditorOption("Fold On Open", 0): view.FoldTopLevelEvent()
class EditorDocumentBase(ParentEditorDocument): def __init__(self, template): self.bAutoReload = GetEditorOption("Auto Reload", 1) self.bDeclinedReload = 0 # Has the user declined to reload. self.fileStat = None self.bReportedFileNotFound = 0 # what sort of bak file should I create. # default to write to %temp%/bak/filename.ext self.bakFileType = GetEditorOption("Backup Type", BAK_DOT_BAK_BAK_DIR) self.watcherThread = FileWatchingThread(self) self.watcherThread.CreateThread() # Should I try and use VSS integration? self.scModuleName = GetEditorOption("Source Control Module", "") self.scModule = None # Loaded when first used. ParentEditorDocument.__init__(self, template, template.CreateWin32uiDocument()) def OnCloseDocument(self): self.watcherThread.SignalStop() return self._obj_.OnCloseDocument() # def OnOpenDocument(self, name): # rc = ParentEditorDocument.OnOpenDocument(self, name) # self.GetFirstView()._SetLoadedText(self.text) # self._DocumentStateChanged() # return rc def OnSaveDocument(self, fileName): win32ui.SetStatusText("Saving file...", 1) # rename to bak if required. dir, basename = os.path.split(fileName) if self.bakFileType == BAK_DOT_BAK: bakFileName = dir + "\\" + os.path.splitext(basename)[0] + ".bak" elif self.bakFileType == BAK_DOT_BAK_TEMP_DIR: bakFileName = ( win32api.GetTempPath() + "\\" + os.path.splitext(basename)[0] + ".bak" ) elif self.bakFileType == BAK_DOT_BAK_BAK_DIR: tempPath = os.path.join(win32api.GetTempPath(), "bak") try: os.mkdir(tempPath, 0) except os.error: pass bakFileName = os.path.join(tempPath, basename) try: os.unlink(bakFileName) # raise NameError if no bakups wanted. except (os.error, NameError): pass try: # Do a copy as it might be on different volumes, # and the file may be a hard-link, causing the link # to follow the backup. shutil.copy2(fileName, bakFileName) except (os.error, NameError, IOError): pass try: self.SaveFile(fileName) except IOError as details: win32ui.MessageBox("Error - could not save file\r\n\r\n%s" % details) return 0 except (UnicodeEncodeError, LookupError) as details: rc = win32ui.MessageBox( "Encoding failed: \r\n%s" % details + "\r\nPlease add desired source encoding as first line of file, eg \r\n" + "# -*- coding: mbcs -*-\r\n\r\n" + "If you continue, the file will be saved as binary and will\r\n" + "not be valid in the declared encoding.\r\n\r\n" + "Save the file as binary with an invalid encoding?", "File save failed", win32con.MB_YESNO | win32con.MB_DEFBUTTON2, ) if rc == win32con.IDYES: try: self.SaveFile(fileName, encoding="latin-1") except IOError as details: win32ui.MessageBox( "Error - could not save file\r\n\r\n%s" % details ) return 0 else: return 0 self.SetModifiedFlag(0) # No longer dirty self.bDeclinedReload = 0 # They probably want to know if it changes again! win32ui.AddToRecentFileList(fileName) self.SetPathName(fileName) win32ui.SetStatusText("Ready") self._DocumentStateChanged() return 1 def FinalizeViewCreation(self, view): ParentEditorDocument.FinalizeViewCreation(self, view) if view == self.GetFirstView(): self._DocumentStateChanged() if view.bFolding and GetEditorOption("Fold On Open", 0): view.FoldTopLevelEvent() def HookViewNotifications(self, view): ParentEditorDocument.HookViewNotifications(self, view) # Support for reloading the document from disk - presumably after some # external application has modified it (or possibly source control has # checked it out. def ReloadDocument(self): """Reloads the document from disk. Assumes the file has been saved and user has been asked if necessary - it just does it! """ win32ui.SetStatusText("Reloading document. Please wait...", 1) self.SetModifiedFlag(0) # Loop over all views, saving their state, then reload the document views = self.GetAllViews() states = [] for view in views: try: info = view._PrepareUserStateChange() except AttributeError: # Not our editor view? info = None states.append(info) self.OnOpenDocument(self.GetPathName()) for view, info in zip(views, states): if info is not None: view._EndUserStateChange(info) self._DocumentStateChanged() win32ui.SetStatusText("Document reloaded.") # Reloading the file def CheckExternalDocumentUpdated(self): if self.bDeclinedReload or not self.GetPathName(): return try: newstat = os.stat(self.GetPathName()) except os.error as exc: if not self.bReportedFileNotFound: print( "The file '%s' is open for editing, but\nchecking it for changes caused the error: %s" % (self.GetPathName(), exc.strerror) ) self.bReportedFileNotFound = 1 return if self.bReportedFileNotFound: print( "The file '%s' has re-appeared - continuing to watch for changes..." % (self.GetPathName(),) ) self.bReportedFileNotFound = ( 0 # Once found again we want to start complaining. ) changed = ( (self.fileStat is None) or self.fileStat[0] != newstat[0] or self.fileStat[6] != newstat[6] or self.fileStat[8] != newstat[8] or self.fileStat[9] != newstat[9] ) if changed: question = None if self.IsModified(): question = ( "%s\r\n\r\nThis file has been modified outside of the source editor.\r\nDo you want to reload it and LOSE THE CHANGES in the source editor?" % self.GetPathName() ) mbStyle = win32con.MB_YESNO | win32con.MB_DEFBUTTON2 # Default to "No" else: if not self.bAutoReload: question = ( "%s\r\n\r\nThis file has been modified outside of the source editor.\r\nDo you want to reload it?" % self.GetPathName() ) mbStyle = win32con.MB_YESNO # Default to "Yes" if question: rc = win32ui.MessageBox(question, None, mbStyle) if rc != win32con.IDYES: self.bDeclinedReload = 1 return self.ReloadDocument() def _DocumentStateChanged(self): """Called whenever the documents state (on disk etc) has been changed by the editor (eg, as the result of a save operation) """ if self.GetPathName(): try: self.fileStat = os.stat(self.GetPathName()) except os.error: self.fileStat = None else: self.fileStat = None self.watcherThread._DocumentStateChanged() self._UpdateUIForState() self._ApplyOptionalToViews("_UpdateUIForState") self._ApplyOptionalToViews("SetReadOnly", self._IsReadOnly()) self._ApplyOptionalToViews("SCISetSavePoint") # Allow the debugger to reset us too. import pywin.debugger if pywin.debugger.currentDebugger is not None: pywin.debugger.currentDebugger.UpdateDocumentLineStates(self) # Read-only document support - make it obvious to the user # that the file is read-only. def _IsReadOnly(self): return self.fileStat is not None and (self.fileStat[0] & 128) == 0 def _UpdateUIForState(self): """Change the title to reflect the state of the document - eg ReadOnly, Dirty, etc """ filename = self.GetPathName() if not filename: return # New file - nothing to do try: # This seems necessary so the internal state of the window becomes # "visible". without it, it is still shown, but certain functions # (such as updating the title) dont immediately work? self.GetFirstView().ShowWindow(win32con.SW_SHOW) title = win32ui.GetFileTitle(filename) except win32ui.error: title = filename if self._IsReadOnly(): title = title + " (read-only)" self.SetTitle(title) def MakeDocumentWritable(self): pretend_ss = 0 # Set to 1 to test this without source safe :-) if not self.scModuleName and not pretend_ss: # No Source Control support. win32ui.SetStatusText( "Document is read-only, and no source-control system is configured" ) win32api.MessageBeep() return 0 # We have source control support - check if the user wants to use it. msg = "Would you like to check this file out?" defButton = win32con.MB_YESNO if self.IsModified(): msg = msg + "\r\n\r\nALL CHANGES IN THE EDITOR WILL BE LOST" defButton = win32con.MB_YESNO if win32ui.MessageBox(msg, None, defButton) != win32con.IDYES: return 0 if pretend_ss: print("We are only pretending to check it out!") win32api.SetFileAttributes( self.GetPathName(), win32con.FILE_ATTRIBUTE_NORMAL ) self.ReloadDocument() return 1 # Now call on the module to do it. if self.scModule is None: try: self.scModule = __import__(self.scModuleName) for part in self.scModuleName.split(".")[1:]: self.scModule = getattr(self.scModule, part) except: traceback.print_exc() print("Error loading source control module.") return 0 if self.scModule.CheckoutFile(self.GetPathName()): self.ReloadDocument() return 1 return 0 def CheckMakeDocumentWritable(self): if self._IsReadOnly(): return self.MakeDocumentWritable() return 1 def SaveModified(self): # Called as the document is closed. If we are about # to prompt for a save, bring the document to the foreground. if self.IsModified(): frame = self.GetFirstView().GetParentFrame() try: frame.MDIActivate() frame.AutoRestore() except: print("Could not bring document to foreground") return self._obj_.SaveModified()
class EditorDocumentBase(ParentEditorDocument): def __init__(self, template): self.bAutoReload = GetEditorOption("Auto Reload", 1) self.bDeclinedReload = 0 # Has the user declined to reload. self.fileStat = None self.bReportedFileNotFound = 0 # what sort of bak file should I create. # default to write to %temp%/bak/filename.ext self.bakFileType=GetEditorOption("Backup Type", BAK_DOT_BAK_BAK_DIR) self.watcherThread = FileWatchingThread(self) self.watcherThread.CreateThread() # Should I try and use VSS integration? self.scModuleName=GetEditorOption("Source Control Module", "") self.scModule = None # Loaded when first used. ParentEditorDocument.__init__(self, template, template.CreateWin32uiDocument()) def OnCloseDocument(self ): self.watcherThread.SignalStop() return self._obj_.OnCloseDocument() # def OnOpenDocument(self, name): # rc = ParentEditorDocument.OnOpenDocument(self, name) # self.GetFirstView()._SetLoadedText(self.text) # self._DocumentStateChanged() # return rc def OnSaveDocument( self, fileName ): win32ui.SetStatusText("Saving file...",1) # rename to bak if required. dir, basename = os.path.split(fileName) if self.bakFileType==BAK_DOT_BAK: bakFileName=dir+'\\'+os.path.splitext(basename)[0]+'.bak' elif self.bakFileType==BAK_DOT_BAK_TEMP_DIR: bakFileName=win32api.GetTempPath()+'\\'+os.path.splitext(basename)[0]+'.bak' elif self.bakFileType==BAK_DOT_BAK_BAK_DIR: tempPath=os.path.join(win32api.GetTempPath(),'bak') try: os.mkdir(tempPath,0) except os.error: pass bakFileName=os.path.join(tempPath,basename) try: os.unlink(bakFileName) # raise NameError if no bakups wanted. except (os.error, NameError): pass try: # Do a copy as it might be on different volumes, # and the file may be a hard-link, causing the link # to follow the backup. shutil.copy2(fileName, bakFileName) except (os.error, NameError, IOError): pass try: self.SaveFile(fileName) except IOError as details: win32ui.MessageBox("Error - could not save file\r\n\r\n%s"%details) return 0 except (UnicodeEncodeError, LookupError) as details: rc = win32ui.MessageBox("Encoding failed: \r\n%s"%details + '\r\nPlease add desired source encoding as first line of file, eg \r\n' + '# -*- coding: mbcs -*-\r\n\r\n' + 'If you continue, the file will be saved as binary and will\r\n' + 'not be valid in the declared encoding.\r\n\r\n' + 'Save the file as binary with an invalid encoding?', "File save failed", win32con.MB_YESNO | win32con.MB_DEFBUTTON2) if rc==win32con.IDYES: try: self.SaveFile(fileName, encoding="latin-1") except IOError as details: win32ui.MessageBox("Error - could not save file\r\n\r\n%s"%details) return 0 else: return 0 self.SetModifiedFlag(0) # No longer dirty self.bDeclinedReload = 0 # They probably want to know if it changes again! win32ui.AddToRecentFileList(fileName) self.SetPathName(fileName) win32ui.SetStatusText("Ready") self._DocumentStateChanged() return 1 def FinalizeViewCreation(self, view): ParentEditorDocument.FinalizeViewCreation(self, view) if view == self.GetFirstView(): self._DocumentStateChanged() if view.bFolding and GetEditorOption("Fold On Open", 0): view.FoldTopLevelEvent() def HookViewNotifications(self, view): ParentEditorDocument.HookViewNotifications(self, view) # Support for reloading the document from disk - presumably after some # external application has modified it (or possibly source control has # checked it out. def ReloadDocument(self): """Reloads the document from disk. Assumes the file has been saved and user has been asked if necessary - it just does it! """ win32ui.SetStatusText("Reloading document. Please wait...", 1) self.SetModifiedFlag(0) # Loop over all views, saving their state, then reload the document views = self.GetAllViews() states = [] for view in views: try: info = view._PrepareUserStateChange() except AttributeError: # Not our editor view? info = None states.append(info) self.OnOpenDocument(self.GetPathName()) for view, info in zip(views, states): if info is not None: view._EndUserStateChange(info) self._DocumentStateChanged() win32ui.SetStatusText("Document reloaded.") # Reloading the file def CheckExternalDocumentUpdated(self): if self.bDeclinedReload or not self.GetPathName(): return try: newstat = os.stat(self.GetPathName()) except os.error as exc: if not self.bReportedFileNotFound: print("The file '%s' is open for editing, but\nchecking it for changes caused the error: %s" % (self.GetPathName(), exc.strerror)) self.bReportedFileNotFound = 1 return if self.bReportedFileNotFound: print("The file '%s' has re-appeared - continuing to watch for changes..." % (self.GetPathName(),)) self.bReportedFileNotFound = 0 # Once found again we want to start complaining. changed = (self.fileStat is None) or \ self.fileStat[0] != newstat[0] or \ self.fileStat[6] != newstat[6] or \ self.fileStat[8] != newstat[8] or \ self.fileStat[9] != newstat[9] if changed: question = None if self.IsModified(): question = "%s\r\n\r\nThis file has been modified outside of the source editor.\r\nDo you want to reload it and LOSE THE CHANGES in the source editor?" % self.GetPathName() mbStyle = win32con.MB_YESNO | win32con.MB_DEFBUTTON2 # Default to "No" else: if not self.bAutoReload: question = "%s\r\n\r\nThis file has been modified outside of the source editor.\r\nDo you want to reload it?" % self.GetPathName() mbStyle = win32con.MB_YESNO # Default to "Yes" if question: rc = win32ui.MessageBox(question, None, mbStyle) if rc!=win32con.IDYES: self.bDeclinedReload = 1 return self.ReloadDocument() def _DocumentStateChanged(self): """Called whenever the documents state (on disk etc) has been changed by the editor (eg, as the result of a save operation) """ if self.GetPathName(): try: self.fileStat = os.stat(self.GetPathName()) except os.error: self.fileStat = None else: self.fileStat = None self.watcherThread._DocumentStateChanged() self._UpdateUIForState() self._ApplyOptionalToViews("_UpdateUIForState") self._ApplyOptionalToViews("SetReadOnly", self._IsReadOnly()) self._ApplyOptionalToViews("SCISetSavePoint") # Allow the debugger to reset us too. import pywin.debugger if pywin.debugger.currentDebugger is not None: pywin.debugger.currentDebugger.UpdateDocumentLineStates(self) # Read-only document support - make it obvious to the user # that the file is read-only. def _IsReadOnly(self): return self.fileStat is not None and (self.fileStat[0] & 128)==0 def _UpdateUIForState(self): """Change the title to reflect the state of the document - eg ReadOnly, Dirty, etc """ filename = self.GetPathName() if not filename: return # New file - nothing to do try: # This seems necessary so the internal state of the window becomes # "visible". without it, it is still shown, but certain functions # (such as updating the title) dont immediately work? self.GetFirstView().ShowWindow(win32con.SW_SHOW) title = win32ui.GetFileTitle(filename) except win32ui.error: title = filename if self._IsReadOnly(): title = title + " (read-only)" self.SetTitle(title) def MakeDocumentWritable(self): pretend_ss = 0 # Set to 1 to test this without source safe :-) if not self.scModuleName and not pretend_ss: # No Source Control support. win32ui.SetStatusText("Document is read-only, and no source-control system is configured") win32api.MessageBeep() return 0 # We have source control support - check if the user wants to use it. msg = "Would you like to check this file out?" defButton = win32con.MB_YESNO if self.IsModified(): msg = msg + "\r\n\r\nALL CHANGES IN THE EDITOR WILL BE LOST" defButton = win32con.MB_YESNO if win32ui.MessageBox(msg, None, defButton)!=win32con.IDYES: return 0 if pretend_ss: print("We are only pretending to check it out!") win32api.SetFileAttributes(self.GetPathName(), win32con.FILE_ATTRIBUTE_NORMAL) self.ReloadDocument() return 1 # Now call on the module to do it. if self.scModule is None: try: self.scModule = __import__(self.scModuleName) for part in self.scModuleName.split('.')[1:]: self.scModule = getattr(self.scModule, part) except: traceback.print_exc() print("Error loading source control module.") return 0 if self.scModule.CheckoutFile(self.GetPathName()): self.ReloadDocument() return 1 return 0 def CheckMakeDocumentWritable(self): if self._IsReadOnly(): return self.MakeDocumentWritable() return 1 def SaveModified(self): # Called as the document is closed. If we are about # to prompt for a save, bring the document to the foreground. if self.IsModified(): frame = self.GetFirstView().GetParentFrame() try: frame.MDIActivate() frame.AutoRestore() except: print("Could not bring document to foreground") return self._obj_.SaveModified()