src/eric7/QtHelpInterface/HelpDocsInstaller.py

branch
eric7
changeset 9686
2eee7a645cba
parent 9653
e67609152c5e
child 10192
f457742dd3d6
equal deleted inserted replaced
9685:b43e04854aba 9686:2eee7a645cba
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a thread class populating and updating the QtHelp
8 documentation database.
9 """
10
11 import datetime
12 import pathlib
13
14 from PyQt6.QtCore import QLibraryInfo, QMutex, QThread, pyqtSignal
15 from PyQt6.QtHelp import QHelpEngineCore
16
17 from eric7.Globals import getConfig
18 from eric7.SystemUtilities import QtUtilities
19
20
21 class HelpDocsInstaller(QThread):
22 """
23 Class implementing the worker thread populating and updating the QtHelp
24 documentation database.
25
26 @signal errorMessage(str) emitted, if an error occurred during
27 the installation of the documentation
28 @signal docsInstalled(bool) emitted after the installation has finished
29 """
30
31 errorMessage = pyqtSignal(str)
32 docsInstalled = pyqtSignal(bool)
33
34 def __init__(self, collection):
35 """
36 Constructor
37
38 @param collection full pathname of the collection file
39 @type str
40 """
41 super().__init__()
42
43 self.__abort = False
44 self.__collection = collection
45 self.__mutex = QMutex()
46
47 def stop(self):
48 """
49 Public slot to stop the installation procedure.
50 """
51 if not self.isRunning():
52 return
53
54 self.__mutex.lock()
55 self.__abort = True
56 self.__mutex.unlock()
57 self.wait()
58
59 def installDocs(self):
60 """
61 Public method to start the installation procedure.
62 """
63 self.start(QThread.Priority.LowPriority)
64
65 def run(self):
66 """
67 Public method executed by the thread.
68 """
69 engine = QHelpEngineCore(self.__collection)
70 changes = False
71
72 qt5Docs = [
73 "activeqt",
74 "qdoc",
75 "qmake",
76 "qt3d",
77 "qt3drenderer",
78 "qtandroidextras",
79 "qtassistant",
80 "qtbluetooth",
81 "qtcanvas3d",
82 "qtcharts",
83 "qtcmake",
84 "qtconcurrent",
85 "qtcore",
86 "qtdatavis3d",
87 "qtdatavisualization",
88 "qtdbus",
89 "qtdesigner",
90 "qtdistancefieldgenerator",
91 "qtdoc",
92 "qtenginio",
93 "qtenginiooverview",
94 "qtenginoqml",
95 "qtgamepad",
96 "qtgraphicaleffects",
97 "qtgui",
98 "qthelp",
99 "qthttpserver",
100 "qtimageformats",
101 "qtlabscalendar",
102 "qtlabsplatform",
103 "qtlabscontrols",
104 "qtlinguist",
105 "qtlocation",
106 "qtlottieanimation",
107 "qtmacextras",
108 "qtmultimedia",
109 "qtmultimediawidgets",
110 "qtnetwork",
111 "qtnetworkauth",
112 "qtnfc",
113 "qtopengl",
114 "qtpdf",
115 "qtplatformheaders",
116 "qtpositioning",
117 "qtprintsupport",
118 "qtpurchasing",
119 "qtqml",
120 "qtqmlcore",
121 "qtqmlmodels",
122 "qtqmltest",
123 "qtqmlworkerscript",
124 "qtqmlxmllistmodel",
125 "qtquick",
126 "qtquick3d",
127 "qtquick3dphysics",
128 "qtquickcontrols",
129 "qtquickcontrols1",
130 "qtquickdialogs",
131 "qtquickextras",
132 "qtquicklayouts",
133 "qtquicktimeline",
134 "qtremoteobjects",
135 "qtscript",
136 "qtscripttools",
137 "qtscxml",
138 "qtsensors",
139 "qtserialbus",
140 "qtserialport",
141 "qtshadertools",
142 "qtspatialaudio",
143 "qtspeech",
144 "qtsql",
145 "qtstatemachine",
146 "qtsvg",
147 "qttest",
148 "qttestlib",
149 "qtuitools",
150 "qtvirtualkeyboard",
151 "qtwaylandcompositor",
152 "qtwebchannel",
153 "qtwebengine",
154 "qtwebenginewidgets",
155 "qtwebkit",
156 "qtwebkitexamples",
157 "qtwebsockets",
158 "qtwebview",
159 "qtwidgets",
160 "qtwinextras",
161 "qtx11extras",
162 "qtxml",
163 "qtxmlpatterns",
164 ]
165 for qtDocs, version in [(qt5Docs, 5)]:
166 for doc in qtDocs:
167 changes |= self.__installQtDoc(doc, version, engine)
168 self.__mutex.lock()
169 if self.__abort:
170 engine = None
171 self.__mutex.unlock()
172 return
173 self.__mutex.unlock()
174
175 changes |= self.__installEric7Doc(engine)
176 engine = None
177 del engine
178 self.docsInstalled.emit(changes)
179
180 def __installQtDoc(self, name, version, engine):
181 """
182 Private method to install/update a Qt help document.
183
184 @param name name of the Qt help document
185 @type str
186 @param version Qt version of the help documents
187 @type int
188 @param engine reference to the help engine
189 @type QHelpEngineCore
190 @return flag indicating success
191 @rtype bool
192 """
193 versionKey = "qt_version_{0}@@{1}".format(version, name)
194 info = engine.customValue(versionKey, "")
195 lst = info.split("|")
196
197 dt = None
198 if len(lst) and lst[0]:
199 dt = datetime.datetime.fromisoformat(lst[0])
200
201 qchFile = ""
202 if len(lst) == 2:
203 qchFile = lst[1]
204
205 if version == 5:
206 docsPath = pathlib.Path(
207 QLibraryInfo.path(QLibraryInfo.LibraryPath.DocumentationPath)
208 )
209 if not docsPath.is_dir() or len(list(docsPath.glob("*.qch"))) == 0:
210 docsPath = (
211 docsPath.parents[2]
212 / "Docs"
213 / "Qt-{0}.{1}".format(*QtUtilities.qVersionTuple())
214 )
215 else:
216 # unsupported Qt version
217 return False
218
219 files = list(docsPath.glob("*.qch"))
220 if not files:
221 engine.setCustomValue(versionKey, "|")
222 return False
223
224 for f in files:
225 if f.stem == name:
226 namespace = QHelpEngineCore.namespaceName(str(f.resolve()))
227 if not namespace:
228 continue
229
230 if (
231 dt is not None
232 and namespace in engine.registeredDocumentations()
233 and (datetime.datetime.fromtimestamp(f.stat().st_mtime) == dt)
234 and qchFile == str(f.resolve())
235 ):
236 return False
237
238 if namespace in engine.registeredDocumentations():
239 engine.unregisterDocumentation(namespace)
240
241 if not engine.registerDocumentation(str(f.resolve())):
242 self.errorMessage.emit(
243 self.tr(
244 """<p>The file <b>{0}</b> could not be"""
245 """ registered. <br/>Reason: {1}</p>"""
246 ).format(f, engine.error())
247 )
248 return False
249
250 engine.setCustomValue(
251 versionKey,
252 datetime.datetime.fromtimestamp(f.stat().st_mtime).isoformat()
253 + "|"
254 + str(f.resolve()),
255 )
256 return True
257
258 return False
259
260 def __installEric7Doc(self, engine):
261 """
262 Private method to install/update the eric help documentation.
263
264 @param engine reference to the help engine
265 @type QHelpEngineCore
266 @return flag indicating success
267 @rtype bool
268 """
269 versionKey = "eric7_ide"
270 info = engine.customValue(versionKey, "")
271 lst = info.split("|")
272
273 dt = None
274 if len(lst) and lst[0]:
275 dt = datetime.datetime.fromisoformat(lst[0])
276
277 qchFile = ""
278 if len(lst) == 2:
279 qchFile = lst[1]
280
281 docsPath = pathlib.Path(getConfig("ericDocDir")) / "Help"
282
283 files = list(docsPath.glob("*.qch"))
284 if not files:
285 engine.setCustomValue(versionKey, "|")
286 return False
287
288 for f in files:
289 if f.name == "source.qch":
290 namespace = QHelpEngineCore.namespaceName(str(f.resolve()))
291 if not namespace:
292 continue
293
294 if (
295 dt is not None
296 and namespace in engine.registeredDocumentations()
297 and (datetime.datetime.fromtimestamp(f.stat().st_mtime) == dt)
298 and qchFile == str(f.resolve())
299 ):
300 return False
301
302 if namespace in engine.registeredDocumentations():
303 engine.unregisterDocumentation(namespace)
304
305 if not engine.registerDocumentation(str(f.resolve())):
306 self.errorMessage.emit(
307 self.tr(
308 """<p>The file <b>{0}</b> could not be"""
309 """ registered. <br/>Reason: {1}</p>"""
310 ).format(f, engine.error())
311 )
312 return False
313
314 engine.setCustomValue(
315 versionKey,
316 datetime.datetime.fromtimestamp(f.stat().st_mtime).isoformat()
317 + "|"
318 + str(f.resolve()),
319 )
320 return True
321
322 return False

eric ide

mercurial