eric6/WebBrowser/QtHelp/HelpDocsInstaller.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7195
6b53960ff598
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2019 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 from __future__ import unicode_literals
12
13 import os
14
15 from PyQt5.QtCore import pyqtSignal, QThread, Qt, QMutex, QDateTime, QDir, \
16 QLibraryInfo, QFileInfo
17 from PyQt5.QtHelp import QHelpEngineCore
18
19 from eric6config import getConfig
20
21 from Globals import qVersionTuple
22
23
24 class HelpDocsInstaller(QThread):
25 """
26 Class implementing the worker thread populating and updating the QtHelp
27 documentation database.
28
29 @signal errorMessage(str) emitted, if an error occurred during
30 the installation of the documentation
31 @signal docsInstalled(bool) emitted after the installation has finished
32 """
33 errorMessage = pyqtSignal(str)
34 docsInstalled = pyqtSignal(bool)
35
36 def __init__(self, collection):
37 """
38 Constructor
39
40 @param collection full pathname of the collection file (string)
41 """
42 super(HelpDocsInstaller, self).__init__()
43
44 self.__abort = False
45 self.__collection = collection
46 self.__mutex = QMutex()
47
48 def stop(self):
49 """
50 Public slot to stop the installation procedure.
51 """
52 if not self.isRunning():
53 return
54
55 self.__mutex.lock()
56 self.__abort = True
57 self.__mutex.unlock()
58 self.wait()
59
60 def installDocs(self):
61 """
62 Public method to start the installation procedure.
63 """
64 self.start(QThread.LowPriority)
65
66 def run(self):
67 """
68 Public method executed by the thread.
69 """
70 engine = QHelpEngineCore(self.__collection)
71 changes = False
72
73 qt4Docs = ["designer", "linguist", "qt"]
74 qt5Docs = [
75 "activeqt", "qdoc", "qmake", "qt3d", "qt3drenderer",
76 "qtandroidextras", "qtassistant", "qtbluetooth", "qtcanvas3d",
77 "qtconcurrent", "qtcore", "qtdbus", "qtdesigner", "qtdoc",
78 "qtenginio", "qtenginiooverview", "qtenginoqml",
79 "qtgraphicaleffects", "qtgui", "qthelp", "qtimageformats",
80 "qtlabscontrols", "qtlinguist", "qtlocation", "qtmaxextras",
81 "qtmultimedia", "qtmultimediawidgets", "qtnetwork", "qtnfc",
82 "qtopengl", "qtplatformheaders", "qtpositioning", "qtprintsupport",
83 "qtqml", "qtquick", "qtquickcontrols", "qtquickdialogs",
84 "qtquickextras", "qtquicklayouts", "qtscript", "qtscripttools",
85 "qtsensors", "qtserialbus", "qtserialport", "qtsql", "qtsvg",
86 "qttestlib", "qtuitools", "qtwebchannel", "qtwebengine",
87 "qtwebenginewidgets", "qtwebkit", "qtwebkitexamples",
88 "qtwebsockets", "qtwebview", "qtwidgets", "qtwinextras",
89 "qtx11extras", "qtxml", "qtxmlpatterns"]
90 for qtDocs, version in [(qt4Docs, 4), (qt5Docs, 5)]:
91 for doc in qtDocs:
92 changes |= self.__installQtDoc(doc, version, engine)
93 self.__mutex.lock()
94 if self.__abort:
95 engine = None
96 self.__mutex.unlock()
97 return
98 self.__mutex.unlock()
99
100 changes |= self.__installEric6Doc(engine)
101 engine = None
102 del engine
103 self.docsInstalled.emit(changes)
104
105 def __installQtDoc(self, name, version, engine):
106 """
107 Private method to install/update a Qt help document.
108
109 @param name name of the Qt help document (string)
110 @param version Qt version of the help documens (integer)
111 @param engine reference to the help engine (QHelpEngineCore)
112 @return flag indicating success (boolean)
113 """
114 versionKey = "qt_version_{0}@@{1}".format(version, name)
115 info = engine.customValue(versionKey, "")
116 lst = info.split('|')
117
118 dt = QDateTime()
119 if len(lst) and lst[0]:
120 dt = QDateTime.fromString(lst[0], Qt.ISODate)
121
122 qchFile = ""
123 if len(lst) == 2:
124 qchFile = lst[1]
125
126 if version == 4:
127 docsPath = QDir(
128 QLibraryInfo.location(QLibraryInfo.DocumentationPath) +
129 QDir.separator() + "qch")
130 elif version == 5:
131 docsPath = QLibraryInfo.location(QLibraryInfo.DocumentationPath)
132 if not os.path.isdir(docsPath) or \
133 len(QDir(docsPath).entryList(["*.qch"])) == 0:
134 # Qt installer is a bit buggy; it's missing a symbolic link
135 docsPathList = QDir.fromNativeSeparators(docsPath).split("/")
136 docsPath = os.sep.join(
137 docsPathList[:-3] +
138 ["Docs", "Qt-{0}.{1}".format(*qVersionTuple())])
139 docsPath = QDir(docsPath)
140 else:
141 # unsupported Qt version
142 return False
143
144 files = docsPath.entryList(["*.qch"])
145 if not files:
146 engine.setCustomValue(
147 versionKey,
148 QDateTime().toString(Qt.ISODate) + '|')
149 return False
150
151 for f in files:
152 if f.startswith(name + "."):
153 fi = QFileInfo(docsPath.absolutePath() + QDir.separator() + f)
154 namespace = QHelpEngineCore.namespaceName(
155 fi.absoluteFilePath())
156 if not namespace:
157 continue
158
159 if dt.isValid() and \
160 namespace in engine.registeredDocumentations() and \
161 fi.lastModified().toString(Qt.ISODate) == \
162 dt.toString(Qt.ISODate) and \
163 qchFile == fi.absoluteFilePath():
164 return False
165
166 if namespace in engine.registeredDocumentations():
167 engine.unregisterDocumentation(namespace)
168
169 if not engine.registerDocumentation(fi.absoluteFilePath()):
170 self.errorMessage.emit(
171 self.tr(
172 """<p>The file <b>{0}</b> could not be"""
173 """ registered. <br/>Reason: {1}</p>""")
174 .format(fi.absoluteFilePath, engine.error())
175 )
176 return False
177
178 engine.setCustomValue(
179 versionKey,
180 fi.lastModified().toString(Qt.ISODate) + '|' +
181 fi.absoluteFilePath())
182 return True
183
184 return False
185
186 def __installEric6Doc(self, engine):
187 """
188 Private method to install/update the eric6 help documentation.
189
190 @param engine reference to the help engine (QHelpEngineCore)
191 @return flag indicating success (boolean)
192 """
193 versionKey = "eric6_ide"
194 info = engine.customValue(versionKey, "")
195 lst = info.split('|')
196
197 dt = QDateTime()
198 if len(lst) and lst[0]:
199 dt = QDateTime.fromString(lst[0], Qt.ISODate)
200
201 qchFile = ""
202 if len(lst) == 2:
203 qchFile = lst[1]
204
205 docsPath = QDir(getConfig("ericDocDir") + QDir.separator() + "Help")
206
207 files = docsPath.entryList(["*.qch"])
208 if not files:
209 engine.setCustomValue(
210 versionKey, QDateTime().toString(Qt.ISODate) + '|')
211 return False
212
213 for f in files:
214 if f == "source.qch":
215 fi = QFileInfo(docsPath.absolutePath() + QDir.separator() + f)
216 namespace = QHelpEngineCore.namespaceName(
217 fi.absoluteFilePath())
218 if not namespace:
219 continue
220
221 if dt.isValid() and \
222 namespace in engine.registeredDocumentations() and \
223 fi.lastModified().toString(Qt.ISODate) == \
224 dt.toString(Qt.ISODate) and \
225 qchFile == fi.absoluteFilePath():
226 return False
227
228 if namespace in engine.registeredDocumentations():
229 engine.unregisterDocumentation(namespace)
230
231 if not engine.registerDocumentation(fi.absoluteFilePath()):
232 self.errorMessage.emit(
233 self.tr(
234 """<p>The file <b>{0}</b> could not be"""
235 """ registered. <br/>Reason: {1}</p>""")
236 .format(fi.absoluteFilePath, engine.error())
237 )
238 return False
239
240 engine.setCustomValue(
241 versionKey,
242 fi.lastModified().toString(Qt.ISODate) + '|' +
243 fi.absoluteFilePath())
244 return True
245
246 return False

eric ide

mercurial