eric6/QScintilla/MiniEditor.py

changeset 7690
a59680062837
parent 7635
0cdead130a81
child 7730
20b05e846148
--- 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)

eric ide

mercurial