diff -r 147236d850a4 -r a59680062837 eric6/QScintilla/MiniEditor.py --- a/eric6/QScintilla/MiniEditor.py Fri Sep 04 18:48:52 2020 +0200 +++ b/eric6/QScintilla/MiniEditor.py Fri Sep 04 18:50:43 2020 +0200 @@ -18,7 +18,7 @@ from PyQt5.QtGui import QCursor, QKeySequence, QPalette, QFont from PyQt5.QtWidgets import ( QWidget, QWhatsThis, QActionGroup, QDialog, QInputDialog, QApplication, - QMenu, QVBoxLayout, QLabel + QMenu, QVBoxLayout, QHBoxLayout, QLabel ) from PyQt5.QtPrintSupport import QPrinter, QPrintDialog, QAbstractPrintDialog from PyQt5.Qsci import QsciScintilla @@ -114,8 +114,20 @@ Class implementing a minimalistic editor for simple editing tasks. @signal editorSaved() emitted after the file has been saved + @signal languageChanged(str) emitted when the editors language was set. The + language is passed as a parameter. + @signal editorRenamed(str) emitted after the editor got a new name + (i.e. after a 'Save As') + @signal cursorLineChanged(int) emitted when the cursor line was changed + + @signal refreshed() dummy signal to emulate the Editor interface """ editorSaved = pyqtSignal() + languageChanged = pyqtSignal(str) + editorRenamed = pyqtSignal(str) + cursorLineChanged = pyqtSignal(int) + + refreshed = pyqtSignal() def __init__(self, filename="", filetype="", parent=None, name=None): """ @@ -139,6 +151,12 @@ self.__textEdit.setSearchIndicator = self.setSearchIndicator self.__textEdit.setUtf8(True) + self.getCursorPosition = self.__textEdit.getCursorPosition + self.text = self.__textEdit.text + + self.__curFile = filename + self.__lastLine = 0 + self.srHistory = { "search": [], "replace": [] @@ -147,10 +165,21 @@ self.__searchWidget = SearchReplaceWidget(False, self, self) self.__replaceWidget = SearchReplaceWidget(True, self, self) + from .EditorOutline import EditorOutlineView + self.__sourceOutline = EditorOutlineView(self, populate=False) + self.__sourceOutline.setMaximumWidth( + Preferences.getEditor("SourceOutlineWidth")) + + hlayout = QHBoxLayout() + hlayout.setContentsMargins(0, 0, 0, 0) + hlayout.setSpacing(1) + hlayout.addWidget(self.__textEdit) + hlayout.addWidget(self.__sourceOutline) + centralWidget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(1, 1, 1, 1) - layout.addWidget(self.__textEdit) + layout.addLayout(hlayout) layout.addWidget(self.__searchWidget) layout.addWidget(self.__replaceWidget) centralWidget.setLayout(layout) @@ -161,7 +190,6 @@ self.lexer_ = None self.apiLanguage = "" self.filetype = "" - self.__curFile = filename self.__loadEditorConfig(filename) @@ -189,6 +217,11 @@ self.__markOccurrencesTimer.timeout.connect(self.__markOccurrences) self.__markedText = "" + self.__changeTimer = QTimer(self) + self.__changeTimer.setSingleShot(True) + self.__changeTimer.setInterval(5 * 1000) + self.__textEdit.textChanged.connect(self.__resetChangeTimer) + self.__textEdit.textChanged.connect(self.__documentWasModified) self.__textEdit.modificationChanged.connect(self.__modificationChanged) self.__textEdit.cursorPositionChanged.connect( @@ -211,6 +244,16 @@ self.encoding = self.__getEditorConfig("DefaultEncoding") self.__checkActions() + + self.__sourceOutline.setActive(True) + self.__sourceOutline.setVisible( + self.__sourceOutline.isSupportedLanguage( + self.getLanguage() + ) + ) + self.__changeTimer.timeout.connect(self.__sourceOutline.repopulate) + self.languageChanged.connect(self.__editorChanged) + self.editorRenamed.connect(self.__editorChanged) def closeEvent(self, event): """ @@ -265,7 +308,11 @@ if not fileName: return False - return self.__saveFile(fileName) + result = self.__saveFile(fileName) + + self.editorRenamed.emit(fileName) + + return result def __saveCopy(self): """ @@ -2531,6 +2578,10 @@ if Preferences.getEditor("MarkOccurrencesEnabled"): self.__markOccurrencesTimer.stop() self.__markOccurrencesTimer.start() + + if self.__lastLine != line: + self.cursorLineChanged.emit(line) + self.__lastLine = line def __undo(self): """ @@ -2899,7 +2950,8 @@ """ if self.apiLanguage.startswith("Pygments|"): self.pygmentsSelAct.setText( - self.tr("Alternatives ({0})").format(self.getLanguage())) + self.tr("Alternatives ({0})").format( + self.getLanguage(normalized=False))) else: self.pygmentsSelAct.setText(self.tr("Alternatives")) @@ -2907,12 +2959,14 @@ """ Private method to select a specific pygments lexer. - @return name of the selected pygments lexer (string) + @return name of the selected pygments lexer + @rtype str """ from pygments.lexers import get_all_lexers lexerList = sorted(lex[0] for lex in get_all_lexers()) try: - lexerSel = lexerList.index(self.getLanguage()) + lexerSel = lexerList.index( + self.getLanguage(normalized=False, forPygments=True)) except ValueError: lexerSel = 0 lexerName, ok = QInputDialog.getItem( @@ -2968,6 +3022,8 @@ self.__textEdit.setPaper( Preferences.getEditorColour("EditAreaBackground")) + self.languageChanged.emit(self.apiLanguage) + def setLanguage(self, filename, initTextDisplay=True, pyname=""): """ Public method to set a lexer language. @@ -2986,20 +3042,43 @@ if initTextDisplay: self.__setTextDisplay() self.__setMargins() + + self.languageChanged.emit(self.apiLanguage) - def getLanguage(self): + def getLanguage(self, normalized=True, forPygments=False): """ Public method to retrieve the language of the editor. - @return language of the editor (string) + @param normalized flag indicating to normalize some Pygments + lexer names + @type bool + @param forPygments flag indicating to normalize some lexer + names for Pygments + @type bool + @return language of the editor + @rtype str """ if ( self.apiLanguage == "Guessed" or self.apiLanguage.startswith("Pygments|") ): - return self.lexer_.name() + lang = self.lexer_.name() + if normalized: + # adjust some Pygments lexer names + if lang in ("Python 2.x", "Python"): + lang = "Python3" + elif lang == "Protocol Buffer": + lang = "Protocol" + else: - return self.apiLanguage + lang = self.apiLanguage + if forPygments: + # adjust some names to Pygments lexer names + if lang == "Python3": + lang = "Python" + elif lang == "Protocol": + lang = "Protocol Buffer" + return lang def __checkLanguage(self): """ @@ -3055,7 +3134,16 @@ if pyname: self.apiLanguage = "Pygments|{0}".format(pyname) else: - self.apiLanguage = self.lexer_.language() + if language == "Protocol": + self.apiLanguage = language + else: + # Change API language for lexer where QScintilla reports + # an abbreviated name. + self.apiLanguage = self.lexer_.language() + if self.apiLanguage == "POV": + self.apiLanguage = "Povray" + elif self.apiLanguage == "PO": + self.apiLanguage = "Gettext" self.__textEdit.setLexer(self.lexer_) if self.lexer_.lexer() == "container" or self.lexer_.lexer() is None: self.__textEdit.SCN_STYLENEEDED.connect(self.__styleNeeded) @@ -3495,3 +3583,23 @@ return overrides[self.filetype][1] return None + + ####################################################################### + ## Methods supporting the outline view below + ####################################################################### + + def __resetChangeTimer(self): + """ + Private slot to reset the parse timer. + """ + self.__changeTimer.stop() + self.__changeTimer.start() + + def __editorChanged(self): + """ + Private slot handling changes of the editor language or file name. + """ + supported = self.__sourceOutline.isSupportedLanguage( + self.getLanguage()) + + self.__sourceOutline.setVisible(supported)