src/eric7/WebBrowser/QtHelp/HelpDocsInstaller.py

Tue, 18 Oct 2022 16:06:21 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 18 Oct 2022 16:06:21 +0200
branch
eric7
changeset 9413
80c06d472826
parent 9286
f6f950e4c8f0
child 9448
ea215f7afab3
permissions
-rw-r--r--

Changed the eric7 import statements to include the package name (i.e. eric7) in order to not fiddle with sys.path.

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

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

"""
Module implementing a thread class populating and updating the QtHelp
documentation database.
"""

import datetime
import pathlib

from PyQt6.QtCore import pyqtSignal, QThread, QMutex, QLibraryInfo
from PyQt6.QtHelp import QHelpEngineCore

from eric7config import getConfig

from eric7.Globals import qVersionTuple


class HelpDocsInstaller(QThread):
    """
    Class implementing the worker thread populating and updating the QtHelp
    documentation database.

    @signal errorMessage(str) emitted, if an error occurred during
        the installation of the documentation
    @signal docsInstalled(bool) emitted after the installation has finished
    """

    errorMessage = pyqtSignal(str)
    docsInstalled = pyqtSignal(bool)

    def __init__(self, collection):
        """
        Constructor

        @param collection full pathname of the collection file
        @type str
        """
        super().__init__()

        self.__abort = False
        self.__collection = collection
        self.__mutex = QMutex()

    def stop(self):
        """
        Public slot to stop the installation procedure.
        """
        if not self.isRunning():
            return

        self.__mutex.lock()
        self.__abort = True
        self.__mutex.unlock()
        self.wait()

    def installDocs(self):
        """
        Public method to start the installation procedure.
        """
        self.start(QThread.Priority.LowPriority)

    def run(self):
        """
        Public method executed by the thread.
        """
        engine = QHelpEngineCore(self.__collection)
        changes = False

        qt5Docs = [
            "activeqt",
            "qdoc",
            "qmake",
            "qt3d",
            "qt3drenderer",
            "qtandroidextras",
            "qtassistant",
            "qtbluetooth",
            "qtcanvas3d",
            "qtcharts",
            "qtcmake",
            "qtconcurrent",
            "qtcore",
            "qtdatavis3d",
            "qtdatavisualization",
            "qtdbus",
            "qtdesigner",
            "qtdistancefieldgenerator",
            "qtdoc",
            "qtenginio",
            "qtenginiooverview",
            "qtenginoqml",
            "qtgamepad",
            "qtgraphicaleffects",
            "qtgui",
            "qthelp",
            "qtimageformats",
            "qtlabscalendar",
            "qtlabsplatform",
            "qtlabscontrols",
            "qtlinguist",
            "qtlocation",
            "qtlottieanimation",
            "qtmaxextras",
            "qtmultimedia",
            "qtmultimediawidgets",
            "qtnetwork",
            "qtnetworkauth",
            "qtnfc",
            "qtopengl",
            "qtplatformheaders",
            "qtpositioning",
            "qtprintsupport",
            "qtpurchasing",
            "qtqml",
            "qtqmlmodels",
            "qtqmltest",
            "qtquick",
            "qtquick3d",
            "qtquickcontrols",
            "qtquickcontrols1",
            "qtquickdialogs",
            "qtquickextras",
            "qtquicklayouts",
            "qtquicktimeline",
            "qtremoteobjects",
            "qtscript",
            "qtscripttools",
            "qtscxml",
            "qtsensors",
            "qtserialbus",
            "qtserialport",
            "qtshadertools",
            "qtspeech",
            "qtsql",
            "qtsvg",
            "qttest",
            "qttestlib",
            "qtuitools",
            "qtvirtualkeyboard",
            "qtwaylandcompositor",
            "qtwebchannel",
            "qtwebengine",
            "qtwebenginewidgets",
            "qtwebkit",
            "qtwebkitexamples",
            "qtwebsockets",
            "qtwebview",
            "qtwidgets",
            "qtwinextras",
            "qtx11extras",
            "qtxml",
            "qtxmlpatterns",
        ]
        for qtDocs, version in [(qt5Docs, 5)]:
            for doc in qtDocs:
                changes |= self.__installQtDoc(doc, version, engine)
                self.__mutex.lock()
                if self.__abort:
                    engine = None
                    self.__mutex.unlock()
                    return
                self.__mutex.unlock()

        changes |= self.__installEric7Doc(engine)
        engine = None
        del engine
        self.docsInstalled.emit(changes)

    def __installQtDoc(self, name, version, engine):
        """
        Private method to install/update a Qt help document.

        @param name name of the Qt help document
        @type str
        @param version Qt version of the help documents
        @type int
        @param engine reference to the help engine
        @type QHelpEngineCore
        @return flag indicating success
        @rtype bool
        """
        versionKey = "qt_version_{0}@@{1}".format(version, name)
        info = engine.customValue(versionKey, "")
        lst = info.split("|")

        dt = None
        if len(lst) and lst[0]:
            dt = datetime.datetime.fromisoformat(lst[0])

        qchFile = ""
        if len(lst) == 2:
            qchFile = lst[1]

        if version == 5:
            docsPath = pathlib.Path(
                QLibraryInfo.path(QLibraryInfo.LibraryPath.DocumentationPath)
            )
            if not docsPath.is_dir() or len(list(docsPath.glob("*.qch"))) == 0:
                docsPath = (
                    docsPath.parents[2] / "Docs" / "Qt-{0}.{1}".format(*qVersionTuple())
                )
        else:
            # unsupported Qt version
            return False

        files = list(docsPath.glob("*.qch"))
        if not files:
            engine.setCustomValue(versionKey, "|")
            return False

        for f in files:
            if f.stem == name:
                namespace = QHelpEngineCore.namespaceName(str(f.resolve()))
                if not namespace:
                    continue

                if (
                    dt is not None
                    and namespace in engine.registeredDocumentations()
                    and (datetime.datetime.fromtimestamp(f.stat().st_mtime) == dt)
                    and qchFile == str(f.resolve())
                ):
                    return False

                if namespace in engine.registeredDocumentations():
                    engine.unregisterDocumentation(namespace)

                if not engine.registerDocumentation(str(f.resolve())):
                    self.errorMessage.emit(
                        self.tr(
                            """<p>The file <b>{0}</b> could not be"""
                            """ registered. <br/>Reason: {1}</p>"""
                        ).format(f, engine.error())
                    )
                    return False

                engine.setCustomValue(
                    versionKey,
                    datetime.datetime.fromtimestamp(f.stat().st_mtime).isoformat()
                    + "|"
                    + str(f.resolve()),
                )
                return True

        return False

    def __installEric7Doc(self, engine):
        """
        Private method to install/update the eric help documentation.

        @param engine reference to the help engine
        @type QHelpEngineCore
        @return flag indicating success
        @rtype bool
        """
        versionKey = "eric7_ide"
        info = engine.customValue(versionKey, "")
        lst = info.split("|")

        dt = None
        if len(lst) and lst[0]:
            dt = datetime.datetime.fromisoformat(lst[0])

        qchFile = ""
        if len(lst) == 2:
            qchFile = lst[1]

        docsPath = pathlib.Path(getConfig("ericDocDir")) / "Help"

        files = list(docsPath.glob("*.qch"))
        if not files:
            engine.setCustomValue(versionKey, "|")
            return False

        for f in files:
            if f.name == "source.qch":
                namespace = QHelpEngineCore.namespaceName(str(f.resolve()))
                if not namespace:
                    continue

                if (
                    dt is not None
                    and namespace in engine.registeredDocumentations()
                    and (datetime.datetime.fromtimestamp(f.stat().st_mtime) == dt)
                    and qchFile == str(f.resolve())
                ):
                    return False

                if namespace in engine.registeredDocumentations():
                    engine.unregisterDocumentation(namespace)

                if not engine.registerDocumentation(str(f.resolve())):
                    self.errorMessage.emit(
                        self.tr(
                            """<p>The file <b>{0}</b> could not be"""
                            """ registered. <br/>Reason: {1}</p>"""
                        ).format(f, engine.error())
                    )
                    return False

                engine.setCustomValue(
                    versionKey,
                    datetime.datetime.fromtimestamp(f.stat().st_mtime).isoformat()
                    + "|"
                    + str(f.resolve()),
                )
                return True

        return False

eric ide

mercurial