Mon, 13 Feb 2023 17:52:26 +0100
Modified Editor and view managers to be usable with files loaded from a connected device and (potentially) remote files.
--- a/src/eric7/Documentation/Source/eric7.QScintilla.Editor.html Mon Feb 13 17:51:03 2023 +0100 +++ b/src/eric7/Documentation/Source/eric7.QScintilla.Editor.html Mon Feb 13 17:52:26 2023 +0100 @@ -743,10 +743,6 @@ <td>Private method to configure the eol mode of the editor.</td> </tr> <tr> -<td><a href="#Editor.__setFileName">__setFileName</a></td> -<td>Private method to set the file name of the current file.</td> -</tr> -<tr> <td><a href="#Editor.__setLineMarkerColours">__setLineMarkerColours</a></td> <td>Private method to set the line marker colours.</td> </tr> @@ -983,6 +979,10 @@ <td>Public method to check dirty status and open a message window.</td> </tr> <tr> +<td><a href="#Editor.checkReadOnly">checkReadOnly</a></td> +<td>Public method to check the 'read only' state.</td> +</tr> +<tr> <td><a href="#Editor.checkSpelling">checkSpelling</a></td> <td>Public slot to perform an interactive spell check of the document.</td> </tr> @@ -1003,6 +1003,10 @@ <td>Public method to clear a breakpoint.</td> </tr> <tr> +<td><a href="#Editor.clearChangeMarkers">clearChangeMarkers</a></td> +<td>Public method to clear all change markers.</td> +</tr> +<tr> <td><a href="#Editor.clearFlakesWarnings">clearFlakesWarnings</a></td> <td>Public slot to clear all pyflakes warnings.</td> </tr> @@ -1379,6 +1383,10 @@ <td>Public method to check, if a last edit position is available.</td> </tr> <tr> +<td><a href="#Editor.isLocalFile">isLocalFile</a></td> +<td>Public method to check, if the editor contains a local file.</td> +</tr> +<tr> <td><a href="#Editor.isMicroPythonFile">isMicroPythonFile</a></td> <td>Public method to return a flag indicating a MicroPython file.</td> </tr> @@ -1623,6 +1631,10 @@ <td>Public method to set the automatic spell checking.</td> </tr> <tr> +<td><a href="#Editor.setFileName">setFileName</a></td> +<td>Public method to set the file name of the current file.</td> +</tr> +<tr> <td><a href="#Editor.setHighlight">setHighlight</a></td> <td>Public method to set a text highlight.</td> </tr> @@ -3712,20 +3724,6 @@ <p> Private method to configure the eol mode of the editor. </p> -<a NAME="Editor.__setFileName" ID="Editor.__setFileName"></a> -<h4>Editor.__setFileName</h4> -<b>__setFileName</b>(<i>name</i>) - -<p> - Private method to set the file name of the current file. -</p> -<dl> - -<dt><i>name</i> (str)</dt> -<dd> -name of the current file -</dd> -</dl> <a NAME="Editor.__setLineMarkerColours" ID="Editor.__setLineMarkerColours"></a> <h4>Editor.__setLineMarkerColours</h4> <b>__setLineMarkerColours</b>(<i></i>) @@ -4385,6 +4383,25 @@ flag indicating successful reset of the dirty flag (boolean) </dd> </dl> +<a NAME="Editor.checkReadOnly" ID="Editor.checkReadOnly"></a> +<h4>Editor.checkReadOnly</h4> +<b>checkReadOnly</b>(<i></i>) + +<p> + Public method to check the 'read only' state. +</p> +<dl> +<dt>Return:</dt> +<dd> +flag indicate a 'read only' state +</dd> +</dl> +<dl> +<dt>Return Type:</dt> +<dd> +bool +</dd> +</dl> <a NAME="Editor.checkSpelling" ID="Editor.checkSpelling"></a> <h4>Editor.checkSpelling</h4> <b>checkSpelling</b>(<i></i>) @@ -4431,6 +4448,13 @@ line number of the breakpoint (integer) </dd> </dl> +<a NAME="Editor.clearChangeMarkers" ID="Editor.clearChangeMarkers"></a> +<h4>Editor.clearChangeMarkers</h4> +<b>clearChangeMarkers</b>(<i></i>) + +<p> + Public method to clear all change markers. +</p> <a NAME="Editor.clearFlakesWarnings" ID="Editor.clearFlakesWarnings"></a> <h4>Editor.clearFlakesWarnings</h4> <b>clearFlakesWarnings</b>(<i></i>) @@ -5881,6 +5905,25 @@ flag indicating availability (boolean) </dd> </dl> +<a NAME="Editor.isLocalFile" ID="Editor.isLocalFile"></a> +<h4>Editor.isLocalFile</h4> +<b>isLocalFile</b>(<i></i>) + +<p> + Public method to check, if the editor contains a local file. +</p> +<dl> +<dt>Return:</dt> +<dd> +flag indicating a local file +</dd> +</dl> +<dl> +<dt>Return Type:</dt> +<dd> +bool +</dd> +</dl> <a NAME="Editor.isMicroPythonFile" ID="Editor.isMicroPythonFile"></a> <h4>Editor.isMicroPythonFile</h4> <b>isMicroPythonFile</b>(<i></i>) @@ -6564,6 +6607,20 @@ <p> Public method to set the automatic spell checking. </p> +<a NAME="Editor.setFileName" ID="Editor.setFileName"></a> +<h4>Editor.setFileName</h4> +<b>setFileName</b>(<i>name</i>) + +<p> + Public method to set the file name of the current file. +</p> +<dl> + +<dt><i>name</i> (str)</dt> +<dd> +name of the current file +</dd> +</dl> <a NAME="Editor.setHighlight" ID="Editor.setHighlight"></a> <h4>Editor.setHighlight</h4> <b>setHighlight</b>(<i>startLine, startIndex, endLine, endIndex</i>)
--- a/src/eric7/Documentation/Source/eric7.ViewManager.ViewManager.html Mon Feb 13 17:51:03 2023 +0100 +++ b/src/eric7/Documentation/Source/eric7.ViewManager.ViewManager.html Mon Feb 13 17:52:26 2023 +0100 @@ -1007,13 +1007,17 @@ </tr> <tr> <td><a href="#ViewManager.newEditor">newEditor</a></td> -<td>Public slot to generate a new empty editor.</td> +<td>Public method to generate a new empty editor.</td> </tr> <tr> <td><a href="#ViewManager.newEditorView">newEditorView</a></td> <td>Public method to create a new editor displaying the given document.</td> </tr> <tr> +<td><a href="#ViewManager.newEditorWithText">newEditorWithText</a></td> +<td>Public method to generate a new editor with a given text and associated file name.</td> +</tr> +<tr> <td><a href="#ViewManager.nextSplit">nextSplit</a></td> <td>Public slot used to move to the next split.</td> </tr> @@ -3244,8 +3248,8 @@ </dd> <dt><i>indexes</i> (tuple of two int)</dt> <dd> -of the editor, first the split view index, second the - index within the view +tuple containing the indexes of the editor, first the split + view index, second the index within the view </dd> </dl> <dl> @@ -3765,8 +3769,20 @@ <b>newEditor</b>(<i></i>) <p> - Public slot to generate a new empty editor. -</p> + Public method to generate a new empty editor. +</p> +<dl> +<dt>Return:</dt> +<dd> +reference to the new editor +</dd> +</dl> +<dl> +<dt>Return Type:</dt> +<dd> +Editor +</dd> +</dl> <a NAME="ViewManager.newEditorView" ID="ViewManager.newEditorView"></a> <h4>ViewManager.newEditorView</h4> <b>newEditorView</b>(<i>fn, caller, filetype="", indexes=None</i>) @@ -3806,6 +3822,29 @@ Editor </dd> </dl> +<a NAME="ViewManager.newEditorWithText" ID="ViewManager.newEditorWithText"></a> +<h4>ViewManager.newEditorWithText</h4> +<b>newEditorWithText</b>(<i>text, language="", fileName=""</i>) + +<p> + Public method to generate a new editor with a given text and associated file + name. +</p> +<dl> + +<dt><i>text</i> (str)</dt> +<dd> +text for the editor +</dd> +<dt><i>language</i> (str (optional))</dt> +<dd> +source language (defaults to "") +</dd> +<dt><i>fileName</i> (str (optional))</dt> +<dd> +associated file name (defaults to "") +</dd> +</dl> <a NAME="ViewManager.nextSplit" ID="ViewManager.nextSplit"></a> <h4>ViewManager.nextSplit</h4> <b>nextSplit</b>(<i></i>)
--- a/src/eric7/Plugins/ViewManagerPlugins/Listspace/Listspace.py Mon Feb 13 17:51:03 2023 +0100 +++ b/src/eric7/Plugins/ViewManagerPlugins/Listspace/Listspace.py Mon Feb 13 17:52:26 2023 +0100 @@ -487,7 +487,7 @@ editor.setNoName(noName) else: txt = os.path.basename(fn) - if not os.access(fn, os.W_OK): + if editor.checkReadOnly(): txt = self.tr("{0} (ro)").format(txt) itm = QListWidgetItem(txt) itm.setToolTip(fn) @@ -623,7 +623,7 @@ currentRow = self.viewlist.currentRow() index = self.editors.index(editor) txt = os.path.basename(newName) - if not os.access(newName, os.W_OK): + if editor.checkReadOnly(): txt = self.tr("{0} (ro)").format(txt) itm = self.viewlist.item(index) if itm:
--- a/src/eric7/Plugins/ViewManagerPlugins/Tabview/Tabview.py Mon Feb 13 17:51:03 2023 +0100 +++ b/src/eric7/Plugins/ViewManagerPlugins/Tabview/Tabview.py Mon Feb 13 17:52:26 2023 +0100 @@ -488,7 +488,7 @@ maxFileNameChars = Preferences.getUI("TabViewManagerFilenameLength") if len(txt) > maxFileNameChars: txt = "...{0}".format(txt[-maxFileNameChars:]) - if editor.isReadOnly(): + if editor.checkReadOnly(): txt = self.tr("{0} (ro)").format(txt) assembly = editor.parent() @@ -1052,7 +1052,7 @@ txt = ericApp().getObject("Project").getRelativePath(fn) if len(txt) > self.maxFileNameChars: txt = "...{0}".format(txt[-self.maxFileNameChars :]) - if not os.access(fn, os.W_OK): + if editor.checkReadOnly(): txt = self.tr("{0} (ro)").format(txt) if addNext: index = self.currentTabWidget.currentIndex() + 1 @@ -1107,7 +1107,7 @@ txt = ericApp().getObject("Project").getRelativePath(fn) if len(txt) > self.maxFileNameChars: txt = "...{0}".format(txt[-self.maxFileNameChars :]) - if not os.access(fn, os.W_OK): + if editor.checkReadOnly(): txt = self.tr("{0} (ro)").format(txt) nindex = tabWidget.insertWidget(index, win, txt) tabWidget.setTabToolTip(nindex, fn) @@ -1498,7 +1498,7 @@ txt = ericApp().getObject("Project").getRelativePath(fn) if len(txt) > self.maxFileNameChars: txt = "...{0}".format(txt[-self.maxFileNameChars :]) - if not os.access(fn, os.W_OK): + if editor.checkReadOnly(): txt = self.tr("{0} (ro)").format(txt) tabWidget.setTabText(index, txt)
--- a/src/eric7/QScintilla/Editor.py Mon Feb 13 17:51:03 2023 +0100 +++ b/src/eric7/QScintilla/Editor.py Mon Feb 13 17:52:26 2023 +0100 @@ -227,7 +227,7 @@ self.dbs = dbs self.taskViewer = tv - self.__setFileName(fn) + self.setFileName(fn) self.vm = vm self.filetype = filetype self.filetypeByFlag = False @@ -404,37 +404,39 @@ if not Utilities.MimeTypes.isTextFile(self.fileName): raise OSError() - fileSizeKB = pathlib.Path(self.fileName).stat().st_size // 1024 - if fileSizeKB > Preferences.getEditor("RejectFilesize"): - EricMessageBox.warning( - None, - self.tr("Open File"), - self.tr( - "<p>The size of the file <b>{0}</b> is <b>{1} KB</b> and" - " exceeds the configured limit of <b>{2} KB</b>. It will" - " not be opened!</p>" - ).format( - self.fileName, - fileSizeKB, - Preferences.getEditor("RejectFilesize"), - ), - ) - raise OSError() - elif fileSizeKB > Preferences.getEditor("WarnFilesize"): - res = EricMessageBox.yesNo( - None, - self.tr("Open File"), - self.tr( - """<p>The size of the file <b>{0}</b>""" - """ is <b>{1} KB</b>.""" - """ Do you really want to load it?</p>""" - ).format(self.fileName, fileSizeKB), - icon=EricMessageBox.Warning, - ) - if not res: + if self.isLocalFile(): + fileSizeKB = pathlib.Path(self.fileName).stat().st_size // 1024 + if fileSizeKB > Preferences.getEditor("RejectFilesize"): + EricMessageBox.warning( + None, + self.tr("Open File"), + self.tr( + "<p>The size of the file <b>{0}</b> is <b>{1} KB</b> and" + " exceeds the configured limit of <b>{2} KB</b>. It will" + " not be opened!</p>" + ).format( + self.fileName, + fileSizeKB, + Preferences.getEditor("RejectFilesize"), + ), + ) raise OSError() - - self.readFile(self.fileName, True) + elif fileSizeKB > Preferences.getEditor("WarnFilesize"): + res = EricMessageBox.yesNo( + None, + self.tr("Open File"), + self.tr( + """<p>The size of the file <b>{0}</b>""" + """ is <b>{1} KB</b>.""" + """ Do you really want to load it?</p>""" + ).format(self.fileName, fileSizeKB), + icon=EricMessageBox.Warning, + ) + if not res: + raise OSError() + + self.readFile(self.fileName, True) + self.__bindLexer(self.fileName) self.__bindCompleter(self.fileName) self.checkSyntax() @@ -611,9 +613,9 @@ self.SCN_ZOOM.connect(self.__markerMap.update) self.__markerMap.update() - def __setFileName(self, name): - """ - Private method to set the file name of the current file. + def setFileName(self, name): + """ + Public method to set the file name of the current file. @param name name of the current file @type str @@ -625,6 +627,15 @@ else: self.__fileNameExtension = "" + def isLocalFile(self): + """ + Public method to check, if the editor contains a local file. + + @return flag indicating a local file + @rtype bool + """ + return not self.fileName.startswith(("device:", "remote:")) + def __registerImages(self): """ Private method to register images for autocompletion lists. @@ -3111,6 +3122,12 @@ self.changeMarkersUpdated.emit(self) self.__markerMap.update() + def clearChangeMarkers(self): + """ + Public method to clear all change markers. + """ + self.__reinitOnlineChangeTrace() + def getChangeLines(self): """ Public method to get the lines containing a change. @@ -3221,7 +3238,7 @@ self, self.tr("File Modified"), self.tr("<p>The file <b>{0}</b> has unsaved changes.</p>").format(fn), - self.saveFile, + self.saveFile if self.isLocalFile() else None, ) if res: self.vm.setEditorName(self, self.fileName) @@ -3493,8 +3510,9 @@ @param path directory to save the file in (string) @return flag indicating success (boolean) """ - if not saveas and not self.isModified(): - return False # do nothing if text wasn't changed + if not saveas and (not self.isModified() or not self.isLocalFile()): + # do nothing if text wasn't changed or is not a local file + return False newName = None if saveas or self.fileName == "": @@ -3524,7 +3542,7 @@ if self.writeFile(fn): if saveas: self.__clearBreakpoints(self.fileName) - self.__setFileName(fn) + self.setFileName(fn) self.setModified(False) self.setReadOnly(False) self.setWindowTitle(self.fileName) @@ -3580,7 +3598,7 @@ """ self.__clearBreakpoints(fn) - self.__setFileName(fn) + self.setFileName(fn) self.setWindowTitle(self.fileName) self.__loadEditorConfig() @@ -7251,7 +7269,7 @@ if self.windowState() == Qt.WindowState.WindowMinimized else self.fileName ) - if self.isReadOnly(): + if self.checkReadOnly(): cap = self.tr("{0} (ro)").format(cap) self.setWindowTitle(cap) @@ -7394,10 +7412,10 @@ @param bForce True to force change, False to only update and emit signal if there was an attribute change. """ - if self.fileName == "": + if self.fileName == "" or not self.isLocalFile(): return - readOnly = not os.access(self.fileName, os.W_OK) or self.isReadOnly() + readOnly = self.checkReadOnly() if not bForce and (readOnly == self.isReadOnly()): return @@ -7408,6 +7426,18 @@ self.setWindowTitle(cap) self.captionChanged.emit(cap, self) + def checkReadOnly(self): + """ + Public method to check the 'read only' state. + + @return flag indicate a 'read only' state + @rtype bool + """ + return ( + (self.isLocalFile() and not os.access(self.fileName, os.W_OK)) + or self.isReadOnly() + ) + def refresh(self): """ Public slot to refresh the editor contents. @@ -8785,7 +8815,7 @@ """ editorConfig = {} - if fileName: + if fileName and self.isLocalFile(): try: editorConfig = editorconfig.get_properties(fileName) except editorconfig.EditorConfigError:
--- a/src/eric7/ViewManager/ViewManager.py Mon Feb 13 17:51:03 2023 +0100 +++ b/src/eric7/ViewManager/ViewManager.py Mon Feb 13 17:52:26 2023 +0100 @@ -5402,7 +5402,7 @@ "ViewManager", """<p>The file <b>{0}</b> has unsaved changes.</p>""", ).format(fn), - editor.saveFile, + editor.saveFile if editor.isLocalFile() else None, ) if res: self.setEditorName(editor, editor.getFileName()) @@ -5938,8 +5938,8 @@ @param addNext flag indicating that if a new editor needs to be created, it should be added next to the current editor @type bool - @param indexes of the editor, first the split view index, second the - index within the view + @param indexes tuple containing the indexes of the editor, first the split + view index, second the index within the view @type tuple of two int @return tuple of two values giving a flag indicating a new window creation and a reference to the editor displaying this file @@ -6161,7 +6161,10 @@ def newEditor(self): """ - Public slot to generate a new empty editor. + Public method to generate a new empty editor. + + @return reference to the new editor + @rtype Editor """ from eric7.QScintilla.EditorAssembly import EditorAssembly @@ -6177,6 +6180,38 @@ self.editorOpened.emit("") self.editorOpenedEd.emit(editor) + return editor + + def newEditorWithText(self, text, language="", fileName=""): + """ + Public method to generate a new editor with a given text and associated file + name. + + @param text text for the editor + @type str + @param language source language (defaults to "") + @type str (optional) + @param fileName associated file name (defaults to "") + @type str (optional) + """ + from eric7.QScintilla.EditorAssembly import EditorAssembly + + assembly = EditorAssembly( + self.dbs, fileName, vm=self, filetype=language, tv=ericApp().getObject("TaskViewer") + ) + editor = assembly.getEditor() + self.editors.append(editor) + self.__connectEditor(editor) + self._addView(assembly, fileName) + self.__editorOpened() + self._checkActions(editor) + self.editorOpened.emit(fileName) + self.editorOpenedEd.emit(editor) + + editor.setText(text) + editor.setModified(False) + editor.clearChangeMarkers() + def printEditor(self, editor): """ Public slot to print an editor. @@ -7482,7 +7517,7 @@ (boolean) """ if editor is not None: - self.saveAct.setEnabled(editor.isModified()) + self.saveAct.setEnabled(editor.isModified() and editor.isLocalFile()) self.revertAct.setEnabled(editor.isModified()) self.undoAct.setEnabled(editor.isUndoAvailable())