src/eric7/QtHelpInterface/HelpDocsInstaller.py

branch
eric7
changeset 9686
2eee7a645cba
parent 9653
e67609152c5e
child 10192
f457742dd3d6
diff -r b43e04854aba -r 2eee7a645cba src/eric7/QtHelpInterface/HelpDocsInstaller.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/QtHelpInterface/HelpDocsInstaller.py	Mon Jan 09 11:22:56 2023 +0100
@@ -0,0 +1,322 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009 - 2023 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 QLibraryInfo, QMutex, QThread, pyqtSignal
+from PyQt6.QtHelp import QHelpEngineCore
+
+from eric7.Globals import getConfig
+from eric7.SystemUtilities import QtUtilities
+
+
+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",
+            "qthttpserver",
+            "qtimageformats",
+            "qtlabscalendar",
+            "qtlabsplatform",
+            "qtlabscontrols",
+            "qtlinguist",
+            "qtlocation",
+            "qtlottieanimation",
+            "qtmacextras",
+            "qtmultimedia",
+            "qtmultimediawidgets",
+            "qtnetwork",
+            "qtnetworkauth",
+            "qtnfc",
+            "qtopengl",
+            "qtpdf",
+            "qtplatformheaders",
+            "qtpositioning",
+            "qtprintsupport",
+            "qtpurchasing",
+            "qtqml",
+            "qtqmlcore",
+            "qtqmlmodels",
+            "qtqmltest",
+            "qtqmlworkerscript",
+            "qtqmlxmllistmodel",
+            "qtquick",
+            "qtquick3d",
+            "qtquick3dphysics",
+            "qtquickcontrols",
+            "qtquickcontrols1",
+            "qtquickdialogs",
+            "qtquickextras",
+            "qtquicklayouts",
+            "qtquicktimeline",
+            "qtremoteobjects",
+            "qtscript",
+            "qtscripttools",
+            "qtscxml",
+            "qtsensors",
+            "qtserialbus",
+            "qtserialport",
+            "qtshadertools",
+            "qtspatialaudio",
+            "qtspeech",
+            "qtsql",
+            "qtstatemachine",
+            "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(*QtUtilities.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