eric7/HelpViewer/HelpViewerImpl_qtb.py

Fri, 15 Oct 2021 20:09:38 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 15 Oct 2021 20:09:38 +0200
branch
eric7
changeset 8689
da40117c42d6
parent 8683
e8a907801549
child 8693
d51660d6f1b9
permissions
-rw-r--r--

Implemented some keyboard zoom actions and zooming via a pinch gesture for the QTextBrowser based help viewer.

# -*- coding: utf-8 -*-

# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the QTextBrowser based help viewer class.
"""

from PyQt6.QtCore import Qt, QByteArray, QUrl, QEvent
from PyQt6.QtGui import QDesktopServices,  QImage
from PyQt6.QtWidgets import QTextBrowser

from .HelpViewerImpl import HelpViewerImpl


class HelpViewerImpl_qtb(HelpViewerImpl, QTextBrowser):
    """
    Class implementing the QTextBrowser based help viewer class.
    """
    def __init__(self, engine, parent=None):
        """
        Constructor
        
        @param engine reference to the help engine
        @type QHelpEngine
        @param parent reference to the parent widget
        @type QWidget
        """
        QTextBrowser.__init__(self,  parent=parent)
        HelpViewerImpl.__init__(self, engine)
        
        self.__zoomCount = 0
        
        self.sourceChanged.connect(self.titleChanged)
        
        self.grabGesture(Qt.GestureType.PinchGesture)
    
    def setUrl(self, url):
        """
        Public method to set the URL of the document to be shown.
        
        @param url source of the document
        @type QUrl
        """
        self.setSource(url)
    
    def url(self):
        """
        Public method to get the URL of the shown document.
        
        @return url URL of the document
        @rtype QUrl
        """
        return self.source()
    
    def doSetSource(self, url, type):
        """
        Public method to load the data and show it.
        
        @param url DESCRIPTION
        @type TYPE
        @param type DESCRIPTION
        @type TYPE
        """
        data = self.getData(url)
        if data is None:
            QDesktopServices.openUrl(url)
            return
        
        if url != QUrl("about:blank"):
            super().doSetSource(url, type)
        
        self.setHtml(data)
        self.sourceChanged.emit(url)
        self.loadFinished.emit(True)
    
    def title(self):
        """
        Public method get the page title.
        
        @return page title
        @rtype str
        """
        return self.documentTitle()
    
    def loadResource(self, type_,  name):
        """
        Public method to load data of the specified type from the resource with
        the given name.
        
        @param type_ resource type
        @type int
        @param name resource name
        @type QUrl
        """
        ba = QByteArray()
        
        if type_ < 4:     # QTextDocument.ResourceType.MarkdownResource
            url = self._engine.findFile(name)
            ba = self._engine.fileData(url)
            if url.toString().lower().endswith(".svg"):
                image = QImage()
                image.loadFromData(ba, "svg")
                if not image.isNull():
                    return image
        
        return ba
    
    def mousePressEvent(self, evt):
        """
        Protected method called by a mouse press event.
        
        @param evt reference to the mouse event
        @type QMouseEvent
        """
        if evt.button() == Qt.MouseButton.XButton1:
            self.backward()
        elif evt.button() == Qt.MouseButton.XButton2:
            self.forward()
        else:
            super().mousePressEvent(evt)
    
    def gotoHistory(self, index):
        """
        Public method to step through the history.
        
        @param index history index (<0 backward, >0 forward)
        @type int
        """
        if index < 0:
            # backward
            for ind in range(-index):
                self.backward()
        else:
            # forward
            for ind in range(index):
                self.forward()
    
    def scaleUp(self):
        """
        Public method to zoom in.
        """
        if self.__zoomCount < 10:
            self.__zoomCount += 1
            self.zoomIn()
            self.zoomChanged.emit()
    
    def scaleDown(self):
        """
        Public method to zoom out.
        """
        if self.__zoomCount > -5:
            self.__zoomCount -= 1
            self.zoomOut()
            self.zoomChanged.emit()
    
    def setScale(self, scale):
        """
        Public method to set the zoom level.
        
        @param scale zoom level to set
        @type int
        """
        if -5 <= scale <= 10:
            self.zoomOut(scale)
            self.__zoomCount = scale
            self.zoomChanged.emit()
    
    def resetScale(self):
        """
        Public method to reset the zoom level.
        """
        if self.__zoomCount != 0:
            self.zoomOut(self.__zoomCount)
            self.zoomChanged.emit()
        self.__zoomCount = 0
    
    def scale(self):
        """
        Public method to get the zoom level.
        
        @return current zoom level
        @rtype int
        """
        return self.__zoomCount
    
    def isScaleUpAvailable(self):
        """
        Public method to check, if the max. zoom level is reached.
        
        @return flag indicating scale up is available
        @rtype bool
        """
        return self.__zoomCount < 10
    
    def isScaleDownAvailable(self):
        """
        Public method to check, if the min. zoom level is reached.
        
        @return flag indicating scale down is available
        @rtype bool
        """
        return self.__zoomCount > -5
    
    def wheelEvent(self, evt):
        """
        Public method to handle wheel event to zoom.
        
        @param evt reference to the event object
        @type QWheelEvent
        """
        if evt.modifiers() == Qt.KeyboardModifier.ControlModifier:
            if evt.angleDelta().y() > 0:
                self.scaleUp()
            else:
                self.scaleDown()
            evt.accept()
        else:
            QTextBrowser.wheelEvent(self, evt)
    
    def keyPressEvent(self, evt):
        """
        Public method to handle key press events.
        
        @param evt reference to the key event
        @type QKeyEvent
        """
        if evt.key() == Qt.Key.Key_ZoomIn:
            self.scaleUp()
            evt.accept()
        elif evt.key() == Qt.Key.Key_ZoomOut:
            self.scaleDown()
            evt.accept()
        elif evt.key() == Qt.Key.Key_Plus:
            if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
                self.scaleUp()
                evt.accept()
        elif evt.key() == Qt.Key.Key_Minus:
            if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
                self.scaleDown()
                evt.accept()
        elif evt.key() == Qt.Key.Key_0:
            if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
                self.resetScale()
                evt.accept()
        elif evt.key() == Qt.Key.Key_Backspace:
            self.backward()
            evt.accept()
    
    def event(self, evt):
        """
        Public method handling events.
        
        @param evt reference to the event
        @type QEvent
        @return flag indicating the event was handled
        @rtype bool
        """
        if evt.type() == QEvent.Type.Gesture:
            self.gestureEvent(evt)    
            return True
        
        return super().event(evt)
    
    def gestureEvent(self, evt):
        """
        Protected method handling gesture events.
        
        @param evt reference to the gesture event
        @type QGestureEvent
        """
        pinch = evt.gesture(Qt.GestureType.PinchGesture)
        if pinch:
            if pinch.state() == Qt.GestureState.GestureStarted:
                zoom = (self.getZoom() + 6) / 10.0
                pinch.setTotalScaleFactor(zoom)
            elif pinch.state() == Qt.GestureState.GestureUpdated:
                zoom = int(pinch.totalScaleFactor() * 10) - 6
                if zoom <= -5:
                    zoom = -5
                    pinch.setTotalScaleFactor(0.1)
                elif zoom >= 10:
                    zoom = 10
                    pinch.setTotalScaleFactor(1.6)
                self.setScale(zoom)
            evt.accept()
    
    # TODO: implement context menu
    #       - Open Link
    #       - Open Link in New Page
    #       - Open Link in Background Page
    #       - Copy
    #       - Copy Link LOcation
    #       - Select All
    # TODO: add Ctrl+LMB action (open link in new page)

eric ide

mercurial