eric7/UI/Previewer.py

branch
eric7
changeset 8312
800c432b34c8
parent 8218
7c09585bd960
child 8318
962bce857696
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/UI/Previewer.py	Sat May 15 18:45:04 2021 +0200
@@ -0,0 +1,225 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a previewer widget for HTML, Markdown and ReST files.
+"""
+
+import os
+
+from PyQt5.QtCore import pyqtSlot, QTimer
+from PyQt5.QtWidgets import QStackedWidget
+
+import Preferences
+
+
+class Previewer(QStackedWidget):
+    """
+    Class implementing a previewer widget containing a stack of
+    specialized previewers.
+    """
+    def __init__(self, viewmanager, splitter, parent=None):
+        """
+        Constructor
+        
+        @param viewmanager reference to the viewmanager object (ViewManager)
+        @param splitter reference to the embedding splitter (QSplitter)
+        @param parent reference to the parent widget (QWidget)
+        """
+        super().__init__(parent)
+        
+        self.__vm = viewmanager
+        self.__splitter = splitter
+        
+        self.__firstShow = True
+        
+        self.__htmlPreviewer = None
+        self.__qssPreviewer = None
+        
+        # Don't update too often because the UI might become sluggish
+        self.__typingTimer = QTimer()
+        self.__typingTimer.setInterval(
+            Preferences.getEditor("PreviewRefreshWaitTimer"))   # default 500ms
+        self.__typingTimer.timeout.connect(self.__processEditor)
+        
+        self.__vm.editorChangedEd.connect(self.__editorChanged)
+        self.__vm.editorLanguageChanged.connect(self.__editorLanguageChanged)
+        self.__vm.editorTextChanged.connect(self.__editorTextChanged)
+
+        self.__vm.previewStateChanged.connect(self.__previewStateChanged)
+        
+        self.__splitter.splitterMoved.connect(self.__splitterMoved)
+        
+        self.hide()
+    
+    @pyqtSlot()
+    def preferencesChanged(self):
+        """
+        Public slot handling a change of preferences.
+        """
+        self.__typingTimer.setInterval(
+            Preferences.getEditor("PreviewRefreshWaitTimer"))
+    
+    def show(self):
+        """
+        Public method to show the preview widget.
+        """
+        super().show()
+        if self.__firstShow:
+            self.__splitter.restoreState(
+                Preferences.getUI("PreviewSplitterState"))
+            self.__firstShow = False
+        self.__typingTimer.start()
+    
+    def hide(self):
+        """
+        Public method to hide the preview widget.
+        """
+        super().hide()
+        self.__typingTimer.stop()
+    
+    def shutdown(self):
+        """
+        Public method to perform shutdown actions.
+        """
+        self.__typingTimer.stop()
+        self.__htmlPreviewer and self.__htmlPreviewer.shutdown()
+    
+    def __splitterMoved(self):
+        """
+        Private slot to handle the movement of the embedding splitter's handle.
+        """
+        state = self.__splitter.saveState()
+        Preferences.setUI("PreviewSplitterState", state)
+    
+    def __editorChanged(self, editor):
+        """
+        Private slot to handle a change of the current editor.
+        
+        @param editor reference to the editor (Editor)
+        """
+        if editor is None:
+            self.hide()
+            return
+        
+        if (
+            Preferences.getUI("ShowFilePreview") and
+            self.__isPreviewable(editor)
+        ):
+            self.show()
+            self.__processEditor()
+        else:
+            self.hide()
+    
+    def __editorLanguageChanged(self, editor):
+        """
+        Private slot to handle a change of the current editor's language.
+        
+        @param editor reference to the editor (Editor)
+        """
+        self.__editorChanged(editor)
+    
+    def __editorTextChanged(self, editor):
+        """
+        Private slot to handle changes of an editor's text.
+        
+        @param editor reference to the editor (Editor)
+        """
+        if self.isVisible():
+            self.__typingTimer.stop()
+            self.__typingTimer.start()
+    
+    def __previewStateChanged(self, on):
+        """
+        Private slot to toggle the display of the preview.
+        
+        @param on flag indicating to show a preview (boolean)
+        """
+        editor = self.__vm.activeWindow()
+        if on and editor and self.__isPreviewable(editor):
+            self.show()
+        else:
+            self.hide()
+    
+    def __isPreviewable(self, editor):
+        """
+        Private method to check, if a preview can be shown for the given
+        editor.
+        
+        @param editor reference to an editor (Editor)
+        @return flag indicating if a preview can be shown (boolean)
+        """
+        if editor:
+            if bool(editor.getFileName()):
+                extension = os.path.normcase(
+                    os.path.splitext(editor.getFileName())[1][1:])
+                return extension in (
+                    Preferences.getEditor("PreviewHtmlFileNameExtensions") +
+                    Preferences.getEditor(
+                        "PreviewMarkdownFileNameExtensions") +
+                    Preferences.getEditor("PreviewRestFileNameExtensions") +
+                    Preferences.getEditor("PreviewQssFileNameExtensions")
+                )
+            elif editor.getLanguage().lower() in [
+                    "html", "markdown", "restructuredtext", "qss"]:
+                return True
+        
+        return False
+    
+    def __processEditor(self):
+        """
+        Private slot to schedule the processing of the current editor's text.
+        """
+        self.__typingTimer.stop()
+        
+        editor = self.__vm.activeWindow()
+        if editor is not None:
+            fn = editor.getFileName()
+            
+            if fn:
+                extension = os.path.normcase(os.path.splitext(fn)[1][1:])
+            else:
+                extension = ""
+            if (
+                extension in Preferences.getEditor(
+                    "PreviewHtmlFileNameExtensions") or
+                editor.getLanguage().lower() == "html"
+            ):
+                language = "HTML"
+            elif (
+                extension in Preferences.getEditor(
+                    "PreviewMarkdownFileNameExtensions") or
+                editor.getLanguage().lower() == "markdown"
+            ):
+                language = "Markdown"
+            elif (
+                extension in Preferences.getEditor(
+                    "PreviewRestFileNameExtensions") or
+                editor.getLanguage().lower() == "restructuredtext"
+            ):
+                language = "ReST"
+            elif (
+                extension in Preferences.getEditor(
+                    "PreviewQssFileNameExtensions") or
+                editor.getLanguage().lower() == "qss"
+            ):
+                language = "QSS"
+            else:
+                language = ""
+            
+            if language in ["HTML", "Markdown", "ReST"]:
+                if self.__htmlPreviewer is None:
+                    from .Previewers.PreviewerHTML import PreviewerHTML
+                    self.__htmlPreviewer = PreviewerHTML()
+                    self.addWidget(self.__htmlPreviewer)
+                self.setCurrentWidget(self.__htmlPreviewer)
+                self.__htmlPreviewer.processEditor(editor)
+            elif language == "QSS":
+                if self.__qssPreviewer is None:
+                    from .Previewers.PreviewerQSS import PreviewerQSS
+                    self.__qssPreviewer = PreviewerQSS()
+                    self.addWidget(self.__qssPreviewer)
+                self.setCurrentWidget(self.__qssPreviewer)
+                self.__qssPreviewer.processEditor(editor)

eric ide

mercurial