eric6/Helpviewer/HelpDocsInstaller.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
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 engine.setupData()
72 changes = False
73
74 qt4Docs = ["designer", "linguist", "qt"]
75 qt5Docs = [
76 "activeqt", "qdoc", "qmake", "qt3d", "qt3drenderer",
77 "qtandroidextras", "qtassistant", "qtbluetooth", "qtcanvas3d",
78 "qtconcurrent", "qtcore", "qtdbus", "qtdesigner", "qtdoc",
79 "qtenginio", "qtenginiooverview", "qtenginoqml",
80 "qtgraphicaleffects", "qtgui", "qthelp", "qtimageformats",
81 "qtlabscontrols", "qtlinguist", "qtlocation", "qtmaxextras",
82 "qtmultimedia", "qtmultimediawidgets", "qtnetwork", "qtnfc",
83 "qtopengl", "qtplatformheaders", "qtpositioning", "qtprintsupport",
84 "qtqml", "qtquick", "qtquickcontrols", "qtquickdialogs",
85 "qtquickextras", "qtquicklayouts", "qtscript", "qtscripttools",
86 "qtsensors", "qtserialbus", "qtserialport", "qtsql", "qtsvg",
87 "qttestlib", "qtuitools", "qtwebchannel", "qtwebengine",
88 "qtwebenginewidgets", "qtwebkit", "qtwebkitexamples",
89 "qtwebsockets", "qtwebview", "qtwidgets", "qtwinextras",
90 "qtx11extras", "qtxml", "qtxmlpatterns"]
91 for qtDocs, version in [(qt4Docs, 4), (qt5Docs, 5)]:
92 for doc in qtDocs:
93 changes |= self.__installQtDoc(doc, version, engine)
94 self.__mutex.lock()
95 if self.__abort:
96 engine = None
97 self.__mutex.unlock()
98 return
99 self.__mutex.unlock()
100
101 changes |= self.__installEric6Doc(engine)
102 engine = None
103 del engine
104 self.docsInstalled.emit(changes)
105
106 def __installQtDoc(self, name, version, engine):
107 """
108 Private method to install/update a Qt help document.
109
110 @param name name of the Qt help document (string)
111 @param version Qt version of the help documens (integer)
112 @param engine reference to the help engine (QHelpEngineCore)
113 @return flag indicating success (boolean)
114 """
115 versionKey = "qt_version_{0}@@{1}".format(version, name)
116 info = engine.customValue(versionKey, "")
117 lst = info.split('|')
118
119 dt = QDateTime()
120 if len(lst) and lst[0]:
121 dt = QDateTime.fromString(lst[0], Qt.ISODate)
122
123 qchFile = ""
124 if len(lst) == 2:
125 qchFile = lst[1]
126
127 if version == 4:
128 docsPath = QDir(
129 QLibraryInfo.location(QLibraryInfo.DocumentationPath) +
130 QDir.separator() + "qch")
131 elif version == 5:
132 docsPath = QLibraryInfo.location(QLibraryInfo.DocumentationPath)
133 if not os.path.isdir(docsPath) or \
134 len(QDir(docsPath).entryList(["*.qch"])) == 0:
135 # Qt installer is a bit buggy; it's missing a symbolic link
136 docsPathList = QDir.fromNativeSeparators(docsPath).split("/")
137 docsPath = os.sep.join(
138 docsPathList[:-3] +
139 ["Docs", "Qt-{0}.{1}".format(*qVersionTuple())])
140 docsPath = QDir(docsPath)
141 else:
142 # unsupported Qt version
143 return False
144
145 files = docsPath.entryList(["*.qch"])
146 if not files:
147 engine.setCustomValue(
148 versionKey,
149 QDateTime().toString(Qt.ISODate) + '|')
150 return False
151
152 for f in files:
153 if f.startswith(name):
154 fi = QFileInfo(docsPath.absolutePath() + QDir.separator() + f)
155 namespace = QHelpEngineCore.namespaceName(
156 fi.absoluteFilePath())
157 if not namespace:
158 continue
159
160 if dt.isValid() and \
161 namespace in engine.registeredDocumentations() and \
162 fi.lastModified().toString(Qt.ISODate) == \
163 dt.toString(Qt.ISODate) and \
164 qchFile == fi.absoluteFilePath():
165 return False
166
167 if namespace in engine.registeredDocumentations():
168 engine.unregisterDocumentation(namespace)
169
170 if not engine.registerDocumentation(fi.absoluteFilePath()):
171 self.errorMessage.emit(
172 self.tr(
173 """<p>The file <b>{0}</b> could not be"""
174 """ registered. <br/>Reason: {1}</p>""")
175 .format(fi.absoluteFilePath, engine.error())
176 )
177 return False
178
179 engine.setCustomValue(
180 versionKey,
181 fi.lastModified().toString(Qt.ISODate) + '|' +
182 fi.absoluteFilePath())
183 return True
184
185 return False
186
187 def __installEric6Doc(self, engine):
188 """
189 Private method to install/update the eric6 help documentation.
190
191 @param engine reference to the help engine (QHelpEngineCore)
192 @return flag indicating success (boolean)
193 """
194 versionKey = "eric6_ide"
195 info = engine.customValue(versionKey, "")
196 lst = info.split('|')
197
198 dt = QDateTime()
199 if len(lst) and lst[0]:
200 dt = QDateTime.fromString(lst[0], Qt.ISODate)
201
202 qchFile = ""
203 if len(lst) == 2:
204 qchFile = lst[1]
205
206 docsPath = QDir(getConfig("ericDocDir") + QDir.separator() + "Help")
207
208 files = docsPath.entryList(["*.qch"])
209 if not files:
210 engine.setCustomValue(
211 versionKey, QDateTime().toString(Qt.ISODate) + '|')
212 return False
213
214 for f in files:
215 if f == "source.qch":
216 fi = QFileInfo(docsPath.absolutePath() + QDir.separator() + f)
217 if dt.isValid() and \
218 fi.lastModified().toString(Qt.ISODate) == \
219 dt.toString(Qt.ISODate) and \
220 qchFile == fi.absoluteFilePath():
221 return False
222
223 namespace = QHelpEngineCore.namespaceName(
224 fi.absoluteFilePath())
225 if not namespace:
226 continue
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